Merge "Add source-rest mapping"
authorDan Timoney <dtimoney@att.com>
Wed, 11 Sep 2019 19:56:15 +0000 (19:56 +0000)
committerGerrit Code Review <gerrit@onap.org>
Wed, 11 Sep 2019 19:56:15 +0000 (19:56 +0000)
116 files changed:
INFO.yaml
cds-ui/application/pom.xml
cds-ui/client/pom.xml
cds-ui/client/src/app/common/constants/app-constants.ts
cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-edit.service.ts
cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-metadata/resource-metadata.component.html
cds-ui/client/src/app/feature-modules/resource-definition/resource-edit/resource-metadata/resource-metadata.component.ts
cds-ui/pom.xml
cds-ui/server/pom.xml
cds-ui/server/src/controllers/data-dictionary.controller.ts
cds-ui/server/src/datasources/resource-dictionary.datasource-template.ts
cds-ui/server/src/services/resource-dictionary.service.ts
components/model-catalog/proto-definition/pom.xml
components/model-catalog/proto-definition/proto/BluePrintCommon.proto
components/parent/pom.xml
components/pom.xml
ms/blueprintsprocessor/application/pom.xml
ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintGRPCServer.java
ms/blueprintsprocessor/application/src/main/resources/application-dev.properties
ms/blueprintsprocessor/application/src/main/resources/application.properties
ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintsAcceptanceTest.kt
ms/blueprintsprocessor/cba-parent/pom.xml
ms/blueprintsprocessor/distribution/pom.xml
ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml
ms/blueprintsprocessor/functions/cli-executor/pom.xml
ms/blueprintsprocessor/functions/config-snapshots/pom.xml
ms/blueprintsprocessor/functions/netconf-executor/pom.xml
ms/blueprintsprocessor/functions/pom.xml
ms/blueprintsprocessor/functions/python-executor/pom.xml
ms/blueprintsprocessor/functions/resource-resolution/pom.xml
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/utils/ResourceAssignmentUtils.kt
ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt
ms/blueprintsprocessor/functions/restconf-executor/pom.xml
ms/blueprintsprocessor/modules/commons/db-lib/pom.xml
ms/blueprintsprocessor/modules/commons/dmaap-lib/pom.xml
ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml
ms/blueprintsprocessor/modules/commons/message-lib/pom.xml
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibConfiguration.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibData.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BluePrintMessageLibPropertyService.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerService.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageConsumerService.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageProducerServiceTest.kt
ms/blueprintsprocessor/modules/commons/message-lib/src/test/resources/logback-test.xml
ms/blueprintsprocessor/modules/commons/pom.xml
ms/blueprintsprocessor/modules/commons/processor-core/pom.xml
ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibData.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BlueprintWebClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/SSLRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/TokenAuthRestClientService.kt
ms/blueprintsprocessor/modules/commons/rest-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BluePrintRestLibPropertyServiceTest.kt
ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml
ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml
ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt [moved from ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandler.kt with 54% similarity]
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelController.kt
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerBlueprintExceptionHandler.kt [moved from ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ControllerBlueprintExceptionHandler.kt with 94% similarity]
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/service/AutoResourceMappingService.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/utils/BluePrintEnhancerUtils.kt
ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandlerTest.kt [moved from ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandlerTest.kt with 86% similarity]
ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt
ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/utils/BluePrintEnhancerUtilsTest.kt
ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/test-cba.zip [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/pom.xml
ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml
ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt [new file with mode: 0644]
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/ExecutionServiceHandler.kt
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/utils/Utils.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/BluePrintProcessingKafkaConsumerTest.kt [new file with mode: 0644]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt [moved from ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt with 72% similarity]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt [deleted file]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt [deleted file]
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_enriched.zip [deleted file]
ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/logback-test.xml [moved from ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/logback.xml with 91% similarity]
ms/blueprintsprocessor/modules/outbounds/pom.xml
ms/blueprintsprocessor/modules/pom.xml
ms/blueprintsprocessor/modules/services/execution-service/pom.xml
ms/blueprintsprocessor/modules/services/pom.xml
ms/blueprintsprocessor/modules/services/workflow-service/pom.xml
ms/blueprintsprocessor/parent/pom.xml
ms/blueprintsprocessor/pom.xml
ms/command-executor/pom.xml
ms/command-executor/src/main/python/command_executor_handler.py
ms/command-executor/src/main/python/server.py
ms/command-executor/src/main/python/utils.py
ms/controllerblueprints/modules/blueprint-core/pom.xml
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/CustomFunctions.kt
ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt [new file with mode: 0644]
ms/controllerblueprints/modules/blueprint-validation/pom.xml
ms/controllerblueprints/modules/blueprint-validation/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/validation/utils/PropertyAssignmentValidationUtils.kt
ms/controllerblueprints/modules/pom.xml
ms/controllerblueprints/modules/resource-dict/pom.xml
ms/controllerblueprints/parent/pom.xml
ms/controllerblueprints/pom.xml
ms/pom.xml
ms/sdclistener/application/pom.xml
ms/sdclistener/distribution/pom.xml
ms/sdclistener/parent/pom.xml
ms/sdclistener/pom.xml
pom.xml
releases/0.6.1.yaml [new file with mode: 0644]
version.properties

index 89c7c13..d07760a 100644 (file)
--- a/INFO.yaml
+++ b/INFO.yaml
@@ -8,7 +8,7 @@ project_lead: &onap_releng_ptl
     email: 'dtimoney@att.com'
     id: 'djtimoney'
     company: 'ATT'
-    timezone: 'America/New York'
+    timezone: 'America/New_York'
 primary_contact: *onap_releng_ptl
 issue_tracking:
     type: 'jira'
@@ -33,12 +33,12 @@ committers:
       email: 'jflucas@research.att.com'
       company: 'ATT'
       id: 'jackl'
-      timezone: 'America/New York'
+      timezone: 'America/New_York'
     - name: 'Jun (Nicolas) Hu'
       email: 'jh245g@att.com'
       company: 'ATT'
       id: 'jh245g'
-      timezone: 'America/New York'
+      timezone: 'America/New_York'
     - name: 'Gaurav Agrawal'
       email: 'gaurav.agrawal@huawei.com'
       company: 'Huawei'
@@ -48,21 +48,9 @@ committers:
       email: 'brindasanth@in.ibm.com'
       company: 'IBM'
       id: 'brindasanthm'
-      timezone: 'America/New York'
+      timezone: 'America/New_York'
 repositories:
-    - ccsdk-apps
-    - ccsdk-cds
-    - ccsdk-distribution
-    - ccsdk-features
-    - ccsdk-parent
-    - ccsdk-platform-blueprints
-    - ccsdk-platform-plugins
-    - ccsdk-sli-adaptors
-    - ccsdk-sli-core
-    - ccsdk-sli-northbound
-    - ccsdk-sli-plugins
-    - ccsdk-storage-esaas
-    - ccsdk-utils
+    - ccsdk/cds
 tsc:
     approval: 'https://lists.onap.org/pipermail/onap-tsc'
     changes:
index 752275a..87cb4f2 100644 (file)
@@ -24,12 +24,12 @@ limitations under the License.
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>ui</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
 
     <artifactId>application</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>cds-ui-application</name>
index 44c7a89..f25e782 100644 (file)
@@ -24,12 +24,12 @@ limitations under the License.
   <parent>
     <groupId>org.onap.ccsdk.cds</groupId>
     <artifactId>ui</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <relativePath>..</relativePath>
   </parent>
 
   <artifactId>ui-client</artifactId>
-  <version>0.6.1-SNAPSHOT</version>
+  <version>0.7.0-SNAPSHOT</version>
   <packaging>pom</packaging>
 
   <name>cds-ui-client</name>
index 5ebde91..78fefd8 100644 (file)
@@ -108,5 +108,6 @@ export const ResourceDictionaryURLs = {
     searchResourceDictionaryByTags: '/resourcedictionary/search',
     searchResourceDictionaryByName: '',
     getSources: '/resourcedictionary/source-mapping',
-    getModelType: '/resourcedictionary/model-type'
+    getModelType: '/resourcedictionary/model-type',
+    getDataType: '/resourcedictionary/model-type/by-definition/data_type'
 }
\ No newline at end of file
index ed1ef6f..f66a1c9 100644 (file)
@@ -44,4 +44,8 @@ export class ResourceEditService {
     getModelType(name) {
         return this.api.get(ResourceDictionaryURLs.getModelType + '/' + name);
     }
+
+    getDataTypes() {
+        return this.api.get(ResourceDictionaryURLs.getDataType);
+    }
 }
\ No newline at end of file
index d40dbd9..24bee27 100644 (file)
@@ -28,8 +28,9 @@
     </mat-form-field>
     <mat-form-field class="form-field">
       <mat-select matInput placeholder="Data Type" formControlName="_type">
-       <mat-option value="string">string</mat-option>
-       <mat-option value="list">list</mat-option>
+       <!-- <mat-option value="string">string</mat-option> -->
+        <!-- <mat-option value="list">list</mat-option> -->
+        <mat-option value="string" *ngFor="let item of dataTypeList">{{item.modelName}}</mat-option>
       </mat-select>
     </mat-form-field>
     <mat-form-field class="form-field" >
index e155ec1..473b200 100644 (file)
@@ -24,13 +24,15 @@ import { Component, OnInit, EventEmitter, Output  } from '@angular/core';
 import {FormBuilder, FormGroup, Validators} from '@angular/forms';
 import { IResources } from 'src/app/common/core/store/models/resources.model';
 import { IResourcesState } from 'src/app/common/core/store/models/resourcesState.model';
-import { Observable } from 'rxjs';
+import { Observable, from } from 'rxjs';
 import { Store } from '@ngrx/store';
 import { IAppState } from '../../../../common/core/store/state/app.state';
 import { A11yModule } from '@angular/cdk/a11y';
+
 import { LoadResourcesSuccess } from 'src/app/common/core/store/actions/resources.action';
 import { IPropertyData } from 'src/app/common/core/store/models/propertyData.model';
 import { IEntrySchema } from 'src/app/common/core/store/models/entrySchema.model';
+import { ResourceEditService } from '../resource-edit.service';
 
 @Component({
   selector: 'app-resource-metadata',
@@ -48,8 +50,13 @@ export class ResourceMetadataComponent implements OnInit {
     propertyValues = [];
     property = [];   
     @Output() resourcesData = new EventEmitter();
+    dataTypeList: any[] = [
+       {modelName: 'String'}, {modelName: 'Boolean'}, {modelName: 'Integer'}, {modelName: 'Float'}, {modelName: 'Double'}
+    ];
      
- constructor(private formBuilder: FormBuilder, private store: Store<IAppState>) { 
+ constructor(private formBuilder: FormBuilder, 
+             private store: Store<IAppState>, 
+             private resourceEditService: ResourceEditService) { 
     this.rdState = this.store.select('resources');
     this.ResourceMetadata = this.formBuilder.group({
         Resource_Name: ['', Validators.required],
@@ -62,6 +69,17 @@ export class ResourceMetadataComponent implements OnInit {
  }
 
  ngOnInit() {
+    this.resourceEditService.getDataTypes()
+    .subscribe(data=>{
+      console.log(data);
+      if(data) {
+         data.forEach(element => {
+            this.dataTypeList.push(element);
+         });
+      }
+    }, (error)=>{
+       console.log("There is an error");
+    });
     this.rdState.subscribe(
       resourcesdata => {
         var resourcesState: IResourcesState = { resources: resourcesdata.resources, isLoadSuccess: resourcesdata.isLoadSuccess, isSaveSuccess: resourcesdata.isSaveSuccess, isUpdateSuccess: resourcesdata.isUpdateSuccess };
index 8c4d241..de2be35 100644 (file)
@@ -24,13 +24,13 @@ limitations under the License.
     <parent>
         <groupId>org.onap.ccsdk.parent</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>1.4.1-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
         <relativePath/>
     </parent>
 
     <groupId>org.onap.ccsdk.cds</groupId>
     <artifactId>ui</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>cds-ui-parent</name>
index 32f68de..2d6d646 100644 (file)
@@ -24,12 +24,12 @@ limitations under the License.
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>ui</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
 
     <artifactId>ui-server</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>cds-ui-server</name>
index 63587e6..eab0bc5 100644 (file)
@@ -95,4 +95,15 @@ export class DataDictionaryController {
   async getmodelType(@param.path.string('source') source: string) {
     return await this.rdservice.getModelType(source);
   }
+
+  @get('/resourcedictionary/model-type/by-definition/data_type', {
+    responses: {
+      '200': {
+        content: { 'application/json': {} },
+      },
+    },
+  })
+  async getDataTypes() {
+    return await this.rdservice.getDataTypes();
+  }
 }
index af96aca..9f9d754 100644 (file)
@@ -88,7 +88,6 @@ export default {
 
             }
         },
-        ,
         {
             "template": {
                 "method": "GET",
@@ -103,6 +102,22 @@ export default {
             "functions": {
                 "getModelType": ["source"]
 
+            }
+        },
+        {
+            "template": {
+                "method": "GET",
+                "url": controllerApiConfig.http.url + "/model-type/by-definition/data_type",
+                "headers": {
+                    "accepts": "application/json",
+                    "content-type": "application/json",
+                    "authorization": controllerApiConfig.http.authToken
+                },
+                "responsePath": "$.*"
+            },
+            "functions": {
+                "getDataTypes": []
+
             }
         }
     ]
index 9a781d6..8df2208 100644 (file)
@@ -9,6 +9,7 @@ export interface ResourceDictionaryService {
   save(resourceDictionary: JSON): Promise<JSON>;
   searchbyNames(resourceDictionaryList: JSON): Promise<JSON>;  
   getModelType(source: string): Promise<JSON>;
+  getDataTypes(): Promise<JSON>;
 }
 
 export class ResourceDictionaryServiceProvider implements Provider<ResourceDictionaryService> {
index e358240..9c6d802 100644 (file)
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../../../</relativePath>
     </parent>
 
     <groupId>org.onap.ccsdk.cds.components</groupId>
     <artifactId>proto-definition</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>jar</packaging>
 
     <name>Controller Blueprints Proto Definition</name>
index 5d1efbd..9b24c50 100644 (file)
@@ -24,7 +24,9 @@ message ActionIdentifiers {
 
 message Status {
   int32 code = 1;
+  // present only if message is failure
   string errorMessage = 2;
+  // This will be success or failure
   string message = 3;
   EventType eventType = 4;
   string timestamp = 5;
index 4ce7e8c..6f33118 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>components</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <groupId>org.onap.ccsdk.cds.components</groupId>
     <artifactId>parent</artifactId>
index 26d609f..060cf4e 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>components</artifactId>
index a4f60f1..64452a0 100755 (executable)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
     <artifactId>application</artifactId>
index 5ad6ee2..9214121 100644 (file)
@@ -18,8 +18,8 @@ package org.onap.ccsdk.cds.blueprintsprocessor;
 
 import io.grpc.Server;
 import io.grpc.ServerBuilder;
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.BluePrintManagementGRPCHandler;
 import org.onap.ccsdk.cds.blueprintsprocessor.security.BasicAuthServerInterceptor;
-import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.BluePrintManagementGRPCHandler;
 import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.BluePrintProcessingGRPCHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
index 019c5aa..2fd5951 100755 (executable)
@@ -99,10 +99,15 @@ blueprintsprocessor.cliExecutor.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
+blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false
+blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t
+blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000
+
+blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageproducer.self-service-api.topic=producer.t
\ No newline at end of file
index 2925b79..37eb87c 100755 (executable)
@@ -92,10 +92,15 @@ blueprintsprocessor.restclient.aai-data.username=aai@aai.onap.org
 blueprintsprocessor.restclient.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
+blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false
+blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t
+blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000
+
+blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageproducer.self-service-api.topic=producer.t
index dfa0a85..ce7434f 100644 (file)
@@ -190,7 +190,7 @@ class BlueprintsAcceptanceTest(private val blueprintName: String, private val fi
         val body = toMultiValueMap("file", getBlueprintAsResource(blueprintName))
         webTestClient
                 .post()
-                .uri("/api/v1/execution-service/upload")
+                .uri("/api/v1/blueprint-model/publish")
                 .header("Authorization", TestSecuritySettings.clientAuthToken())
                 .syncBody(body)
                 .exchange()
index 0ee0da4..a1b6bef 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
     <artifactId>cba-parent</artifactId>
index d6d9c56..4037c98 100755 (executable)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
     <artifactId>distribution</artifactId>
index 96254b7..8b59b17 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>functions</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
index 53882b0..89f409a 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>functions</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
index 0867135..0ad9796 100644 (file)
     <parent>
         <artifactId>functions</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
     <artifactId>config-snapshots</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <name>Blueprints Processor Function - Config Snapshots</name>
     <description>Blueprints Processor Function - Config Snapshots</description>
 
index ff9d0f7..f163c0e 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>functions</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
index c2ac510..73daf22 100755 (executable)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
index 68ba95e..872e5a6 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>functions</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
index 6f2d349..be524fe 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>functions</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
     <artifactId>resource-resolution</artifactId>
index 2a9218d..7696442 100644 (file)
@@ -29,5 +29,4 @@ object ResourceResolutionConstants {
         const val RESOURCE_RESOLUTION_INPUT_OCCURRENCE = "occurrence"
         const val RESOURCE_RESOLUTION_INPUT_RESOURCE_ID = "resource-id"
         const val RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE = "resource-type"
-        val DATA_DICTIONARY_SECRET_SOURCE_TYPES = arrayOf("vault-data") //Add more secret data dictionary source type here
 }
\ No newline at end of file
index 641175c..51170a9 100644 (file)
@@ -28,6 +28,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.proc
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceDefinitionUtils.createResourceAssignments
 import org.onap.ccsdk.cds.controllerblueprints.core.*
+import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
@@ -151,7 +152,9 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                 ResourceAssignmentUtils.generateResourceDataForAssignments(resourceAssignments.toList())
 
         resolvedContent = blueprintTemplateService.generateContent(bluePrintRuntimeService, nodeTemplateName,
-                artifactTemplate, resolvedParamJsonContent)
+                artifactTemplate, resolvedParamJsonContent, false,
+                mutableMapOf(ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE to
+                    properties[ResourceResolutionConstants.RESOURCE_RESOLUTION_INPUT_OCCURRENCE].asJsonPrimitive()))
 
         if (isToStore(properties)) {
             templateResolutionDBService.write(properties, resolvedContent, bluePrintRuntimeService, artifactPrefix)
@@ -330,7 +333,9 @@ open class ResourceResolutionServiceImpl(private var applicationContext: Applica
                 resourceAssignmentList.forEach {
                     if (compareOne(resourceResolution, it)) {
                         log.info("Resource ({}) already resolve: value=({})", it.name, resourceResolution.value)
-                        val value = resourceResolution.value!!.asJsonPrimitive()
+
+                        // Make sure to recreate value as per the defined type.
+                        val value = resourceResolution.value!!.asJsonType(it.property!!.type)
                         it.property!!.value = value
                         it.status = resourceResolution.status
                         ResourceAssignmentUtils.setResourceDataValue(it, raRuntimeService, value)
index 01cfd72..117df1e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2017-2018 AT&T Intellectual Property.
- * Modifications Copyright © 2019 IBM.
+ * Modifications Copyright (c) 2019 IBM, Bell Canada.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.uti
 import com.fasterxml.jackson.databind.JsonNode
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.fasterxml.jackson.databind.node.ArrayNode
+import com.fasterxml.jackson.databind.node.NullNode
 import com.fasterxml.jackson.databind.node.ObjectNode
 import com.fasterxml.jackson.databind.node.TextNode
 import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
@@ -194,85 +195,214 @@ class ResourceAssignmentUtils {
         @Throws(BluePrintProcessorException::class)
         fun parseResponseNode(responseNode: JsonNode, resourceAssignment: ResourceAssignment,
                               raRuntimeService: ResourceAssignmentRuntimeService, outputKeyMapping: MutableMap<String, String>): JsonNode {
+            try {
+                if ((resourceAssignment.property?.type).isNullOrEmpty()) {
+                    throw BluePrintProcessorException("Couldn't get data dictionary type for dictionary name (${resourceAssignment.name})")
+                }
+                val type = resourceAssignment.property!!.type
+                return when (type) {
+                    in BluePrintTypes.validPrimitiveTypes() -> {
+                        parseResponseNodeForPrimitiveTypes(responseNode, resourceAssignment, outputKeyMapping)
+                    }
+                    in BluePrintTypes.validCollectionTypes() -> {
+                        // Array Types
+                        parseResponseNodeForCollection(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping)
+                    }
+                    else -> {
+                        // Complex Types
+                        parseResponseNodeForComplexType(responseNode, resourceAssignment, raRuntimeService, outputKeyMapping)
+                    }
+                }
+            } catch (e: Exception) {
+                logger.error("Fail to parse response data, error message $e")
+                throw BluePrintProcessorException("${e.message}", e)
+            }
+        }
+
+        private fun parseResponseNodeForPrimitiveTypes(responseNode: JsonNode, resourceAssignment: ResourceAssignment,
+                                                       outputKeyMapping: MutableMap<String, String>): JsonNode {
             val dName = resourceAssignment.dictionaryName
-            val dSource = resourceAssignment.dictionarySource
-            val type = nullToEmpty(resourceAssignment.property?.type)
-            lateinit var entrySchemaType: String
-            when (type) {
-                in BluePrintTypes.validPrimitiveTypes() -> {
-                    if (dSource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
-                        logger.info("For template key (${resourceAssignment.name}) setting value as ($responseNode)")
-                    val result = if (responseNode is ArrayNode)
-                        responseNode.get(0)
-                    else
-                        responseNode
-                    return if (result.isComplexType()) {
-                        check(result.has(outputKeyMapping[dName])) {
-                            "Fail to find output key mapping ($dName) in result."
+            logger.info("For template key (${resourceAssignment.name}) setting value as ($responseNode)")
+
+            var result: JsonNode? = responseNode
+            if (responseNode.isComplexType()) {
+                val key = outputKeyMapping.keys.firstOrNull()
+                var returnNode: JsonNode? = responseNode
+                if (responseNode is ArrayNode) {
+                    val arrayNode = responseNode.toList()
+                    val firstElement = if (key.isNullOrEmpty()) {
+                        arrayNode.first()
+                    }
+                    else{
+                        arrayNode.firstOrNull { element ->
+                            element.isComplexType() && element.has(outputKeyMapping[key])
+                        }
+                    }
+
+                    if (firstElement.isNull() || (firstElement!!.isComplexType() && !firstElement!!.has(outputKeyMapping[key]))
+                            || (!result!!.isComplexType() && result is NullNode)) {
+                        if (key.isNullOrEmpty()) {
+                            throw BluePrintProcessorException("Fail to find mapping in the responseNode.")
+                        }
+                        else {
+                            throw BluePrintProcessorException("Fail to find response with output key mapping ($key) in result.")
                         }
-                        result[outputKeyMapping[dName]]
-                    } else {
-                        result
                     }
+                    returnNode = firstElement
                 }
-                in BluePrintTypes.validCollectionTypes() -> {
-                    // Array Types
-                    entrySchemaType = checkNotEmpty(resourceAssignment.property?.entrySchema?.type) {
-                        "Entry schema is not defined for dictionary ($dName) info"
+                result = if (returnNode!!.isComplexType()) {
+                    returnNode[outputKeyMapping[key]]
+                }
+                else {
+                    returnNode
+                }
+            }
+            return result!!
+        }
+
+        private fun parseResponseNodeForCollection(responseNode: JsonNode, resourceAssignment: ResourceAssignment,
+                                                   raRuntimeService: ResourceAssignmentRuntimeService,
+                                                   outputKeyMapping: MutableMap<String, String>): JsonNode {
+            val dName = resourceAssignment.dictionaryName
+            if ((resourceAssignment.property?.entrySchema?.type).isNullOrEmpty()) {
+                throw BluePrintProcessorException("Couldn't get data type for dictionary type " +
+                        "(${resourceAssignment.property!!.type}) and dictionary name ($dName)")
+            }
+            val entrySchemaType = resourceAssignment.property!!.entrySchema!!.type
+
+            var arrayNode = JacksonUtils.objectMapper.createArrayNode()
+
+            if (outputKeyMapping.isNotEmpty()) {
+                when (responseNode) {
+                    is ArrayNode -> {
+                        val responseArrayNode = responseNode.toList()
+                        for (responseSingleJsonNode in responseArrayNode) {
+                            val arrayChildNode = parseArrayNodeElementWithOutputKeyMapping(raRuntimeService, responseSingleJsonNode,
+                                    outputKeyMapping, entrySchemaType)
+                            arrayNode.add(arrayChildNode)
+                        }
                     }
-                    val arrayNode = JacksonUtils.objectMapper.createArrayNode()
-                    lateinit var responseValueNode: JsonNode
-                    lateinit var propertyType: String
-                    outputKeyMapping.map {
-                        val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+                    is ObjectNode -> {
                         val responseArrayNode = responseNode.rootFieldsToMap()
-                        outer@ for ((key, responseSingleJsonNode) in responseArrayNode) {
-                            if (key == it.key) {
-                                if (entrySchemaType in BluePrintTypes.validPrimitiveTypes()) {
-                                    responseValueNode = responseSingleJsonNode
-                                    propertyType = entrySchemaType
-
-                                } else {
-                                    responseValueNode = responseSingleJsonNode.get(it.key)
-                                    propertyType = getPropertyType(raRuntimeService, entrySchemaType, it.key)
-                                }
-                                if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
-                                    logger.info("For List Type Resource: key (${it.key}), value ($responseValueNode), " +
-                                            "type  ({$propertyType})")
-                                JacksonUtils.populateJsonNodeValues(it.value,
-                                        responseValueNode, propertyType, arrayChildNode)
-                                arrayNode.add(arrayChildNode)
-                                break@outer
-                            }
-                        }
+                        val arrayNodeResult = parseObjectNodeWithOutputKeyMapping(responseArrayNode, outputKeyMapping, entrySchemaType)
+                        arrayNode.addAll(arrayNodeResult)
+                    }
+                    else -> {
+                        throw BluePrintProcessorException("Key-value response expected to match the responseNode.")
                     }
-                    if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
-                        logger.info("For template key (${resourceAssignment.name}) setting value as ($arrayNode)")
-
-                    return arrayNode
                 }
-                else -> {
-                    // Complex Types
-                    entrySchemaType = checkNotEmpty(resourceAssignment.property?.type) {
-                        "Entry schema is not defined for dictionary ($dName) info"
+            }
+            else {
+                when (responseNode) {
+                    is ArrayNode -> {
+                        responseNode.forEach { elementNode ->
+                            arrayNode.add(elementNode)
+                        }
                     }
-                    val objectNode = JacksonUtils.objectMapper.createObjectNode()
+                    is ObjectNode -> {
+                        val responseArrayNode = responseNode.rootFieldsToMap()
+                        for ((key, responseSingleJsonNode) in responseArrayNode) {
+                            val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+                            JacksonUtils.populateJsonNodeValues(key, responseSingleJsonNode, entrySchemaType, arrayChildNode)
+                            arrayNode.add(arrayChildNode)
+                        }
+                    }
+                    else -> {
+                        arrayNode.add(responseNode)
+                    }
+                }
+            }
+
+            logger.info("For template key (${resourceAssignment.name}) setting value as ($arrayNode)")
+
+            return arrayNode
+        }
+
+        private fun parseResponseNodeForComplexType(responseNode: JsonNode, resourceAssignment: ResourceAssignment,
+                                                    raRuntimeService: ResourceAssignmentRuntimeService,
+                                                    outputKeyMapping: MutableMap<String, String>): JsonNode {
+            val entrySchemaType = resourceAssignment.property!!.type
+            val dictionaryName = resourceAssignment.dictionaryName!!
+
+            var result: ObjectNode
+            if (checkOutputKeyMappingInDataTypeProperties(entrySchemaType, outputKeyMapping, raRuntimeService))
+            {
+                result = parseArrayNodeElementWithOutputKeyMapping(raRuntimeService, responseNode, outputKeyMapping, entrySchemaType)
+            }
+            else {
+                val childNode = JacksonUtils.objectMapper.createObjectNode()
+                if (outputKeyMapping.isNotEmpty()) {
                     outputKeyMapping.map {
-                        val responseKeyValue = responseNode.get(it.key)
-                        val propertyTypeForDataType = ResourceAssignmentUtils
-                                .getPropertyType(raRuntimeService, entrySchemaType, it.key)
+                        val responseKeyValue = if (responseNode.has(it.key)) {
+                            responseNode.get(it.key)
+                        }
+                        else {
+                            NullNode.getInstance()
+                        }
 
-                        if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
-                            logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), type  ({$propertyTypeForDataType})")
-                        JacksonUtils.populateJsonNodeValues(it.value, responseKeyValue, propertyTypeForDataType, objectNode)
+                        JacksonUtils.populateJsonNodeValues(it.value,
+                                responseKeyValue, entrySchemaType, childNode)
                     }
+                }
+                else {
+                    JacksonUtils.populateJsonNodeValues(dictionaryName, responseNode, entrySchemaType, childNode)
+                }
+                result = childNode
+            }
+            return result
+        }
+
+        private fun parseArrayNodeElementWithOutputKeyMapping(raRuntimeService: ResourceAssignmentRuntimeService,
+                                                              responseSingleJsonNode: JsonNode, outputKeyMapping:
+                                                              MutableMap<String, String>, entrySchemaType: String): ObjectNode {
+            val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+
+            outputKeyMapping.map {
+                val responseKeyValue = if (responseSingleJsonNode.has(it.key)) {
+                    responseSingleJsonNode.get(it.key)
+                }
+                else {
+                    NullNode.getInstance()
+                }
+                val propertyTypeForDataType = ResourceAssignmentUtils
+                        .getPropertyType(raRuntimeService, entrySchemaType, it.key)
+
+                logger.info("For List Type Resource: key (${it.key}), value ($responseKeyValue), " +
+                        "type  ({$propertyTypeForDataType})")
 
-                    if (resourceAssignment.dictionarySource !in ResourceResolutionConstants.DATA_DICTIONARY_SECRET_SOURCE_TYPES)
-                        logger.info("For template key (${resourceAssignment.name}) setting value as ($objectNode)")
+                JacksonUtils.populateJsonNodeValues(it.value,
+                        responseKeyValue, propertyTypeForDataType, arrayChildNode)
+            }
+
+            return arrayChildNode
+        }
+
+        private fun parseObjectNodeWithOutputKeyMapping(responseArrayNode: MutableMap<String, JsonNode>,
+                                                        outputKeyMapping: MutableMap<String, String>,
+                                                        entrySchemaType: String): ArrayNode {
+            val arrayNode = JacksonUtils.objectMapper.createArrayNode()
+            outputKeyMapping.map {
+                val objectNode = JacksonUtils.objectMapper.createObjectNode()
+                val responseSingleJsonNode = responseArrayNode.filterKeys { key -> key == it.key }.entries.firstOrNull()
 
-                    return objectNode
+                if (responseSingleJsonNode == null) {
+                    JacksonUtils.populateJsonNodeValues(it.value, NullNode.getInstance(), entrySchemaType, objectNode)
                 }
+                else
+                {
+                    JacksonUtils.populateJsonNodeValues(it.value, responseSingleJsonNode.value, entrySchemaType, objectNode)
+                }
+                arrayNode.add(objectNode)
             }
+
+            return arrayNode
+        }
+
+        private fun checkOutputKeyMappingInDataTypeProperties(dataTypeName: String, outputKeyMapping: MutableMap<String, String>,
+                                                              raRuntimeService: ResourceAssignmentRuntimeService): Boolean {
+            val dataTypeProps = raRuntimeService.bluePrintContext().dataTypeByName(dataTypeName)?.properties
+            val result = outputKeyMapping.filterKeys { !dataTypeProps!!.containsKey(it) }.keys.firstOrNull()
+            return result == null
         }
     }
 }
\ No newline at end of file
index 9b87c12..9365c3e 100644 (file)
@@ -1,6 +1,7 @@
 /*-
  * ============LICENSE_START=======================================================
  *  Copyright (C) 2019 Nordix Foundation.
+ * Modifications Copyright (c) 2019 IBM, Bell Canada.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * ============LICENSE_END=========================================================
  */
 
-
 package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils
 
+import com.fasterxml.jackson.databind.JsonNode
+import com.fasterxml.jackson.databind.node.NullNode
 import com.fasterxml.jackson.databind.node.TextNode
+import io.mockk.every
+import io.mockk.spyk
+import org.junit.Before
 import org.junit.Test
+import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive
+import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
+import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
+import org.onap.ccsdk.cds.controllerblueprints.core.data.EntrySchema
 import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
 import kotlin.test.assertEquals
 
+data class IpAddress(val port: String, val ip: String)
+data class Host(val name: String, val ipAddress: IpAddress)
+data class ExpectedResponseIp(val ip: String)
+data class ExpectedResponsePort(val port: String)
+
 class ResourceAssignmentUtilsTest {
+    private lateinit var resourceAssignmentRuntimeService: ResourceAssignmentRuntimeService
+
+    @Before
+    fun setup() {
+
+        val bluePrintContext = BluePrintMetadataUtils.getBluePrintContext(
+                "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration")
+
+        resourceAssignmentRuntimeService = spyk(ResourceAssignmentRuntimeService("1234", bluePrintContext))
+
+        val propertiesDefinition1 = PropertyDefinition().apply {
+            type = "string"
+            id = "port"
+        }
+
+        val propertiesDefinition2 = PropertyDefinition().apply {
+            type = "string"
+            id = "ip"
+        }
+
+        val propertiesDefinition3 = PropertyDefinition().apply {
+            type = "string"
+            id = "name"
+        }
+
+        val propertiesDefinition4 = PropertyDefinition().apply {
+            type = "ip-address"
+            id = "ipAddress"
+        }
+
+        var mapOfPropertiesIpAddress = mutableMapOf<String, PropertyDefinition>()
+        mapOfPropertiesIpAddress["port"] = propertiesDefinition1
+        mapOfPropertiesIpAddress["ip"] = propertiesDefinition2
+
+        var mapOfPropertiesHost = mutableMapOf<String, PropertyDefinition>()
+        mapOfPropertiesHost["name"] = propertiesDefinition3
+        mapOfPropertiesHost["ipAddress"] = propertiesDefinition4
+
+        val myDataTypeIpaddress = DataType().apply {
+            id = "ip-address"
+            properties = mapOfPropertiesIpAddress
+        }
+
+        val myDataTypeHost = DataType().apply {
+            id = "host"
+            properties = mapOfPropertiesHost
+        }
+
+        every { resourceAssignmentRuntimeService.bluePrintContext().dataTypeByName("ip-address") } returns myDataTypeIpaddress
+
+        every { resourceAssignmentRuntimeService.bluePrintContext().dataTypeByName("host") } returns myDataTypeHost
+
+        every { resourceAssignmentRuntimeService.setNodeTemplateAttributeValue(any(), any(), any()) } returns Unit
+    }
 
     @Test
     fun `generateResourceDataForAssignments - positive test`() {
@@ -43,7 +114,6 @@ class ResourceAssignmentUtilsTest {
         //then the assignment should produce a valid result
         val expected = "{\n" + "  \"pnf-id\" : \"valid_value\"\n" + "}"
         assertEquals(expected, outcome, "unexpected outcome generated")
-
     }
 
     @Test
@@ -76,4 +146,243 @@ class ResourceAssignmentUtilsTest {
         }
         return resourceAssignmentForTest
     }
+
+    @Test
+    fun parseResponseNodeTestForPrimitivesTypes(){
+        // Input values for primitive type
+        val keyValue = mutableMapOf<String, String>()
+        keyValue["value"]= "1.2.3.1"
+        val expectedPrimitiveType = TextNode("1.2.3.1")
+
+        var outcome = prepareResponseNodeForTest("sample-value", "string",
+                "", "1.2.3.1".asJsonPrimitive())
+        assertEquals(expectedPrimitiveType, outcome, "Unexpected outcome returned for primitive type of simple String")
+        outcome = prepareResponseNodeForTest("sample-key-value", "string", "", keyValue)
+        assertEquals(expectedPrimitiveType, outcome, "Unexpected outcome returned for primitive type of key-value String")
+    }
+
+    @Test
+    fun parseResponseNodeTestForCollectionsOfString(){
+        // Input values for collection type
+        val mapOfString = mutableMapOf<String, String>()
+        mapOfString["value1"] = "1.2.3.1"
+        mapOfString["port"] = "8888"
+        mapOfString["value2"] = "1.2.3.2"
+        val arrayOfKeyValue = arrayListOf(ExpectedResponseIp("1.2.3.1"),
+                ExpectedResponsePort( "8888"), ExpectedResponseIp("1.2.3.2"))
+
+        val mutableMapKeyValue = mutableMapOf<String, String>()
+        mutableMapKeyValue["value1"] = "1.2.3.1"
+        mutableMapKeyValue["port"] = "8888"
+
+        //List
+        val expectedListOfString = arrayOfKeyValue.asJsonType()
+        var outcome = prepareResponseNodeForTest("listOfString", "list",
+                "string", mapOfString.asJsonType())
+        assertEquals(expectedListOfString, outcome, "unexpected outcome returned for list of String")
+
+        //Map
+        val expectedMapOfString = mutableMapOf<String, JsonNode>()
+        expectedMapOfString["ip"] = "1.2.3.1".asJsonPrimitive()
+        expectedMapOfString["port"] = "8888".asJsonPrimitive()
+
+        val arrayNode = JacksonUtils.objectMapper.createArrayNode()
+        expectedMapOfString.map {
+            val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+            arrayChildNode.set(it.key, it.value)
+            arrayNode.add(arrayChildNode)
+        }
+        val arrayChildNode1 = JacksonUtils.objectMapper.createObjectNode()
+        arrayChildNode1.set("ip", NullNode.getInstance())
+        arrayNode.add(arrayChildNode1)
+        outcome = prepareResponseNodeForTest("mapOfString", "map", "string",
+                mutableMapKeyValue.asJsonType())
+        assertEquals(arrayNode, outcome, "unexpected outcome returned for map of String")
+    }
+
+    @Test
+    fun parseResponseNodeTestForCollectionsOfJsonNode(){
+        // Input values for collection type
+        val mapOfString = mutableMapOf<String, JsonNode>()
+        mapOfString["value1"] = "1.2.3.1".asJsonPrimitive()
+        mapOfString["port"] = "8888".asJsonPrimitive()
+        mapOfString["value2"] = "1.2.3.2".asJsonPrimitive()
+        val arrayOfKeyValue = arrayListOf(ExpectedResponseIp("1.2.3.1"),
+                ExpectedResponsePort( "8888"), ExpectedResponseIp("1.2.3.2"))
+
+        val mutableMapKeyValue = mutableMapOf<String, JsonNode>()
+        mutableMapKeyValue["value1"] = "1.2.3.1".asJsonPrimitive()
+        mutableMapKeyValue["port"] = "8888".asJsonPrimitive()
+
+        //List
+        val expectedListOfString = arrayOfKeyValue.asJsonType()
+        var outcome = prepareResponseNodeForTest("listOfString", "list",
+                "string", mapOfString.asJsonType())
+        assertEquals(expectedListOfString, outcome, "unexpected outcome returned for list of String")
+
+        //Map
+        val expectedMapOfString = mutableMapOf<String, JsonNode>()
+        expectedMapOfString["ip"] = "1.2.3.1".asJsonPrimitive()
+        expectedMapOfString["port"] = "8888".asJsonPrimitive()
+        val arrayNode = JacksonUtils.objectMapper.createArrayNode()
+        expectedMapOfString.map {
+            val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+            arrayChildNode.set(it.key, it.value)
+            arrayNode.add(arrayChildNode)
+        }
+        val arrayChildNode1 = JacksonUtils.objectMapper.createObjectNode()
+        arrayChildNode1.set("ip", NullNode.getInstance())
+        arrayNode.add(arrayChildNode1)
+        outcome = prepareResponseNodeForTest("mapOfString", "map",
+                "string", mutableMapKeyValue.asJsonType())
+        assertEquals(arrayNode, outcome, "unexpected outcome returned for map of String")
+    }
+
+    @Test
+    fun parseResponseNodeTestForCollectionsOfComplexType(){
+        // Input values for collection type
+        val mapOfComplexType = mutableMapOf<String, JsonNode>()
+        mapOfComplexType["value1"] = IpAddress("1111", "1.2.3.1").asJsonType()
+        mapOfComplexType["value2"] = IpAddress("2222", "1.2.3.2").asJsonType()
+        mapOfComplexType["value3"] = IpAddress("3333", "1.2.3.3").asJsonType()
+
+        //List
+        val arrayNode = JacksonUtils.objectMapper.createArrayNode()
+        mapOfComplexType.map {
+            val arrayChildNode = JacksonUtils.objectMapper.createObjectNode()
+            arrayChildNode.set("ipAddress", it.value)
+            arrayNode.add(arrayChildNode)
+        }
+        var outcome = prepareResponseNodeForTest("listOfMyDataType", "list",
+                "ip-address", mapOfComplexType.asJsonType())
+        assertEquals(arrayNode, outcome, "unexpected outcome returned for list of String")
+    }
+
+    @Test
+    fun `parseResponseNodeTestForComplexType find one output key mapping`(){
+        // Input values for complex type
+        val objectNode = JacksonUtils.objectMapper.createObjectNode()
+
+        // Input values for collection type
+        val mapOfComplexType = mutableMapOf<String, JsonNode>()
+        mapOfComplexType["value"] = Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType()
+        mapOfComplexType["port"] = "8888".asJsonType()
+        mapOfComplexType["something"] = "1.2.3.2".asJsonType()
+
+        val expectedComplexType = objectNode.set("ipAddress", Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType())
+        val outcome = prepareResponseNodeForTest("complexTypeOneKeys", "host",
+                "", mapOfComplexType.asJsonType())
+        assertEquals(expectedComplexType, outcome, "Unexpected outcome returned for complex type")
+    }
+
+    @Test
+    fun `parseResponseNodeTestForComplexType find all output key mapping`(){
+        // Input values for complex type
+        val objectNode = JacksonUtils.objectMapper.createObjectNode()
+
+        // Input values for collection type
+        val mapOfComplexType = mutableMapOf<String, JsonNode>()
+        mapOfComplexType["name"] = "my-ipAddress".asJsonType()
+        mapOfComplexType["ipAddress"] = IpAddress("1111", "1.2.3.1").asJsonType()
+
+        val expectedComplexType = Host("my-ipAddress", IpAddress("1111", "1.2.3.1")).asJsonType()
+        val outcome = prepareResponseNodeForTest("complexTypeAllKeys", "host",
+                "", mapOfComplexType.asJsonType())
+        assertEquals(expectedComplexType, outcome, "Unexpected outcome returned for complex type")
+    }
+
+    private fun prepareResponseNodeForTest(dictionary_source: String, sourceType: String, entrySchema: String,
+                                           response: Any): JsonNode {
+
+        val resourceAssignment = when (sourceType) {
+            "list", "map" -> {
+                prepareRADataDictionaryCollection(dictionary_source, sourceType, entrySchema)
+            }
+            "string" -> {
+                prepareRADataDictionaryOfPrimaryType(dictionary_source)
+            }
+            else -> {
+                prepareRADataDictionaryComplexType(dictionary_source, sourceType, entrySchema)
+            }
+        }
+
+        val responseNode = checkNotNull(JacksonUtils.getJsonNode(response)) {
+            "Failed to get database query result into Json node."
+        }
+
+        val outputKeyMapping = prepareOutputKeyMapping(dictionary_source)
+
+        return ResourceAssignmentUtils.parseResponseNode(responseNode, resourceAssignment, resourceAssignmentRuntimeService, outputKeyMapping)
+    }
+
+    private fun prepareRADataDictionaryOfPrimaryType(dictionary_source: String): ResourceAssignment {
+        return ResourceAssignment().apply {
+            name = "ipAddress"
+            dictionaryName = "sample-ip"
+            dictionarySource = "$dictionary_source"
+            property = PropertyDefinition().apply {
+                type = "string"
+            }
+        }
+    }
+
+    private fun prepareRADataDictionaryCollection(dictionary_source: String, sourceType: String, schema: String): ResourceAssignment {
+        return ResourceAssignment().apply {
+            name = "ipAddress-list"
+            dictionaryName = "sample-licenses"
+            dictionarySource = "$dictionary_source"
+            property = PropertyDefinition().apply {
+                type = "$sourceType"
+                entrySchema = EntrySchema().apply {
+                    type = "$schema"
+                }
+            }
+        }
+    }
+
+    private fun prepareRADataDictionaryComplexType(dictionary_source: String, sourceType: String, schema: String): ResourceAssignment {
+        return ResourceAssignment().apply {
+            name = "ipAddress-complexType"
+            dictionaryName = "sample-licenses"
+            dictionarySource = "$dictionary_source"
+            property = PropertyDefinition().apply {
+                type = "$sourceType"
+            }
+        }
+    }
+
+    private fun prepareOutputKeyMapping(dictionary_source: String): MutableMap<String, String> {
+        val outputMapping = mutableMapOf<String, String>()
+
+        when (dictionary_source) {
+            "listOfString", "mapOfString" -> {
+                //List of string
+                outputMapping["value1"] = "ip"
+                outputMapping["port"] = "port"
+                outputMapping["value2"] = "ip"
+            }
+            "listOfMyDataType", "mapOfMyDataType" -> {
+                //List or map of complex Type
+                outputMapping["value1"] = "ipAddress"
+                outputMapping["value2"] = "ipAddress"
+                outputMapping["value3"] = "ipAddress"
+            }
+            "sample-key-value", "sample-value" -> {
+                //Primary Type
+                if (dictionary_source=="sample-key-value")
+                    outputMapping["sample-ip"] = "value"
+            }
+            else -> {
+                //Complex Type
+                if (dictionary_source == "complexTypeOneKeys")
+                    outputMapping["value"] = "ipAddress"
+                else {
+                    outputMapping["name"] = "name"
+                    outputMapping["ipAddress"] = "ipAddress"
+                }
+
+            }
+        }
+        return outputMapping
+    }
 }
\ No newline at end of file
index 53f0f4e..c1dd501 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>functions</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId>
index 783d8ef..67b8424 100644 (file)
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>commons</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>db-lib</artifactId>
index b8d418f..3ed0424 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>commons</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>dmaap-lib</artifactId>
index ad16eb9..e5214e1 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>commons</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
index 2a67da1..b5b8c46 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>commons</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
index 644c518..27a444b 100644 (file)
 package org.onap.ccsdk.cds.blueprintsprocessor.message
 
 
+import com.fasterxml.jackson.databind.JsonNode
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BlueprintMessageConsumerService
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BlueprintMessageProducerService
+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
@@ -26,10 +31,36 @@ import org.springframework.context.annotation.Configuration
 @EnableConfigurationProperties
 open class BluePrintMessageLibConfiguration
 
+/**
+ * Exposed Dependency Service by this Message Lib Module
+ */
+fun BluePrintDependencyService.messageLibPropertyService(): BluePrintMessageLibPropertyService =
+        instance(MessageLibConstants.SERVICE_BLUEPRINT_MESSAGE_LIB_PROPERTY)
+
+/** Extension functions for message producer service **/
+fun BluePrintDependencyService.messageProducerService(selector: String): BlueprintMessageProducerService {
+    return messageLibPropertyService().blueprintMessageProducerService(selector)
+}
+
+
+fun BluePrintDependencyService.messageProducerService(jsonNode: JsonNode): BlueprintMessageProducerService {
+    return messageLibPropertyService().blueprintMessageProducerService(jsonNode)
+}
+
+/** Extension functions for message consumer service **/
+fun BluePrintDependencyService.messageConsumerService(selector: String): BlueprintMessageConsumerService {
+    return messageLibPropertyService().blueprintMessageConsumerService(selector)
+}
+
+fun BluePrintDependencyService.messageConsumerService(jsonNode: JsonNode): BlueprintMessageConsumerService {
+    return messageLibPropertyService().blueprintMessageConsumerService(jsonNode)
+}
+
 class MessageLibConstants {
     companion object {
         const val SERVICE_BLUEPRINT_MESSAGE_LIB_PROPERTY = "blueprint-message-lib-property-service"
-        const val PROPERTY_MESSAGE_CLIENT_PREFIX = "blueprintsprocessor.messageclient."
+        const val PROPERTY_MESSAGE_CONSUMER_PREFIX = "blueprintsprocessor.messageconsumer."
+        const val PROPERTY_MESSAGE_PRODUCER_PREFIX = "blueprintsprocessor.messageproducer."
         const val TYPE_KAFKA_BASIC_AUTH = "kafka-basic-auth"
     }
 }
\ No newline at end of file
index e621ec6..ab04054 100644 (file)
@@ -16,7 +16,7 @@
 
 package org.onap.ccsdk.cds.blueprintsprocessor.message
 
-
+/** Producer Properties **/
 open class MessageProducerProperties
 
 
@@ -24,4 +24,18 @@ open class KafkaBasicAuthMessageProducerProperties : MessageProducerProperties()
     lateinit var bootstrapServers: String
     var topic: String? = null
     var clientId: String? = null
-}
\ No newline at end of file
+}
+
+/** Consumer Properties **/
+
+open class MessageConsumerProperties
+
+open class KafkaMessageConsumerProperties : MessageConsumerProperties() {
+    lateinit var bootstrapServers: String
+    lateinit var groupId: String
+    var clientId: String? = null
+    var topic: String? = null
+    var pollMillSec: Long = 1000
+}
+
+open class KafkaBasicAuthMessageConsumerProperties : KafkaMessageConsumerProperties()
index fb01ce1..7c56ea4 100644 (file)
@@ -18,9 +18,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.message.service
 
 import com.fasterxml.jackson.databind.JsonNode
 import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties
-import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageProducerProperties
-import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageLibConstants
-import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageProducerProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.message.*
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 import org.springframework.stereotype.Service
@@ -28,22 +26,22 @@ import org.springframework.stereotype.Service
 @Service(MessageLibConstants.SERVICE_BLUEPRINT_MESSAGE_LIB_PROPERTY)
 open class BluePrintMessageLibPropertyService(private var bluePrintProperties: BluePrintProperties) {
 
-    fun blueprintMessageClientService(jsonNode: JsonNode): BlueprintMessageProducerService {
-        val messageClientProperties = messageClientProperties(jsonNode)
-        return blueprintMessageClientService(messageClientProperties)
+    fun blueprintMessageProducerService(jsonNode: JsonNode): BlueprintMessageProducerService {
+        val messageClientProperties = messageProducerProperties(jsonNode)
+        return blueprintMessageProducerService(messageClientProperties)
     }
 
-    fun blueprintMessageClientService(selector: String): BlueprintMessageProducerService {
-        val prefix = "${MessageLibConstants.PROPERTY_MESSAGE_CLIENT_PREFIX}$selector"
-        val messageClientProperties = messageClientProperties(prefix)
-        return blueprintMessageClientService(messageClientProperties)
+    fun blueprintMessageProducerService(selector: String): BlueprintMessageProducerService {
+        val prefix = "${MessageLibConstants.PROPERTY_MESSAGE_PRODUCER_PREFIX}$selector"
+        val messageClientProperties = messageProducerProperties(prefix)
+        return blueprintMessageProducerService(messageClientProperties)
     }
 
-    fun messageClientProperties(prefix: String): MessageProducerProperties {
+    fun messageProducerProperties(prefix: String): MessageProducerProperties {
         val type = bluePrintProperties.propertyBeanType("$prefix.type", String::class.java)
         return when (type) {
             MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> {
-                kafkaBasicAuthMessageClientProperties(prefix)
+                kafkaBasicAuthMessageProducerProperties(prefix)
             }
             else -> {
                 throw BluePrintProcessorException("Message adaptor($type) is not supported")
@@ -51,7 +49,7 @@ open class BluePrintMessageLibPropertyService(private var bluePrintProperties: B
         }
     }
 
-    fun messageClientProperties(jsonNode: JsonNode): MessageProducerProperties {
+    fun messageProducerProperties(jsonNode: JsonNode): MessageProducerProperties {
         val type = jsonNode.get("type").textValue()
         return when (type) {
             MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> {
@@ -63,7 +61,7 @@ open class BluePrintMessageLibPropertyService(private var bluePrintProperties: B
         }
     }
 
-    private fun blueprintMessageClientService(MessageProducerProperties: MessageProducerProperties)
+    private fun blueprintMessageProducerService(MessageProducerProperties: MessageProducerProperties)
             : BlueprintMessageProducerService {
 
         when (MessageProducerProperties) {
@@ -76,9 +74,67 @@ open class BluePrintMessageLibPropertyService(private var bluePrintProperties: B
         }
     }
 
-    private fun kafkaBasicAuthMessageClientProperties(prefix: String): KafkaBasicAuthMessageProducerProperties {
+    private fun kafkaBasicAuthMessageProducerProperties(prefix: String): KafkaBasicAuthMessageProducerProperties {
         return bluePrintProperties.propertyBeanType(
                 prefix, KafkaBasicAuthMessageProducerProperties::class.java)
     }
 
+    /** Consumer Property Lib Service Implementation **/
+
+    /** Return Message Consumer Service for [jsonNode] definitions. */
+    fun blueprintMessageConsumerService(jsonNode: JsonNode): BlueprintMessageConsumerService {
+        val messageConsumerProperties = messageConsumerProperties(jsonNode)
+        return blueprintMessageConsumerService(messageConsumerProperties)
+    }
+
+    /** Return Message Consumer Service for [selector] definitions. */
+    fun blueprintMessageConsumerService(selector: String): BlueprintMessageConsumerService {
+        val prefix = "${MessageLibConstants.PROPERTY_MESSAGE_CONSUMER_PREFIX}$selector"
+        val messageClientProperties = messageConsumerProperties(prefix)
+        return blueprintMessageConsumerService(messageClientProperties)
+    }
+
+    /** Return Message Consumer Properties for [prefix] definitions. */
+    fun messageConsumerProperties(prefix: String): MessageConsumerProperties {
+        val type = bluePrintProperties.propertyBeanType("$prefix.type", String::class.java)
+        return when (type) {
+            MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> {
+                kafkaBasicAuthMessageConsumerProperties(prefix)
+            }
+            else -> {
+                throw BluePrintProcessorException("Message adaptor($type) is not supported")
+            }
+        }
+    }
+
+    fun messageConsumerProperties(jsonNode: JsonNode): MessageConsumerProperties {
+        val type = jsonNode.get("type").textValue()
+        return when (type) {
+            MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> {
+                JacksonUtils.readValue(jsonNode, KafkaBasicAuthMessageConsumerProperties::class.java)!!
+            }
+            else -> {
+                throw BluePrintProcessorException("Message adaptor($type) is not supported")
+            }
+        }
+    }
+
+    private fun blueprintMessageConsumerService(messageConsumerProperties: MessageConsumerProperties)
+            : BlueprintMessageConsumerService {
+
+        when (messageConsumerProperties) {
+            is KafkaBasicAuthMessageConsumerProperties -> {
+                return KafkaBasicAuthMessageConsumerService(messageConsumerProperties)
+            }
+            else -> {
+                throw BluePrintProcessorException("couldn't get Message client service for")
+            }
+        }
+    }
+
+    private fun kafkaBasicAuthMessageConsumerProperties(prefix: String): KafkaBasicAuthMessageConsumerProperties {
+        return bluePrintProperties.propertyBeanType(
+                prefix, KafkaBasicAuthMessageConsumerProperties::class.java)
+    }
+
 }
diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerService.kt
new file mode 100644 (file)
index 0000000..25f0bf4
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ *  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.message.service
+
+import kotlinx.coroutines.channels.Channel
+
+interface BlueprintMessageConsumerService {
+
+    /** Subscribe to the Kafka channel with [additionalConfig] */
+    suspend fun subscribe(additionalConfig: Map<String, Any>?): Channel<String>
+
+    /** Subscribe to the Kafka channel with [additionalConfig] for dynamic [topics]*/
+    suspend fun subscribe(topics: List<String>, additionalConfig: Map<String, Any>? = null): Channel<String>
+
+    /** close the channel, consumer and other resources */
+    suspend fun shutDown()
+
+}
\ No newline at end of file
diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageConsumerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageConsumerService.kt
new file mode 100644 (file)
index 0000000..5a9e61b
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ *  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.message.service
+
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.apache.kafka.clients.CommonClientConfigs
+import org.apache.kafka.clients.consumer.Consumer
+import org.apache.kafka.clients.consumer.ConsumerConfig
+import org.apache.kafka.clients.consumer.KafkaConsumer
+import org.apache.kafka.common.serialization.StringDeserializer
+import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageConsumerProperties
+import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import java.time.Duration
+import kotlin.concurrent.thread
+
+class KafkaBasicAuthMessageConsumerService(
+        private val messageConsumerProperties: KafkaBasicAuthMessageConsumerProperties)
+    : BlueprintMessageConsumerService {
+
+    private val channel = Channel<String>()
+    private var kafkaConsumer: Consumer<String, String>? = null
+    val log = logger(KafkaBasicAuthMessageConsumerService::class)
+
+    @Volatile
+    var keepGoing = true
+
+    fun kafkaConsumer(additionalConfig: Map<String, Any>? = null): Consumer<String, String> {
+        val configProperties = hashMapOf<String, Any>()
+        configProperties[CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG] = messageConsumerProperties.bootstrapServers
+        configProperties[ConsumerConfig.GROUP_ID_CONFIG] = messageConsumerProperties.groupId
+        configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = "latest"
+        configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java
+        configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java
+        if (messageConsumerProperties.clientId != null) {
+            configProperties[ConsumerConfig.CLIENT_ID_CONFIG] = messageConsumerProperties.clientId!!
+        }
+        // TODO("Security Implementation based on type")
+        /** add or override already set properties */
+        additionalConfig?.let { configProperties.putAll(it) }
+        /** Create Kafka consumer */
+        return KafkaConsumer(configProperties)
+    }
+
+    override suspend fun subscribe(additionalConfig: Map<String, Any>?): Channel<String> {
+        /** get to topic names */
+        val consumerTopic = messageConsumerProperties.topic?.split(",")?.map { it.trim() }
+        check(!consumerTopic.isNullOrEmpty()) { "couldn't get topic information" }
+        return subscribe(consumerTopic, additionalConfig)
+    }
+
+
+    override suspend fun subscribe(consumerTopic: List<String>, additionalConfig: Map<String, Any>?): Channel<String> {
+        /** Create Kafka consumer */
+        kafkaConsumer = kafkaConsumer(additionalConfig)
+
+        checkNotNull(kafkaConsumer) {
+            "failed to create kafka consumer for " +
+                    "server(${messageConsumerProperties.bootstrapServers})'s " +
+                    "topics(${messageConsumerProperties.bootstrapServers})"
+        }
+
+        kafkaConsumer!!.subscribe(consumerTopic)
+        log.info("Successfully consumed topic($consumerTopic)")
+
+        thread(start = true, name = "KafkaConsumer") {
+            keepGoing = true
+            kafkaConsumer!!.use { kc ->
+                while (keepGoing) {
+                    val consumerRecords = kc.poll(Duration.ofMillis(messageConsumerProperties.pollMillSec))
+                    runBlocking {
+                        consumerRecords?.forEach { consumerRecord ->
+                            /** execute the command block */
+                            consumerRecord.value()?.let {
+                                launch {
+                                    if (!channel.isClosedForSend) {
+                                        channel.send(it)
+                                    } else {
+                                        log.error("Channel is closed to receive message")
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                log.info("message listener shutting down.....")
+            }
+        }
+        return channel
+    }
+
+    override suspend fun shutDown() {
+        /** stop the polling loop */
+        keepGoing = false
+        /** Close the Channel */
+        channel.cancel()
+        /** TO shutdown gracefully, need to wait for the maximum poll time */
+        delay(messageConsumerProperties.pollMillSec)
+    }
+}
diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt
new file mode 100644 (file)
index 0000000..2b84eaa
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ *  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.message.service
+
+import io.mockk.every
+import io.mockk.spyk
+import kotlinx.coroutines.channels.consumeEach
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.apache.kafka.clients.consumer.ConsumerRecord
+import org.apache.kafka.clients.consumer.MockConsumer
+import org.apache.kafka.clients.consumer.OffsetResetStrategy
+import org.apache.kafka.common.TopicPartition
+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.message.BluePrintMessageLibConfiguration
+import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import org.springframework.beans.factory.annotation.Autowired
+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 kotlin.test.assertNotNull
+import kotlin.test.assertTrue
+
+
+@RunWith(SpringRunner::class)
+@DirtiesContext
+@ContextConfiguration(classes = [BluePrintMessageLibConfiguration::class,
+    BlueprintPropertyConfiguration::class, BluePrintProperties::class])
+@TestPropertySource(properties =
+["blueprintsprocessor.messageconsumer.sample.type=kafka-basic-auth",
+    "blueprintsprocessor.messageconsumer.sample.bootstrapServers=127.0.0.1:9092",
+    "blueprintsprocessor.messageconsumer.sample.groupId=sample-group",
+    "blueprintsprocessor.messageconsumer.sample.topic=default-topic",
+    "blueprintsprocessor.messageconsumer.sample.clientId=default-client-id",
+    "blueprintsprocessor.messageconsumer.sample.pollMillSec=10",
+
+    "blueprintsprocessor.messageproducer.sample.type=kafka-basic-auth",
+    "blueprintsprocessor.messageproducer.sample.bootstrapServers=127.0.0.1:9092",
+    "blueprintsprocessor.messageproducer.sample.topic=default-topic",
+    "blueprintsprocessor.messageproducer.sample.clientId=default-client-id"
+])
+open class BlueprintMessageConsumerServiceTest {
+    val log = logger(BlueprintMessageConsumerServiceTest::class)
+
+    @Autowired
+    lateinit var bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService
+
+    @Test
+    fun testKafkaBasicAuthConsumerService() {
+        runBlocking {
+            val blueprintMessageConsumerService = bluePrintMessageLibPropertyService
+                    .blueprintMessageConsumerService("sample") as KafkaBasicAuthMessageConsumerService
+            assertNotNull(blueprintMessageConsumerService, "failed to get blueprintMessageConsumerService")
+
+            val spyBlueprintMessageConsumerService = spyk(blueprintMessageConsumerService, recordPrivateCalls = true)
+
+            val topic = "default-topic"
+            val partitions: MutableList<TopicPartition> = arrayListOf()
+            val topicsCollection: MutableList<String> = arrayListOf()
+            partitions.add(TopicPartition(topic, 1))
+            val partitionsBeginningMap: MutableMap<TopicPartition, Long> = mutableMapOf()
+            val partitionsEndMap: MutableMap<TopicPartition, Long> = mutableMapOf()
+
+            val records: Long = 10
+            partitions.forEach { partition ->
+                partitionsBeginningMap[partition] = 0L
+                partitionsEndMap[partition] = records
+                topicsCollection.add(partition.topic())
+            }
+            val mockKafkaConsumer = MockConsumer<String, String>(OffsetResetStrategy.EARLIEST)
+            mockKafkaConsumer.subscribe(topicsCollection)
+            mockKafkaConsumer.rebalance(partitions)
+            mockKafkaConsumer.updateBeginningOffsets(partitionsBeginningMap)
+            mockKafkaConsumer.updateEndOffsets(partitionsEndMap)
+            for (i in 1..10) {
+                val record = ConsumerRecord<String, String>(topic, 1, i.toLong(), "key_$i",
+                        "I am message $i")
+                mockKafkaConsumer.addRecord(record)
+            }
+
+            every { spyBlueprintMessageConsumerService.kafkaConsumer(any()) } returns mockKafkaConsumer
+            val channel = spyBlueprintMessageConsumerService.subscribe(null)
+            launch {
+                channel.consumeEach {
+                    assertTrue(it.startsWith("I am message"), "failed to get the actual message")
+                }
+            }
+            delay(10)
+            spyBlueprintMessageConsumerService.shutDown()
+        }
+    }
+
+    /** Integration Kafka Testing, Enable and use this test case only for local desktop testing with real kafka broker */
+    //@Test
+    fun testKafkaIntegration() {
+        runBlocking {
+            val blueprintMessageConsumerService = bluePrintMessageLibPropertyService
+                    .blueprintMessageConsumerService("sample") as KafkaBasicAuthMessageConsumerService
+            assertNotNull(blueprintMessageConsumerService, "failed to get blueprintMessageConsumerService")
+
+            val channel = blueprintMessageConsumerService.subscribe(null)
+            launch {
+                channel.consumeEach {
+                    log.info("Consumed Message : $it")
+                }
+            }
+
+            /** Send message with every 1 sec */
+            val blueprintMessageProducerService = bluePrintMessageLibPropertyService
+                    .blueprintMessageProducerService("sample") as KafkaBasicAuthMessageProducerService
+            launch {
+                repeat(5) {
+                    delay(1000)
+                    blueprintMessageProducerService.sendMessage("this is my message($it)")
+                }
+            }
+            delay(10000)
+            blueprintMessageConsumerService.shutDown()
+        }
+    }
+}
\ No newline at end of file
index 0f8367d..31bcc15 100644 (file)
@@ -41,10 +41,10 @@ import kotlin.test.assertTrue
 @ContextConfiguration(classes = [BluePrintMessageLibConfiguration::class,
     BlueprintPropertyConfiguration::class, BluePrintProperties::class])
 @TestPropertySource(properties =
-["blueprintsprocessor.messageclient.sample.type=kafka-basic-auth",
-    "blueprintsprocessor.messageclient.sample.bootstrapServers=127:0.0.1:9092",
-    "blueprintsprocessor.messageclient.sample.topic=default-topic",
-    "blueprintsprocessor.messageclient.sample.clientId=default-client-id"
+["blueprintsprocessor.messageproducer.sample.type=kafka-basic-auth",
+    "blueprintsprocessor.messageproducer.sample.bootstrapServers=127.0.0.1:9092",
+    "blueprintsprocessor.messageproducer.sample.topic=default-topic",
+    "blueprintsprocessor.messageproducer.sample.clientId=default-client-id"
 ])
 open class BlueprintMessageProducerServiceTest {
 
@@ -52,10 +52,10 @@ open class BlueprintMessageProducerServiceTest {
     lateinit var bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService
 
     @Test
-    fun testKafkaBasicAuthClientService() {
+    fun testKafkaBasicAuthProducertService() {
         runBlocking {
-            val bluePrintMessageClientService = bluePrintMessageLibPropertyService
-                    .blueprintMessageClientService("sample") as KafkaBasicAuthMessageProducerService
+            val blueprintMessageProducerService = bluePrintMessageLibPropertyService
+                    .blueprintMessageProducerService("sample") as KafkaBasicAuthMessageProducerService
 
             val mockKafkaTemplate = mockk<KafkaTemplate<String, Any>>()
 
@@ -64,11 +64,11 @@ open class BlueprintMessageProducerServiceTest {
 
             every { mockKafkaTemplate.send(any(), any()) } returns future
 
-            val spyBluePrintMessageClientService = spyk(bluePrintMessageClientService, recordPrivateCalls = true)
+            val spyBluePrintMessageProducerService = spyk(blueprintMessageProducerService, recordPrivateCalls = true)
 
-            every { spyBluePrintMessageClientService.messageTemplate(any()) } returns mockKafkaTemplate
+            every { spyBluePrintMessageProducerService.messageTemplate(any()) } returns mockKafkaTemplate
 
-            val response = spyBluePrintMessageClientService.sendMessage("Testing message")
+            val response = spyBluePrintMessageProducerService.sendMessage("Testing message")
             assertTrue(response, "failed to get command response")
         }
     }
index 626b8f9..3868440 100644 (file)
@@ -19,7 +19,7 @@
         <!-- encoders are assigned the type
              ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
         <encoder>
-            <pattern>%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n</pattern>
+            <pattern>%d{HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %msg%n</pattern>
         </encoder>
     </appender>
 
index 8c88db4..37dd5d7 100755 (executable)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>commons</artifactId>
index 8ebbc67..673d127 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>commons</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>processor-core</artifactId>
index 7602853..7c6cceb 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>commons</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>rest-lib</artifactId>
index 75a9409..68672f2 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2017-2018 AT&T Intellectual Property.
  * Modifications Copyright © 2019 Huawei.
+ * Modifications 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.
@@ -20,6 +21,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.rest
 open class RestClientProperties {
     lateinit var type: String
     lateinit var url: String
+    var additionalHeaders: Map<String, String>? = null
 }
 
 open class SSLRestClientProperties : RestClientProperties() {
@@ -63,4 +65,4 @@ open class PolicyManagerRestClientProperties : RestClientProperties() {
     lateinit var env: String
     lateinit var clientAuth: String
     lateinit var authorisation: String
-}
\ No newline at end of file
+}
index 3190cd1..bb6937d 100644 (file)
@@ -18,6 +18,10 @@ package org.onap.ccsdk.cds.blueprintsprocessor.rest.service
 
 import org.apache.http.message.BasicHeader
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.BasicAuthRestClientProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestClientProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.springframework.http.HttpHeaders
 import org.springframework.http.MediaType
 import java.nio.charset.Charset
@@ -25,42 +29,43 @@ import java.util.*
 
 class BasicAuthRestClientService(private val restClientProperties:
                                  BasicAuthRestClientProperties) :
-        BlueprintWebClientService {
+    BlueprintWebClientService {
 
     override fun defaultHeaders(): Map<String, String> {
 
         val encodedCredentials = setBasicAuth(restClientProperties.username,
-                restClientProperties.password)
+            restClientProperties.password)
         return mapOf(
-                HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
-                HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE,
-                HttpHeaders.AUTHORIZATION to "Basic $encodedCredentials")
+            HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
+            HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE,
+            HttpHeaders.AUTHORIZATION to "Basic $encodedCredentials")
     }
 
     override fun host(uri: String): String {
         return restClientProperties.url + uri
     }
 
-    override fun convertToBasicHeaders(headers: Map<String, String>):
-            Array<BasicHeader> {
 
+    override fun convertToBasicHeaders(headers: Map<String, String>):
+        Array<BasicHeader> {
         val customHeaders: MutableMap<String, String> = headers.toMutableMap()
+        //inject additionalHeaders
+        customHeaders.putAll(verifyAdditionalHeaders(restClientProperties))
+
         if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) {
             val encodedCredentials = setBasicAuth(
-                    restClientProperties.username,
-                    restClientProperties.password)
+                restClientProperties.username,
+                restClientProperties.password)
             customHeaders[HttpHeaders.AUTHORIZATION] =
-                    "Basic $encodedCredentials"
+                "Basic $encodedCredentials"
         }
         return super.convertToBasicHeaders(customHeaders)
     }
 
     private fun setBasicAuth(username: String, password: String): String {
-
         val credentialsString = "$username:$password"
         return Base64.getEncoder().encodeToString(
-                credentialsString.toByteArray(Charset.defaultCharset()))
+            credentialsString.toByteArray(Charset.defaultCharset()))
     }
 
-
-}
\ No newline at end of file
+}
index 4f68657..8d4f0ca 100644 (file)
@@ -38,7 +38,7 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties:
                                            BluePrintProperties) {
 
     open fun blueprintWebClientService(jsonNode: JsonNode):
-            BlueprintWebClientService {
+        BlueprintWebClientService {
         val restClientProperties = restClientProperties(jsonNode)
         return blueprintWebClientService(restClientProperties)
     }
@@ -51,7 +51,7 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties:
 
     fun restClientProperties(prefix: String): RestClientProperties {
         val type = bluePrintProperties.propertyBeanType(
-                "$prefix.type", String::class.java)
+            "$prefix.type", String::class.java)
         return when (type) {
             RestLibConstants.TYPE_BASIC_AUTH -> {
                 basicAuthRestClientProperties(prefix)
@@ -76,7 +76,7 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties:
             }
             else -> {
                 throw BluePrintProcessorException("Rest adaptor($type) is" +
-                        " not supported")
+                    " not supported")
             }
         }
     }
@@ -86,43 +86,35 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties:
         val type = jsonNode.get("type").textValue()
         return when (type) {
             RestLibConstants.TYPE_TOKEN_AUTH -> {
-                JacksonUtils.readValue(jsonNode,
-                        TokenAuthRestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, TokenAuthRestClientProperties::class.java)!!
             }
             RestLibConstants.TYPE_BASIC_AUTH -> {
-                JacksonUtils.readValue(jsonNode,
-                        BasicAuthRestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, BasicAuthRestClientProperties::class.java)!!
             }
             RestLibConstants.TYPE_DME2_PROXY -> {
-                JacksonUtils.readValue(jsonNode,
-                        DME2RestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, DME2RestClientProperties::class.java)!!
             }
             RestLibConstants.TYPE_POLICY_MANAGER -> {
-                JacksonUtils.readValue(jsonNode,
-                        PolicyManagerRestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, PolicyManagerRestClientProperties::class.java)!!
             }
             RestLibConstants.TYPE_SSL_BASIC_AUTH -> {
-                JacksonUtils.readValue(jsonNode,
-                        SSLBasicAuthRestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, SSLBasicAuthRestClientProperties::class.java)!!
             }
             RestLibConstants.TYPE_SSL_TOKEN_AUTH -> {
-                JacksonUtils.readValue(jsonNode,
-                        SSLTokenAuthRestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, SSLTokenAuthRestClientProperties::class.java)!!
             }
             RestLibConstants.TYPE_SSL_NO_AUTH -> {
-                JacksonUtils.readValue(
-                        jsonNode, SSLRestClientProperties::class.java)!!
+                JacksonUtils.readValue(jsonNode, SSLRestClientProperties::class.java)!!
             }
             else -> {
-                throw BluePrintProcessorException("Rest adaptor($type) is" +
-                        " not supported")
+                throw BluePrintProcessorException(
+                    "Rest adaptor($type) is not supported")
             }
         }
     }
-    
-    private fun blueprintWebClientService(
-            restClientProperties: RestClientProperties):
-            BlueprintWebClientService {
+
+    private fun blueprintWebClientService(restClientProperties: RestClientProperties):
+        BlueprintWebClientService {
 
         when (restClientProperties) {
             is SSLRestClientProperties -> {
@@ -138,66 +130,65 @@ open class BluePrintRestLibPropertyService(private var bluePrintProperties:
                 return DME2ProxyRestClientService(restClientProperties)
             }
             else -> {
-                throw BluePrintProcessorException("couldn't get rest " +
-                        "service for")
+                throw BluePrintProcessorException("couldn't get rest service for type:${restClientProperties.type}  uri: ${restClientProperties.url}")
             }
         }
     }
 
     private fun tokenRestClientProperties(prefix: String):
-            TokenAuthRestClientProperties {
+        TokenAuthRestClientProperties {
         return bluePrintProperties.propertyBeanType(
-                prefix, TokenAuthRestClientProperties::class.java)
+            prefix, TokenAuthRestClientProperties::class.java)
     }
 
     private fun basicAuthRestClientProperties(prefix: String):
-            BasicAuthRestClientProperties {
+        BasicAuthRestClientProperties {
         return bluePrintProperties.propertyBeanType(
-                prefix, BasicAuthRestClientProperties::class.java)
+            prefix, BasicAuthRestClientProperties::class.java)
     }
 
     private fun sslBasicAuthRestClientProperties(prefix: String):
-            SSLRestClientProperties {
+        SSLRestClientProperties {
 
         val sslProps: SSLBasicAuthRestClientProperties =
-                bluePrintProperties.propertyBeanType(
-                        prefix, SSLBasicAuthRestClientProperties::class.java)
-        val basicProps : BasicAuthRestClientProperties =
-                bluePrintProperties.propertyBeanType(
-                        prefix, BasicAuthRestClientProperties::class.java)
+            bluePrintProperties.propertyBeanType(
+                prefix, SSLBasicAuthRestClientProperties::class.java)
+        val basicProps: BasicAuthRestClientProperties =
+            bluePrintProperties.propertyBeanType(
+                prefix, BasicAuthRestClientProperties::class.java)
         sslProps.basicAuth = basicProps
         return sslProps
     }
 
     private fun sslTokenAuthRestClientProperties(prefix: String):
-            SSLRestClientProperties {
+        SSLRestClientProperties {
 
         val sslProps: SSLTokenAuthRestClientProperties =
-                bluePrintProperties.propertyBeanType(prefix,
-                        SSLTokenAuthRestClientProperties::class.java)
-        val basicProps : TokenAuthRestClientProperties =
-                bluePrintProperties.propertyBeanType(prefix,
-                        TokenAuthRestClientProperties::class.java)
+            bluePrintProperties.propertyBeanType(prefix,
+                SSLTokenAuthRestClientProperties::class.java)
+        val basicProps: TokenAuthRestClientProperties =
+            bluePrintProperties.propertyBeanType(prefix,
+                TokenAuthRestClientProperties::class.java)
         sslProps.tokenAuth = basicProps
         return sslProps
     }
 
     private fun sslNoAuthRestClientProperties(prefix: String):
-            SSLRestClientProperties {
+        SSLRestClientProperties {
         return bluePrintProperties.propertyBeanType(
-                prefix, SSLRestClientProperties::class.java)
+            prefix, SSLRestClientProperties::class.java)
     }
 
     private fun dme2ProxyClientProperties(prefix: String):
-            DME2RestClientProperties {
+        DME2RestClientProperties {
         return bluePrintProperties.propertyBeanType(
-                prefix, DME2RestClientProperties::class.java)
+            prefix, DME2RestClientProperties::class.java)
     }
 
     private fun policyManagerRestClientProperties(prefix: String):
-            PolicyManagerRestClientProperties {
+        PolicyManagerRestClientProperties {
         return bluePrintProperties.propertyBeanType(
-                prefix, PolicyManagerRestClientProperties::class.java)
+            prefix, PolicyManagerRestClientProperties::class.java)
     }
 }
 
index 1acd07b..26c8088 100644 (file)
@@ -28,11 +28,14 @@ import org.apache.http.entity.StringEntity
 import org.apache.http.impl.client.CloseableHttpClient
 import org.apache.http.impl.client.HttpClients
 import org.apache.http.message.BasicHeader
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestClientProperties
+import org.onap.ccsdk.cds.blueprintsprocessor.rest.RestLibConstants
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.utils.WebClientUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintRetryException
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintIOUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
+import org.springframework.http.HttpHeaders
 import org.springframework.http.HttpMethod
 import java.io.IOException
 import java.io.InputStream
@@ -46,9 +49,9 @@ interface BlueprintWebClientService {
 
     fun httpClient(): CloseableHttpClient {
         return HttpClients.custom()
-                .addInterceptorFirst(WebClientUtils.logRequest())
-                .addInterceptorLast(WebClientUtils.logResponse())
-                .build()
+            .addInterceptorFirst(WebClientUtils.logRequest())
+            .addInterceptorLast(WebClientUtils.logResponse())
+            .build()
     }
 
     /** High performance non blocking Retry function, If execution block [block] throws BluePrintRetryException
@@ -82,10 +85,12 @@ interface BlueprintWebClientService {
             HttpMethod.POST -> post(path, request, convertedHeaders, String::class.java)
             HttpMethod.PUT -> put(path, request, convertedHeaders, String::class.java)
             HttpMethod.PATCH -> patch(path, request, convertedHeaders, String::class.java)
-            else -> throw BluePrintProcessorException("Unsupported methodType($methodType)")
+            else -> throw BluePrintProcessorException(
+                "Unsupported methodType($methodType) attempted on path($path)")
         }
     }
 
+    //TODO: convert to multi-map
     fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
         return headers.map { BasicHeader(it.key, it.value) }.toTypedArray()
     }
@@ -135,8 +140,8 @@ interface BlueprintWebClientService {
 
     @Throws(IOException::class, ClientProtocolException::class)
     private fun <T> performCallAndExtractTypedWebClientResponse(
-            httpUriRequest: HttpUriRequest, responseType: Class<T>):
-            WebClientResponse<T> {
+        httpUriRequest: HttpUriRequest, responseType: Class<T>):
+        WebClientResponse<T> {
         val httpResponse = httpClient().execute(httpUriRequest)
         val statusCode = httpResponse.statusLine.statusCode
         httpResponse.entity.content.use {
@@ -154,7 +159,7 @@ interface BlueprintWebClientService {
     }
 
     suspend fun <T> getNB(path: String, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>):
-            WebClientResponse<T> = withContext(Dispatchers.IO) {
+        WebClientResponse<T> = withContext(Dispatchers.IO) {
         get(path, additionalHeaders!!, responseType)
     }
 
@@ -191,27 +196,27 @@ interface BlueprintWebClientService {
     }
 
     suspend fun <T> deleteNB(path: String, additionalHeaders: Array<BasicHeader>?):
-            WebClientResponse<String> {
+        WebClientResponse<String> {
         return deleteNB(path, additionalHeaders, String::class.java)
     }
 
     suspend fun <T> deleteNB(path: String, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>):
-            WebClientResponse<T> = withContext(Dispatchers.IO) {
+        WebClientResponse<T> = withContext(Dispatchers.IO) {
         delete(path, additionalHeaders!!, responseType)
     }
 
     suspend fun <T> patchNB(path: String, request: Any, additionalHeaders: Array<BasicHeader>?, responseType: Class<T>):
-            WebClientResponse<T> = withContext(Dispatchers.IO) {
+        WebClientResponse<T> = withContext(Dispatchers.IO) {
         patch(path, request, additionalHeaders!!, responseType)
     }
 
     suspend fun exchangeNB(methodType: String, path: String, request: Any): WebClientResponse<String> {
         return exchangeNB(methodType, path, request, hashMapOf(),
-                String::class.java)
+            String::class.java)
     }
 
     suspend fun exchangeNB(methodType: String, path: String, request: Any, additionalHeaders: Map<String, String>?):
-            WebClientResponse<String> {
+        WebClientResponse<String> {
         return exchangeNB(methodType, path, request, additionalHeaders, String::class.java)
     }
 
@@ -249,7 +254,7 @@ interface BlueprintWebClientService {
     }
 
     private fun basicHeaders(headers: Map<String, String>?):
-            Array<BasicHeader> {
+        Array<BasicHeader> {
         val basicHeaders = mutableListOf<BasicHeader>()
         defaultHeaders().forEach { (name, value) ->
             basicHeaders.add(BasicHeader(name, value))
@@ -263,11 +268,29 @@ interface BlueprintWebClientService {
     // Non Blocking Rest Implementation
     suspend fun httpClientNB(): CloseableHttpClient {
         return HttpClients.custom()
-                .addInterceptorFirst(WebClientUtils.logRequest())
-                .addInterceptorLast(WebClientUtils.logResponse())
-                .build()
+            .addInterceptorFirst(WebClientUtils.logRequest())
+            .addInterceptorLast(WebClientUtils.logResponse())
+            .build()
     }
 
     //TODO maybe there could be cases where we care about return headers?
     data class WebClientResponse<T>(val status: Int, val body: T)
+
+    fun verifyAdditionalHeaders(restClientProperties: RestClientProperties): Map<String, String> {
+        val customHeaders: MutableMap<String, String> = mutableMapOf()
+        //Extract additionalHeaders from the requestProperties and
+        //throw an error if HttpHeaders.AUTHORIZATION key (headers are case-insensitive)
+        restClientProperties.additionalHeaders?.let {
+            if (it.keys.map { k -> k.toLowerCase().trim() }.contains(HttpHeaders.AUTHORIZATION.toLowerCase())) {
+                val errMsg = "Error in definition of endpoint ${restClientProperties.url}." +
+                    " User-supplied \"additionalHeaders\" cannot contain AUTHORIZATION header with" +
+                    " auth-type \"${RestLibConstants.TYPE_BASIC_AUTH}\""
+                WebClientUtils.log.error(errMsg)
+                throw BluePrintProcessorException(errMsg)
+            } else {
+                customHeaders.putAll(it)
+            }
+        }
+        return customHeaders
+    }
 }
index 30dd490..2acf776 100644 (file)
@@ -33,25 +33,31 @@ import java.io.FileInputStream
 import java.security.KeyStore
 import java.security.cert.X509Certificate
 
-class SSLRestClientService(private val restClientProperties:
-                           SSLRestClientProperties) :
-        BlueprintWebClientService {
+class SSLRestClientService(private val restClientProperties: SSLRestClientProperties) :
+    BlueprintWebClientService {
 
     var auth: BlueprintWebClientService? = null
 
     init {
-         auth = getAuthService()
+        auth = getAuthService()
     }
 
-    private fun getAuthService() : BlueprintWebClientService? {
-
-        return when(restClientProperties) {
+    private fun getAuthService(): BlueprintWebClientService? {
+        //type,url and additional headers don't get carried over to TokenAuthRestClientProperties from SSLTokenAuthRestClientProperties
+        //set them in auth obj to be consistent. TODO: refactor
+        return when (restClientProperties) {
             is SSLBasicAuthRestClientProperties -> {
-                val basic =  restClientProperties.basicAuth!!
-                BasicAuthRestClientService(basic)
+                val basicAuthProps = restClientProperties.basicAuth!!
+                basicAuthProps.additionalHeaders = restClientProperties.additionalHeaders
+                basicAuthProps.url = restClientProperties.url
+                basicAuthProps.type = restClientProperties.type
+                BasicAuthRestClientService(basicAuthProps)
             }
             is SSLTokenAuthRestClientProperties -> {
-                val token =  restClientProperties.tokenAuth!!
+                val token = restClientProperties.tokenAuth!!
+                token.additionalHeaders = restClientProperties.additionalHeaders
+                token.url = restClientProperties.url
+                token.type = restClientProperties.type
                 TokenAuthRestClientService(token)
             }
             else -> {
@@ -61,19 +67,16 @@ class SSLRestClientService(private val restClientProperties:
         }
     }
 
-
     override fun defaultHeaders(): Map<String, String> {
-
         if (auth != null) {
             return auth!!.defaultHeaders()
         }
         return mapOf(
-                HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
-                HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE)
+            HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
+            HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE)
     }
 
     override fun host(uri: String): String {
-
         return restClientProperties.url + uri
     }
 
@@ -85,8 +88,9 @@ class SSLRestClientService(private val restClientProperties:
         val sslTrust = restClientProperties.sslTrust
         val sslTrustPwd = restClientProperties.sslTrustPassword
 
-        val acceptingTrustStrategy = { chain: Array<X509Certificate>,
-                                       authType: String -> true }
+        val acceptingTrustStrategy = { _: Array<X509Certificate>, _: String ->
+            true
+        }
         val sslContext = SSLContextBuilder.create()
 
         if (sslKey != null && sslKeyPwd != null) {
@@ -98,13 +102,12 @@ class SSLRestClientService(private val restClientProperties:
         }
 
         sslContext.loadTrustMaterial(File(sslTrust), sslTrustPwd.toCharArray(),
-                acceptingTrustStrategy)
+            acceptingTrustStrategy)
         val csf = SSLConnectionSocketFactory(sslContext.build())
         return HttpClients.custom()
-                .addInterceptorFirst(WebClientUtils.logRequest())
-                .addInterceptorLast(WebClientUtils.logResponse())
-                .setSSLSocketFactory(csf).build()
-
+            .addInterceptorFirst(WebClientUtils.logRequest())
+            .addInterceptorLast(WebClientUtils.logResponse())
+            .setSSLSocketFactory(csf).build()
     }
 
     // Non Blocking Rest Implementation
@@ -113,13 +116,15 @@ class SSLRestClientService(private val restClientProperties:
     }
 
     override fun convertToBasicHeaders(headers: Map<String, String>): Array<BasicHeader> {
-        var head1: Map<String, String> = defaultHeaders()
-        var head2: MutableMap<String, String> = head1.toMutableMap()
-        head2.putAll(headers)
+        val mergedDefaultAndSuppliedHeaders = defaultHeaders().plus(headers)
+        //During the initialization, getAuthService() sets the auth variable.
+        //If it's not null, then we have an authentication mechanism.
+        //If null - indicates no-auth used
         if (auth != null) {
-            return auth!!.convertToBasicHeaders(head2)
+            return auth!!.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders)
         }
-        return super.convertToBasicHeaders(head2)
+        //inject additionalHeaders
+        return super.convertToBasicHeaders(mergedDefaultAndSuppliedHeaders
+            .plus(verifyAdditionalHeaders(restClientProperties)))
     }
-
-}
\ No newline at end of file
+}
index 8244699..73b5341 100644 (file)
@@ -23,20 +23,20 @@ import org.springframework.http.MediaType
 
 class TokenAuthRestClientService(private val restClientProperties:
                                  TokenAuthRestClientProperties) :
-        BlueprintWebClientService {
+    BlueprintWebClientService {
 
     override fun defaultHeaders(): Map<String, String> {
-
         return mapOf(
-                HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
-                HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE,
-                HttpHeaders.AUTHORIZATION to restClientProperties.token!!)
+            HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE,
+            HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE,
+            HttpHeaders.AUTHORIZATION to restClientProperties.token!!)
     }
 
     override fun convertToBasicHeaders(headers: Map<String, String>):
-            Array<BasicHeader> {
-
+        Array<BasicHeader> {
         val customHeaders: MutableMap<String, String> = headers.toMutableMap()
+        //inject additionalHeaders
+        customHeaders.putAll(verifyAdditionalHeaders(restClientProperties))
         if (!headers.containsKey(HttpHeaders.AUTHORIZATION)) {
             customHeaders[HttpHeaders.AUTHORIZATION] = restClientProperties.token!!
         }
index 37a797f..b617dab 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright © 2017-2018 AT&T Intellectual Property.
  * Modifications Copyright © 2018 IBM.
  * Modifications Copyright © 2019 Huawei.
+ * Modifications 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.
@@ -28,11 +29,15 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.BluePrintRestLibConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLBasicAuthRestClientProperties
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLRestClientProperties
 import org.onap.ccsdk.cds.blueprintsprocessor.rest.SSLTokenAuthRestClientProperties
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
 import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.HttpHeaders
+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 kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
 import kotlin.test.assertNotNull
 
 @RunWith(SpringRunner::class)
@@ -63,26 +68,25 @@ import kotlin.test.assertNotNull
     "blueprintsprocessor.restclient.ssl.sslKeyPassword=changeit"
 ])
 class BluePrintRestLibPropertyServiceTest {
-
     @Autowired
     lateinit var bluePrintRestLibPropertyService: BluePrintRestLibPropertyService
 
     @Test
     fun testRestClientProperties() {
         val properties = bluePrintRestLibPropertyService.restClientProperties(
-                "blueprintsprocessor.restclient.sample")
+            "blueprintsprocessor.restclient.sample")
         assertNotNull(properties, "failed to create property bean")
         assertNotNull(properties.url, "failed to get url property in" +
-                " property bean")
+            " property bean")
     }
 
     @Test
     fun testSSLBasicProperties() {
         val properties = bluePrintRestLibPropertyService.restClientProperties(
-                "blueprintsprocessor.restclient.sslbasic")
+            "blueprintsprocessor.restclient.sslbasic")
         assertNotNull(properties, "failed to create property bean")
         val p: SSLBasicAuthRestClientProperties =
-                properties as SSLBasicAuthRestClientProperties
+            properties as SSLBasicAuthRestClientProperties
 
         assertEquals(p.basicAuth!!.username, "admin")
         assertEquals(p.basicAuth!!.password, "cds")
@@ -94,11 +98,11 @@ class BluePrintRestLibPropertyServiceTest {
     @Test
     fun testSSLTokenProperties() {
         val properties = bluePrintRestLibPropertyService.restClientProperties(
-                "blueprintsprocessor.restclient.ssltoken")
+            "blueprintsprocessor.restclient.ssltoken")
         assertNotNull(properties, "failed to create property bean")
 
         val p: SSLTokenAuthRestClientProperties =
-                properties as SSLTokenAuthRestClientProperties
+            properties as SSLTokenAuthRestClientProperties
 
         assertEquals(p.tokenAuth!!.token!!, "72178473kjshdkjgvbsdkjv903274908")
         assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
@@ -109,11 +113,11 @@ class BluePrintRestLibPropertyServiceTest {
     @Test
     fun testSSLNoAuthProperties() {
         val properties = bluePrintRestLibPropertyService.restClientProperties(
-                "blueprintsprocessor.restclient.ssl")
+            "blueprintsprocessor.restclient.ssl")
         assertNotNull(properties, "failed to create property bean")
 
         val p: SSLRestClientProperties =
-                properties as SSLRestClientProperties
+            properties as SSLRestClientProperties
 
         assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
         assertEquals(p.sslTrustPassword, "changeit")
@@ -125,113 +129,370 @@ class BluePrintRestLibPropertyServiceTest {
 
     @Test
     fun testSSLBasicPropertiesAsJson() {
-        val json: String = "{\n" +
-                "  \"type\" : \"ssl-basic-auth\",\n" +
-                "  \"url\" : \"https://localhost:8443\",\n" +
-                "  \"keyStoreInstance\" : \"PKCS12\",\n" +
-                "  \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" +
-                "  \"sslTrustPassword\" : \"changeit\",\n" +
-                "  \"basicAuth\" : {\n" +
-                "    \"username\" : \"admin\",\n" +
-                "    \"password\" : \"cds\"\n" +
-                "  }\n" +
-                "}"
-        val mapper = ObjectMapper()
-        val actualObj: JsonNode = mapper.readTree(json)
+        val actualObj: JsonNode = defaultMapper.readTree(sslBasicAuthEndpointWithHeadersField())
         val properties = bluePrintRestLibPropertyService.restClientProperties(
-                actualObj)
+            actualObj)
         assertNotNull(properties, "failed to create property bean")
-        val p: SSLBasicAuthRestClientProperties =
-                properties as SSLBasicAuthRestClientProperties
+        val p: SSLBasicAuthRestClientProperties = properties as SSLBasicAuthRestClientProperties
 
-        assertEquals(p.basicAuth!!.username, "admin")
-        assertEquals(p.basicAuth!!.password, "cds")
-        assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
-        assertEquals(p.sslTrustPassword, "changeit")
-        assertEquals(p.keyStoreInstance, "PKCS12")
+        assertEquals("admin", p.basicAuth!!.username)
+        assertEquals("cds", p.basicAuth!!.password)
+        assertEquals("src/test/resources/keystore.p12", p.sslTrust)
+        assertEquals("changeit", p.sslTrustPassword)
+        assertEquals("PKCS12", p.keyStoreInstance)
+        assertEquals("ssl-basic-auth", p.type)
+        assertEquals("https://localhost:8443", p.url)
     }
 
     @Test
     fun testSSLTokenPropertiesAsJson() {
-        val json: String = "{\n" +
-                "  \"type\" : \"ssl-token-auth\",\n" +
-                "  \"url\" : \"https://localhost:8443\",\n" +
-                "  \"keyStoreInstance\" : \"PKCS12\",\n" +
-                "  \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" +
-                "  \"sslTrustPassword\" : \"changeit\",\n" +
-                "  \"tokenAuth\" : {\n" +
-                "    \"token\" : \"72178473kjshdkjgvbsdkjv903274908\"\n" +
-                "  }\n" +
-                "}"
-        val mapper = ObjectMapper()
-        val actualObj: JsonNode = mapper.readTree(json)
-        val properties = bluePrintRestLibPropertyService.restClientProperties(
-                actualObj)
+        val actualObj: JsonNode = defaultMapper.readTree(sslTokenAuthEndpointWithHeadersField())
+        val properties =
+            bluePrintRestLibPropertyService.restClientProperties(actualObj)
         assertNotNull(properties, "failed to create property bean")
 
-        val p: SSLTokenAuthRestClientProperties =
-                properties as SSLTokenAuthRestClientProperties
+        val p: SSLTokenAuthRestClientProperties = properties as SSLTokenAuthRestClientProperties
 
-        assertEquals(p.tokenAuth!!.token!!, "72178473kjshdkjgvbsdkjv903274908")
-        assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
-        assertEquals(p.sslTrustPassword, "changeit")
-        assertEquals(p.keyStoreInstance, "PKCS12")
+        assertEquals("72178473kjshdkjgvbsdkjv903274908", p.tokenAuth!!.token!!)
+        assertEquals("src/test/resources/keystore.p12", p.sslTrust)
+        assertEquals("changeit", p.sslTrustPassword)
+        assertEquals("PKCS12", p.keyStoreInstance)
+        assertEquals("ssl-token-auth", p.type)
+        assertEquals("https://localhost:8443", p.url)
     }
 
     @Test
     fun testSSLNoAuthPropertiesAsJson() {
-        val json: String = "{\n" +
-                "  \"type\" : \"ssl-basic-auth\",\n" +
-                "  \"url\" : \"https://localhost:8443\",\n" +
-                "  \"keyStoreInstance\" : \"PKCS12\",\n" +
-                "  \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" +
-                "  \"sslTrustPassword\" : \"changeit\",\n" +
-                "  \"sslKey\" : \"src/test/resources/keystore.p12\",\n" +
-                "  \"sslKeyPassword\" : \"changeit\"\n" +
-                "}"
-        val mapper = ObjectMapper()
-        val actualObj: JsonNode = mapper.readTree(json)
+        val actualObj: JsonNode = defaultMapper.readTree(sslNoAuthEndpointWithHeadersField())
         val properties = bluePrintRestLibPropertyService.restClientProperties(
-                actualObj)
+            actualObj)
         assertNotNull(properties, "failed to create property bean")
 
         val p: SSLRestClientProperties =
-                properties as SSLRestClientProperties
+            properties as SSLRestClientProperties
 
-        assertEquals(p.sslTrust, "src/test/resources/keystore.p12")
-        assertEquals(p.sslTrustPassword, "changeit")
-        assertEquals(p.keyStoreInstance, "PKCS12")
-        assertEquals(p.sslKey, "src/test/resources/keystore.p12")
-        assertEquals(p.sslKeyPassword, "changeit")
+        assertEquals("src/test/resources/keystore.p12", p.sslTrust)
+        assertEquals("changeit", p.sslTrustPassword)
+        assertEquals("PKCS12", p.keyStoreInstance)
+        assertEquals("src/test/resources/keystore.p12", p.sslKey)
+        assertEquals("changeit", p.sslKeyPassword)
+        assertEquals("ssl-no-auth", p.type)
+        assertEquals("https://localhost:8443", p.url)
     }
 
     @Test
     fun testBlueprintWebClientService() {
         val blueprintWebClientService = bluePrintRestLibPropertyService
-                .blueprintWebClientService("sample")
-        assertNotNull(blueprintWebClientService, "failed to create blu" +
-                "eprintWebClientService")
+            .blueprintWebClientService("sample")
+        assertNotNull(blueprintWebClientService,
+            "failed to create blueprintWebClientService")
     }
 
     @Test
     fun testBlueprintWebClientServiceWithJsonNode() {
-        val json: String = "{\n" +
-                "  \"type\" : \"ssl-basic-auth\",\n" +
-                "  \"url\" : \"https://localhost:8443\",\n" +
-                "  \"keyStoreInstance\" : \"PKCS12\",\n" +
-                "  \"sslTrust\" : \"src/test/resources/keystore.p12\",\n" +
-                "  \"sslTrustPassword\" : \"changeit\",\n" +
-                "  \"basicAuth\" : {\n" +
-                "    \"username\" : \"admin\",\n" +
-                "    \"password\" : \"cds\"\n" +
-                "  }\n" +
-                "}"
-        val mapper = ObjectMapper()
-        val actualObj: JsonNode = mapper.readTree(json)
+        val actualObj: JsonNode = defaultMapper.readTree(sslBasicAuthEndpointWithHeadersField())
         val blueprintWebClientService = bluePrintRestLibPropertyService
-                .blueprintWebClientService(actualObj)
-        assertNotNull(blueprintWebClientService, "failed to create blu" +
-                "eprintWebClientService")
+            .blueprintWebClientService(actualObj)
+        assertNotNull(blueprintWebClientService, "failed to create blueprintWebClientService")
+    }
+
+    //pass the result of $typeEndpointWithHeadersField() output with and without headers to compare.
+    private fun validateHeadersDidNotChangeWithEmptyAdditionalHeaders(noHeaders: String, withHeaders: String) {
+        val parsedObj: JsonNode = defaultMapper.readTree(noHeaders)
+        val bpWebClientService =
+            bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
+        val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
+
+        val parsedObjWithHeaders: JsonNode = defaultMapper.readTree(withHeaders)
+        val bpWebClientServiceWithHeaders =
+            bluePrintRestLibPropertyService.blueprintWebClientService(parsedObjWithHeaders)
+        val extractedHeadersWithAdditionalHeaders = bpWebClientServiceWithHeaders.convertToBasicHeaders(mapOf())
+        //Array<BasicHeader<>> -> Map<String,String>
+        val headersMap = extractedHeaders.map { it.name to it.value }.toMap()
+        val additionalHeadersMap = extractedHeadersWithAdditionalHeaders.map { it.name to it.value }.toMap()
+        assertEquals(headersMap, additionalHeadersMap)
+    }
+
+    @Test
+    fun `BasicAuth WebClientService with empty additionalHeaders does not modify headers`() {
+        val endPointJson = basicAuthEndpointWithHeadersField()
+        val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(emptyAdditionalHeaders)
+        validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
+    }
+
+    private fun acceptsOneAdditionalHeadersTest(endPointWithHeadersJson: String) {
+        val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
+        val bpWebClientService =
+            bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
+        val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
+        assertEquals(1, extractedHeaders.filter { it.name == "key1" }.count())
+    }
+
+    @Test
+    fun `BasicAuth WebClientService accepts one additionalHeaders`() {
+        val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(oneAdditionalParameter)
+        acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
+    }
+
+    private fun acceptsMultipleAdditionalHeaders(endPointWithHeadersJson: String) {
+        val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
+        val bpWebClientService =
+            bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
+        val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
+        assertEquals(1, extractedHeaders.filter { it.name == "key1" }.count())
+        assertEquals(1, extractedHeaders.filter { it.name == "key2" }.count())
+        assertEquals(1, extractedHeaders.filter { it.name == "key3" }.count())
+    }
+
+    @Test
+    fun `BasicAuth WebClientService accepts multiple additionalHeaders`() {
+        val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(threeAdditionalHeaders)
+        acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
+    }
+
+    private fun additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson: String) {
+        val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
+        val bpWebClientService =
+            bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
+        val extractedHeaders = bpWebClientService.convertToBasicHeaders(mapOf())
+        assertEquals(MediaType.APPLICATION_XML.toString(),
+            extractedHeaders.filter { it.name == HttpHeaders.CONTENT_TYPE }[0].value!!)
+    }
+
+    @Test
+    fun `BasicAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
+        //default content type is application/json
+        val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
+        additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
+    }
+
+    //called from within "assertFailsWith(exceptionClass = BluePrintProcessorException::class) {"
+    private fun attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson: String) {
+        val parsedObj: JsonNode = defaultMapper.readTree(endPointWithHeadersJson)
+        val bpWebClientService =
+            bluePrintRestLibPropertyService.blueprintWebClientService(parsedObj)
+        bpWebClientService.convertToBasicHeaders(mapOf())
+    }
+
+    @Test
+    fun `BasicAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(additionalHeadersWithAuth)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+        //spec says headers are case insensitive...
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = basicAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+    }
+
+    @Test
+    fun `TokenAuth WebClientService with empty additionalHeaders does not modify headers`() {
+        val endPointJson = sslTokenAuthEndpointWithHeadersField()
+        val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(emptyAdditionalHeaders)
+        validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `TokenAuth WebClientService accepts one additionalHeaders`() {
+        val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(oneAdditionalParameter)
+        acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `TokenAuth WebClientService accepts multiple additionalHeaders`() {
+        val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(threeAdditionalHeaders)
+        acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `TokenAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
+        //default content type is application/json
+        val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
+        additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `TokenAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(additionalHeadersWithAuth)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+        //spec says headers are case insensitive...
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = sslTokenAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+    }
+
+    //TESTS FOR SSL BASIC AUTH headers
+    @Test
+    fun `SSLBasicAuth WebClientService with empty additionalHeaders does not modify headers`() {
+        val endPointJson = sslBasicAuthEndpointWithHeadersField()
+        val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(emptyAdditionalHeaders)
+        validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLBasicAuth WebClientService accepts one additionalHeaders`() {
+        val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(oneAdditionalParameter)
+        acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLBasicAuth WebClientService accepts multiple additionalHeaders`() {
+        val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(threeAdditionalHeaders)
+        acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLBasicAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
+        //default content type is application/json
+        val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
+        additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLBasicAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(additionalHeadersWithAuth)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+        //spec says headers are case insensitive...
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = sslBasicAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+    }
+
+    //SSL-NO-AUTH headers tests
+    @Test
+    fun `SSLNoAuth WebClientService with empty additionalHeaders does not modify headers`() {
+        val endPointJson = sslNoAuthEndpointWithHeadersField()
+        val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(emptyAdditionalHeaders)
+        validateHeadersDidNotChangeWithEmptyAdditionalHeaders(endPointJson, endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLNoAuth WebClientService accepts one additionalHeaders`() {
+        val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(oneAdditionalParameter)
+        acceptsOneAdditionalHeadersTest(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLNoAuth WebClientService accepts multiple additionalHeaders`() {
+        val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(threeAdditionalHeaders)
+        acceptsMultipleAdditionalHeaders(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLNoAuth WebClientService additionalHeaders can overwrite default Content-Type`() {
+        //default content type is application/json
+        val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(contentTypeAdditionalHeader)
+        additionalHeadersChangedContentTypeToAPPLICATION_XML(endPointWithHeadersJson)
+    }
+
+    @Test
+    fun `SSLNoAuth WebClientService throws BlueprintProcessorException if additionalHeaders contain Authorization`() {
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(additionalHeadersWithAuth)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+        //spec says headers are case insensitive...
+        assertFailsWith(exceptionClass = BluePrintProcessorException::class) {
+            val endPointWithHeadersJson = sslNoAuthEndpointWithHeadersField(additionalHeadersWithAuthLowercased)
+            attemptToPutAuthorizationHeaderIntoAdditionalHeaders(endPointWithHeadersJson)
+        }
+    }
+
+    companion object BluePrintRestLibPropertyServiceTest {
+        val defaultMapper = ObjectMapper()
+        val expectedTokenAuthDefaultHeaders = mapOf<String, String>(
+            "Content-Type" to "application/json",
+            "Accept" to "application/json",
+            "Authorization" to "72178473kjshdkjgvbsdkjv903274908")
+
+        val endPointWithHeadersJsonWithBasicAuthHeader = basicAuthEndpointWithHeadersField(""",
+              "additionalHeaders" : {
+                 "authorization": "Basic aGF2ZTphbmljZWRheQo="
+              }""".trimIndent())
+
+        private fun sslTokenAuthEndpointWithHeadersField(headers: String = ""): String =
+            """{
+            "type" : "ssl-token-auth",
+            "url" : "https://localhost:8443",
+            "keyStoreInstance" : "PKCS12",
+            "sslTrust" : "src/test/resources/keystore.p12",
+            "sslTrustPassword" : "changeit",
+              "tokenAuth" : {
+                "token" : "72178473kjshdkjgvbsdkjv903274908"
+              }$headers
+            }
+            """.trimIndent()
+
+        private fun sslBasicAuthEndpointWithHeadersField(headers: String = ""): String =
+            """{
+          "type" : "ssl-basic-auth",
+          "url" : "https://localhost:8443",
+          "keyStoreInstance" : "PKCS12",
+          "sslTrust" : "src/test/resources/keystore.p12",
+          "sslTrustPassword" : "changeit",
+          "basicAuth" : {
+            "username" : "admin",
+            "password" : "cds"
+          }$headers
+        }""".trimIndent()
+
+        private fun sslNoAuthEndpointWithHeadersField(headers: String = ""): String = """{
+          "type" : "ssl-no-auth",
+          "url" : "https://localhost:8443",
+          "keyStoreInstance" : "PKCS12",
+          "sslTrust" : "src/test/resources/keystore.p12",
+          "sslTrustPassword" : "changeit",
+          "sslKey" : "src/test/resources/keystore.p12",
+          "sslKeyPassword" : "changeit"$headers
+        }""".trimIndent()
+
+        //Don't forget to supply "," as the first char to make valid JSON
+        private fun basicAuthEndpointWithHeadersField(headers: String = ""): String =
+            """{
+              "type": "basic-auth",
+              "url": "http://127.0.0.1:8000",
+              "username": "user",
+              "password": "pass"$headers
+            }""".trimIndent()
+
+        private val emptyAdditionalHeaders = """,
+          "additionalHeaders" : {
+          }""".trimIndent()
+
+        private val oneAdditionalParameter = """,
+          "additionalHeaders" : {
+            "key1": "value1"
+          }""".trimIndent()
+
+        private val threeAdditionalHeaders = """,
+          "additionalHeaders" : {
+            "key1": "value1",
+            "key2": "value2",
+            "key3": "value3"
+          }""".trimIndent()
+
+        private val contentTypeAdditionalHeader = """,
+          "additionalHeaders" : {
+            "${HttpHeaders.CONTENT_TYPE}": "${MediaType.APPLICATION_XML}"
+          }""".trimIndent()
+
+        private val additionalHeadersWithAuth = """,
+          "additionalHeaders" : {
+             "Authorization": "Basic aGF2ZTphbmljZWRheQo="
+          }""".trimIndent()
+
+        private val additionalHeadersWithAuthLowercased = """,
+          "additionalHeaders" : {
+             "authorization": "Basic aGF2ZTphbmljZWRheQo="
+          }""".trimIndent()
     }
 }
 
index a13d0cc..ff09b83 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>commons</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
index f34a1ec..b09a8ac 100644 (file)
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>inbounds</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
     <artifactId>configs-api</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>jar</packaging>
     <name>Blueprints Processor Resource Configurations API</name>
     <description>Blueprints Processor Resource Configurations API</description>
index 8f6d32e..12cb8ae 100644 (file)
@@ -18,7 +18,7 @@
     <parent>
         <artifactId>inbounds</artifactId>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>designer-api</artifactId>
  * limitations under the License.
  */
 
-package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
+package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
 
+import com.google.protobuf.ByteString
 import io.grpc.StatusException
 import io.grpc.stub.StreamObserver
 import kotlinx.coroutines.runBlocking
-import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.utils.currentTimestamp
+import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.BluePrintModelHandler
 import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader
 import org.onap.ccsdk.cds.controllerblueprints.common.api.Status
-import org.onap.ccsdk.cds.controllerblueprints.core.*
-import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
-import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
-import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.emptyTONull
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.currentTimestamp
 import org.onap.ccsdk.cds.controllerblueprints.management.api.*
 import org.slf4j.LoggerFactory
 import org.springframework.security.access.prepost.PreAuthorize
 import org.springframework.stereotype.Service
-import java.io.File
-import java.util.*
 
-// TODO("move to management-api or designer-api module")
 @Service
-open class BluePrintManagementGRPCHandler(private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
-                                          private val blueprintsProcessorCatalogService: BluePrintCatalogService)
+open class BluePrintManagementGRPCHandler(private val bluePrintModelHandler: BluePrintModelHandler)
     : BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() {
 
     private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java)
@@ -47,30 +43,24 @@ open class BluePrintManagementGRPCHandler(private val bluePrintLoadConfiguration
     @PreAuthorize("hasRole('USER')")
     override fun uploadBlueprint(request: BluePrintUploadInput, responseObserver:
     StreamObserver<BluePrintManagementOutput>) {
-        runBlocking {
 
+        runBlocking {
             log.info("request(${request.commonHeader.requestId})")
-            val uploadId = UUID.randomUUID().toString()
-            val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, uploadId)
-            val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, uploadId)
             try {
-                val cbaFile = normalizedFile(blueprintArchive, "cba.zip")
-
-                saveToDisk(request, cbaFile)
-
+                /** Get the file byte array */
+                val byteArray = request.fileChunk.chunk.toByteArray()
+                /** Get the Upload Action */
                 val uploadAction = request.actionIdentifiers?.actionName.emptyTONull()
                         ?: UploadAction.DRAFT.toString()
 
                 when (uploadAction) {
                     UploadAction.DRAFT.toString() -> {
-                        val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(uploadId, cbaFile, false)
-                        responseObserver.onNext(successStatus("Successfully uploaded CBA($blueprintId)...",
-                                request.commonHeader))
+                        val blueprintModel = bluePrintModelHandler.upload(byteArray, false)
+                        responseObserver.onNext(successStatus(request.commonHeader))
                     }
                     UploadAction.PUBLISH.toString() -> {
-                        val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(uploadId, cbaFile, true)
-                        responseObserver.onNext(successStatus("Successfully uploaded CBA($blueprintId)...",
-                                request.commonHeader))
+                        val blueprintModel = bluePrintModelHandler.upload(byteArray, true)
+                        responseObserver.onNext(successStatus(request.commonHeader))
                     }
                     UploadAction.VALIDATE.toString() -> {
                         //TODO("Not Implemented")
@@ -78,21 +68,17 @@ open class BluePrintManagementGRPCHandler(private val bluePrintLoadConfiguration
                                 BluePrintProcessorException("Not Implemented")))
                     }
                     UploadAction.ENRICH.toString() -> {
-                        //TODO("Not Implemented")
-                        responseObserver.onError(failStatus("Not Implemented",
-                                BluePrintProcessorException("Not Implemented")))
+                        val enrichedByteArray = bluePrintModelHandler.enrichBlueprintFileSource(byteArray)
+                        responseObserver.onNext(enrichmentStatus(request.commonHeader, enrichedByteArray))
+                    }
+                    else -> {
+                        responseObserver.onError(failStatus("Upload action($uploadAction) not implemented",
+                                BluePrintProcessorException("Upload action($uploadAction) not implemented")))
                     }
                 }
                 responseObserver.onCompleted()
             } catch (e: Exception) {
                 responseObserver.onError(failStatus("request(${request.commonHeader.requestId}): Failed to upload CBA", e))
-            } finally {
-                // Clean blueprint script cache
-                val cacheKey = BluePrintFileUtils
-                        .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, uploadId))
-                BluePrintCompileCache.cleanClassLoader(cacheKey)
-                deleteNBDir(blueprintArchive)
-                deleteNBDir(blueprintWorking)
             }
         }
     }
@@ -107,11 +93,9 @@ open class BluePrintManagementGRPCHandler(private val bluePrintLoadConfiguration
             val blueprint = "blueprint $blueprintName:$blueprintVersion"
 
             log.info("request(${request.commonHeader.requestId}): Received delete $blueprint")
-
-
             try {
-                blueprintsProcessorCatalogService.deleteFromDatabase(blueprintName, blueprintVersion)
-                responseObserver.onNext(successStatus("Successfully deleted $blueprint", request.commonHeader))
+                bluePrintModelHandler.deleteBlueprintModel(blueprintName, blueprintVersion)
+                responseObserver.onNext(successStatus(request.commonHeader))
                 responseObserver.onCompleted()
             } catch (e: Exception) {
                 responseObserver.onError(failStatus("request(${request.commonHeader.requestId}): Failed to delete $blueprint", e))
@@ -119,25 +103,23 @@ open class BluePrintManagementGRPCHandler(private val bluePrintLoadConfiguration
         }
     }
 
-    private fun saveToDisk(request: BluePrintUploadInput, cbaFile: File) {
-        log.info("request(${request.commonHeader.requestId}): Writing CBA File under :${cbaFile.absolutePath}")
-
-        // Recreate Folder
-        cbaFile.parentFile.reCreateDirs()
-
-        // Write the File
-        cbaFile.writeBytes(request.fileChunk.chunk.toByteArray()).apply {
-            log.info("request(${request.commonHeader.requestId}): CBA file(${cbaFile.absolutePath} written successfully")
-        }
-
-    }
+    private fun enrichmentStatus(header: CommonHeader, byteArray: ByteArray): BluePrintManagementOutput =
+            BluePrintManagementOutput.newBuilder()
+                    .setCommonHeader(header)
+                    .setFileChunk(FileChunk.newBuilder().setChunk(ByteString.copyFrom(byteArray)))
+                    .setStatus(Status.newBuilder()
+                            .setTimestamp(currentTimestamp())
+                            .setMessage(BluePrintConstants.STATUS_SUCCESS)
+                            .setCode(200)
+                            .build())
+                    .build()
 
-    private fun successStatus(message: String, header: CommonHeader): BluePrintManagementOutput =
+    private fun successStatus(header: CommonHeader): BluePrintManagementOutput =
             BluePrintManagementOutput.newBuilder()
                     .setCommonHeader(header)
                     .setStatus(Status.newBuilder()
                             .setTimestamp(currentTimestamp())
-                            .setMessage(message)
+                            .setMessage(BluePrintConstants.STATUS_SUCCESS)
                             .setCode(200)
                             .build())
                     .build()
index f67ed25..4d13486 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
 
+import io.swagger.annotations.ApiOperation
+import io.swagger.annotations.ApiParam
 import kotlinx.coroutines.runBlocking
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModelSearch
 import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler.BluePrintModelHandler
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
 import org.springframework.core.io.Resource
 import org.springframework.http.MediaType
 import org.springframework.http.ResponseEntity
 import org.springframework.http.codec.multipart.FilePart
+import org.springframework.security.access.prepost.PreAuthorize
 import org.springframework.web.bind.annotation.*
 
 /**
@@ -40,18 +43,21 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
     @PostMapping("", produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun saveBlueprint(@RequestPart("file") filePart: FilePart): BlueprintModelSearch = runBlocking {
         bluePrintModelHandler.saveBlueprintModel(filePart)
     }
 
     @GetMapping("", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
+    @PreAuthorize("hasRole('USER')")
     fun allBlueprintModel(): List<BlueprintModelSearch> {
         return this.bluePrintModelHandler.allBlueprintModel()
     }
 
     @DeleteMapping("/{id}")
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun deleteBlueprint(@PathVariable(value = "id") id: String) {
         this.bluePrintModelHandler.deleteBlueprintModel(id)
     }
@@ -59,6 +65,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
     @GetMapping("/by-name/{name}/version/{version}", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun getBlueprintByNameAndVersion(@PathVariable(value = "name") name: String,
                                      @PathVariable(value = "version") version: String): BlueprintModelSearch {
         return this.bluePrintModelHandler.getBlueprintModelSearchByNameAndVersion(name, version)
@@ -67,6 +74,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
     @GetMapping("/download/by-name/{name}/version/{version}", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun downloadBlueprintByNameAndVersion(@PathVariable(value = "name") name: String,
                                           @PathVariable(value = "version") version: String): ResponseEntity<Resource> {
         return this.bluePrintModelHandler.downloadBlueprintModelFileByNameAndVersion(name, version)
@@ -75,6 +83,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
     @GetMapping("/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun getBlueprintModel(@PathVariable(value = "id") id: String): BlueprintModelSearch {
         return this.bluePrintModelHandler.getBlueprintModelSearch(id)
     }
@@ -82,6 +91,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
     @GetMapping("/download/{id}", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun downloadBluePrint(@PathVariable(value = "id") id: String): ResponseEntity<Resource> {
         return this.bluePrintModelHandler.downloadBlueprintModelFile(id)
     }
@@ -90,6 +100,7 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
             .MULTIPART_FORM_DATA_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun enrichBlueprint(@RequestPart("file") file: FilePart): ResponseEntity<Resource> = runBlocking {
         bluePrintModelHandler.enrichBlueprint(file)
     }
@@ -97,13 +108,27 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint
     @PostMapping("/publish", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
     @Throws(BluePrintException::class)
+    @PreAuthorize("hasRole('USER')")
     fun publishBlueprint(@RequestPart("file") file: FilePart): BlueprintModelSearch = runBlocking {
         bluePrintModelHandler.publishBlueprint(file)
     }
 
     @GetMapping("/search/{tags}", produces = [MediaType.APPLICATION_JSON_VALUE])
     @ResponseBody
+    @PreAuthorize("hasRole('USER')")
     fun searchBlueprintModels(@PathVariable(value = "tags") tags: String): List<BlueprintModelSearch> {
         return this.bluePrintModelHandler.searchBlueprintModels(tags)
     }
+
+    @DeleteMapping("/name/{name}/version/{version}")
+    @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(@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 {
+        bluePrintModelHandler.deleteBlueprintModel(name, version)
+    }
 }
@@ -32,10 +32,10 @@ import org.springframework.web.bind.annotation.RestControllerAdvice
  * @version 1.0
  */
 @RestControllerAdvice("org.onap.ccsdk.cds.controllerblueprints")
-open class ControllerBlueprintExceptionHandler {
+open class DesignerBlueprintExceptionHandler {
 
     companion object ControllerBlueprintExceptionHandler {
-        val LOG = LoggerFactory.getLogger(ControllerBlueprintExceptionHandler::class.java)
+        val LOG = LoggerFactory.getLogger(DesignerBlueprintExceptionHandler::class.java)
     }
 
     @ExceptionHandler
index c074573..212ffd9 100644 (file)
@@ -29,7 +29,8 @@ import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfigur
 import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService
-import org.slf4j.LoggerFactory
+import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
+import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
 import org.springframework.core.io.ByteArrayResource
 import org.springframework.core.io.Resource
 import org.springframework.http.HttpHeaders
@@ -38,7 +39,6 @@ import org.springframework.http.ResponseEntity
 import org.springframework.http.codec.multipart.FilePart
 import org.springframework.stereotype.Service
 import org.springframework.transaction.annotation.Transactional
-import java.io.File
 import java.io.IOException
 import java.util.*
 
@@ -50,14 +50,14 @@ import java.util.*
  */
 
 @Service
-open class BluePrintModelHandler(private val controllerBlueprintsCatalogService: BluePrintCatalogService,
+open class BluePrintModelHandler(private val blueprintsProcessorCatalogService: BluePrintCatalogService,
                                  private val bluePrintLoadConfiguration: BluePrintLoadConfiguration,
                                  private val blueprintModelSearchRepository: BlueprintModelSearchRepository,
                                  private val blueprintModelRepository: BlueprintModelRepository,
                                  private val blueprintModelContentRepository: BlueprintModelContentRepository,
                                  private val bluePrintEnhancerService: BluePrintEnhancerService) {
 
-    private val log = LoggerFactory.getLogger(BluePrintModelHandler::class.java)!!
+    private val log = logger(BluePrintModelHandler::class)
 
     /**
      * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database
@@ -77,29 +77,11 @@ open class BluePrintModelHandler(private val controllerBlueprintsCatalogService:
     </BlueprintModelSearch> */
     @Throws(BluePrintException::class)
     open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch {
-        val saveId = UUID.randomUUID().toString()
-        val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
         try {
-            //Recreate the Dir
-            normalizedFile(bluePrintLoadConfiguration.blueprintArchivePath, saveId).reCreateDirs()
-            val deCompressedFile = normalizedFile(blueprintArchive, "cba.zip")
-            // Copy the File Part to Local File
-            BluePrintEnhancerUtils.copyFromFilePart(filePart, deCompressedFile)
-            // Save the Copied file to Database
-            val blueprintId = controllerBlueprintsCatalogService.saveToDatabase(saveId, deCompressedFile, false)
-            // Check and Return the Saved File
-            val blueprintModelSearch = blueprintModelSearchRepository.findById(blueprintId)
-                    ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
-                            String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId))
-
-            log.info("Save($saveId) successful for blueprint(${blueprintModelSearch.artifactName}) " +
-                    "version(${blueprintModelSearch.artifactVersion})")
-            return blueprintModelSearch
+            return upload(filePart, false)
         } catch (e: IOException) {
             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
                     "Error in Save CBA: ${e.message}", e)
-        } finally {
-            deleteDir(blueprintArchive)
         }
     }
 
@@ -261,6 +243,10 @@ open class BluePrintModelHandler(private val controllerBlueprintsCatalogService:
         }
     }
 
+    open suspend fun deleteBlueprintModel(name: String, version: String) {
+        blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
+    }
+
     /**
      * This is a CBA enrichBlueprint method
      * Save the Zip File in archive location and extract the cba content.
@@ -275,22 +261,12 @@ open class BluePrintModelHandler(private val controllerBlueprintsCatalogService:
      */
     @Throws(BluePrintException::class)
     open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity<Resource> {
-        val enhanceId = UUID.randomUUID().toString()
-        val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
-        val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
         try {
-            BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchive, blueprintWorkingDir)
-
-            // Enhance the Blue Prints
-            bluePrintEnhancerService.enhance(blueprintWorkingDir)
-
-            return BluePrintEnhancerUtils.compressToFilePart(blueprintWorkingDir, blueprintArchive)
-
+            val enhancedByteArray = enrichBlueprintFileSource(filePart)
+            return BluePrintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray)
         } catch (e: IOException) {
             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
                     "Error in Enriching CBA: ${e.message}", e)
-        } finally {
-            BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
         }
     }
 
@@ -303,22 +279,66 @@ open class BluePrintModelHandler(private val controllerBlueprintsCatalogService:
      */
     @Throws(BluePrintException::class)
     open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch {
-        val publishId = UUID.randomUUID().toString()
-        val blueprintArchive = bluePrintLoadConfiguration.blueprintArchivePath.plus(File.separator).plus(publishId)
-        val blueprintWorkingDir = bluePrintLoadConfiguration.blueprintWorkingPath.plus(File.separator).plus(publishId)
         try {
-            val compressedFilePart = BluePrintEnhancerUtils
-                    .extractCompressFilePart(filePart, blueprintArchive, blueprintWorkingDir)
+            return upload(filePart, true)
+        } catch (e: Exception) {
+            throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
+                    "Error in Publishing CBA: ${e.message}", e)
+        }
+    }
 
-            val blueprintId = controllerBlueprintsCatalogService.saveToDatabase(publishId, compressedFilePart, true)
+    /** Common CBA Save and Publish function for RestController and GRPC Handler, the [fileSource] may be
+     * byteArray or File Part type.*/
+    open suspend fun upload(fileSource: Any, validate: Boolean): BlueprintModelSearch {
+        val saveId = UUID.randomUUID().toString()
+        val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
+        val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
+        try {
+            val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
+            when (fileSource) {
+                is FilePart -> BluePrintEnhancerUtils.filePartAsFile(fileSource, compressedFile)
+                is ByteArray -> BluePrintEnhancerUtils.byteArrayAsFile(fileSource, compressedFile)
+            }
+            // Save the Copied file to Database
+            val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate)
 
             return blueprintModelSearchRepository.findById(blueprintId)
                     ?: throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value,
                             String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId))
 
-        } catch (e: Exception) {
+        } catch (e: IOException) {
             throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
-                    "Error in Publishing CBA: ${e.message}", e)
+                    "Error in Upload CBA: ${e.message}", e)
+        } finally {
+            // Clean blueprint script cache
+            val cacheKey = BluePrintFileUtils
+                    .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId))
+            BluePrintCompileCache.cleanClassLoader(cacheKey)
+            deleteNBDir(blueprintArchive)
+            deleteNBDir(blueprintWorking)
+        }
+    }
+
+    /** Common CBA Enrich function for RestController and GRPC Handler, the [fileSource] may be
+     * byteArray or File Part type.*/
+    open suspend fun enrichBlueprintFileSource(fileSource: Any): ByteArray {
+        val enhanceId = UUID.randomUUID().toString()
+        val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId)
+        val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId)
+        try {
+            when (fileSource) {
+                is FilePart -> BluePrintEnhancerUtils
+                        .copyFilePartToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
+                is ByteArray -> BluePrintEnhancerUtils
+                        .copyByteArrayToEnhanceDir(fileSource, blueprintArchive, blueprintWorkingDir)
+            }            // Enhance the Blue Prints
+            bluePrintEnhancerService.enhance(blueprintWorkingDir)
+
+            return BluePrintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive)
+
+        } catch (e: IOException) {
+            throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
+                    "Error in Enriching CBA: ${e.message}", e)
         } finally {
             BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir)
         }
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/service/AutoResourceMappingService.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/service/AutoResourceMappingService.kt
deleted file mode 100644 (file)
index be56264..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright © 2017-2018 AT&T Intellectual Property.
- * Modifications Copyright © 2019 Huawei.
- *
- * 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.designer.api.service
-
-import com.google.common.base.Preconditions
-import org.apache.commons.collections.CollectionUtils
-import org.apache.commons.lang3.StringUtils
-import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.AutoMapResponse
-import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain.ResourceDictionary
-import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.repository.ResourceDictionaryRepository
-import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException
-import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition
-import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment
-import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.ResourceDictionaryUtils
-import org.slf4j.LoggerFactory
-import org.springframework.stereotype.Service
-import java.util.*
-
-@Service
-open class AutoResourceMappingService(private val dataDictionaryRepository: ResourceDictionaryRepository) {
-
-    private val log = LoggerFactory.getLogger(AutoResourceMappingService::class.java)
-
-    @Throws(BluePrintException::class)
-    fun autoMap(resourceAssignments: MutableList<ResourceAssignment>):
-            AutoMapResponse {
-        val autoMapResponse = AutoMapResponse()
-        try {
-            if (CollectionUtils.isNotEmpty(resourceAssignments)) {
-                // Create the Dictionary definitions for the ResourceAssignment Names
-                val dictionaryMap = getDictionaryDefinitions(resourceAssignments)
-
-                for (resourceAssignment in resourceAssignments) {
-                    if (StringUtils.isNotBlank(resourceAssignment.name)
-                            && StringUtils.isBlank(resourceAssignment.dictionaryName)) {
-                        populateDictionaryMapping(dictionaryMap, resourceAssignment)
-                        log.info("Mapped Resource : {}", resourceAssignment)
-                    }
-                }
-            }
-            val dictionaries = getDictionaryDefinitionsList(resourceAssignments)
-            val resourceAssignmentsFinal = getAllAutoMapResourceAssignments(resourceAssignments)
-            autoMapResponse.dataDictionaries = dictionaries
-            autoMapResponse.resourceAssignments = resourceAssignmentsFinal
-        } catch (e: Exception) {
-            log.error(String.format("Failed in auto process %s", e.message))
-            throw BluePrintException(e, e.message!!)
-        }
-
-        return autoMapResponse
-    }
-
-    private fun populateDictionaryMapping(dictionaryMap: Map<String, ResourceDictionary>, resourceAssignment: ResourceAssignment) {
-        val dbDataDictionary = dictionaryMap[resourceAssignment.name]
-        if (dbDataDictionary != null && dbDataDictionary.definition != null) {
-
-            val dictionaryDefinition = dbDataDictionary.definition
-
-            if (dictionaryDefinition != null && StringUtils.isNotBlank(dictionaryDefinition.name)
-                    && StringUtils.isBlank(resourceAssignment.dictionaryName)) {
-
-                resourceAssignment.dictionaryName = dbDataDictionary.name
-                ResourceDictionaryUtils.populateSourceMapping(resourceAssignment, dictionaryDefinition)
-            }
-        }
-    }
-
-    private fun getDictionaryDefinitions(resourceAssignments: List<ResourceAssignment>): Map<String, ResourceDictionary> {
-        val dictionaryMap = HashMap<String, ResourceDictionary>()
-        val names = ArrayList<String>()
-        for (resourceAssignment in resourceAssignments) {
-            if (StringUtils.isNotBlank(resourceAssignment.name)) {
-                names.add(resourceAssignment.name)
-            }
-        }
-        if (CollectionUtils.isNotEmpty(names)) {
-
-            val dictionaries = dataDictionaryRepository.findByNameIn(names)
-            if (CollectionUtils.isNotEmpty(dictionaries)) {
-                for (dataDictionary in dictionaries) {
-                    if (StringUtils.isNotBlank(dataDictionary.name)) {
-                        dictionaryMap[dataDictionary.name] = dataDictionary
-                    }
-                }
-            }
-        }
-        return dictionaryMap
-
-    }
-    private fun getDictionaryDefinitionsList(resourceAssignments: List<ResourceAssignment>): List<ResourceDictionary>? {
-        var dictionaries: List<ResourceDictionary>? = null
-        val names = ArrayList<String>()
-        for (resourceAssignment in resourceAssignments) {
-            if (StringUtils.isNotBlank(resourceAssignment.dictionaryName)) {
-
-                if (!names.contains(resourceAssignment.dictionaryName)) {
-                    names.add(resourceAssignment.dictionaryName!!)
-                }
-
-                if (resourceAssignment.dependencies != null && !resourceAssignment.dependencies!!.isEmpty()) {
-                    val dependencyNames = resourceAssignment.dependencies
-                    for (dependencyName in dependencyNames!!) {
-                        if (StringUtils.isNotBlank(dependencyName) && !names.contains(dependencyName)) {
-                            names.add(dependencyName)
-                        }
-                    }
-                }
-            }
-        }
-        if (CollectionUtils.isNotEmpty(names)) {
-            dictionaries = dataDictionaryRepository.findByNameIn(names)
-        }
-        return dictionaries
-
-    }
-
-    private fun getAllAutoMapResourceAssignments(resourceAssignments: MutableList<ResourceAssignment>): List<ResourceAssignment> {
-        var dictionaries: List<ResourceDictionary>? = null
-        val names = ArrayList<String>()
-        for (resourceAssignment in resourceAssignments) {
-            if (StringUtils.isNotBlank(resourceAssignment.dictionaryName)) {
-                if (resourceAssignment.dependencies != null && !resourceAssignment.dependencies!!.isEmpty()) {
-                    val dependencyNames = resourceAssignment.dependencies
-                    for (dependencyName in dependencyNames!!) {
-                        if (StringUtils.isNotBlank(dependencyName) && !names.contains(dependencyName)
-                                && !checkAssignmentsExists(resourceAssignments, dependencyName)) {
-                            names.add(dependencyName)
-                        }
-                    }
-                }
-            }
-        }
-
-        if (!names.isEmpty()) {
-            dictionaries = dataDictionaryRepository.findByNameIn(names)
-        }
-        if (dictionaries != null) {
-            for (rscDictionary in dictionaries) {
-                val dictionaryDefinition = rscDictionary.definition
-                Preconditions.checkNotNull(dictionaryDefinition, "failed to get Resource Definition from dictionary definition")
-                val property = PropertyDefinition()
-                property.required = true
-                val resourceAssignment = ResourceAssignment()
-                resourceAssignment.name = rscDictionary.name
-                resourceAssignment.dictionaryName = rscDictionary.name
-                resourceAssignment.version = 0
-                resourceAssignment.property = property
-                ResourceDictionaryUtils.populateSourceMapping(resourceAssignment, dictionaryDefinition)
-                resourceAssignments.add(resourceAssignment)
-            }
-        }
-        return resourceAssignments
-    }
-
-
-    private fun checkAssignmentsExists(resourceAssignmentsWithDepencies: List<ResourceAssignment>, resourceName: String): Boolean {
-        return resourceAssignmentsWithDepencies.stream().anyMatch { names -> names.name.equals(resourceName, ignoreCase = true) }
-    }
-}
\ No newline at end of file
index 6eab5cd..c79d1b5 100644 (file)
 
 package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils
 
-import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.reactive.awaitSingle
-import kotlinx.coroutines.withContext
 import org.onap.ccsdk.cds.controllerblueprints.core.*
-import org.onap.ccsdk.cds.controllerblueprints.core.data.*
+import org.onap.ccsdk.cds.controllerblueprints.core.data.ArtifactType
+import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType
+import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeType
+import org.onap.ccsdk.cds.controllerblueprints.core.data.RelationshipType
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintRepoService
 import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils
@@ -32,17 +33,13 @@ import org.springframework.http.HttpHeaders
 import org.springframework.http.MediaType
 import org.springframework.http.ResponseEntity
 import org.springframework.http.codec.multipart.FilePart
-import org.springframework.util.StringUtils
-import reactor.core.publisher.Mono
 import java.io.File
-import java.io.IOException
-import java.nio.file.Path
 import java.nio.file.Paths
-import java.util.*
 
 
 class BluePrintEnhancerUtils {
     companion object {
+        val log = logger(BluePrintEnhancerUtils)
 
         fun populateDataTypes(bluePrintContext: BluePrintContext, bluePrintRepoService: BluePrintRepoService,
                               dataTypeName: String): DataType {
@@ -84,81 +81,88 @@ class BluePrintEnhancerUtils {
             return artifactType
         }
 
-        suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File {
+        suspend fun byteArrayAsFile(byteArray: ByteArray, targetFile: File): File {
+            // Recreate Folder
+            targetFile.parentFile.reCreateNBDirs()
+            targetFile.writeBytes(byteArray).apply {
+                log.info("CBA file(${targetFile.absolutePath} written successfully")
+            }
+            return targetFile
+        }
+
+
+        suspend fun filePartAsFile(filePart: FilePart, targetFile: File): File {
             // Delete the Directory
-            targetFile.deleteRecursively()
+            targetFile.parentFile.reCreateNBDirs()
             return filePart.transferTo(targetFile)
                     .thenReturn(targetFile)
                     .awaitSingle()
         }
 
-        suspend fun extractCompressFilePart(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
+        private suspend fun byteArrayAsArchiveFile(byteArray: ByteArray, archiveDir: String, enhanceDir: String): File {
+            //Recreate the Base Directories
+            normalizedFile(archiveDir).reCreateNBDirs()
+            normalizedFile(enhanceDir).reCreateNBDirs()
+            val archiveFile = normalizedFile(archiveDir, "cba.zip")
+            // Copy the File Part to ZIP
+            return byteArrayAsFile(byteArray, archiveFile)
+        }
+
+        private suspend fun filePartAsArchiveFile(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
             //Recreate the Base Directories
-            normalizedFile(archiveDir).reCreateDirs()
-            normalizedFile(enhanceDir).reCreateDirs()
-            val filePartFile = normalizedFile(archiveDir, "cba.zip")
+            normalizedFile(archiveDir).reCreateNBDirs()
+            normalizedFile(enhanceDir).reCreateNBDirs()
+            val archiveFile = normalizedFile(archiveDir, "cba.zip")
             // Copy the File Part to ZIP
-            return copyFromFilePart(filePart, filePartFile)
+            return filePartAsFile(filePart, archiveFile)
+        }
+
+        /** copy the [byteArray] zip file to [archiveDir] and then decompress to [enhanceDir] */
+        suspend fun copyByteArrayToEnhanceDir(byteArray: ByteArray, archiveDir: String, enhanceDir: String): File {
+            val archiveFile = byteArrayAsArchiveFile(byteArray, archiveDir, enhanceDir)
+            val deCompressFileName = normalizedPathName(enhanceDir)
+            return archiveFile.deCompress(deCompressFileName)
         }
 
-        suspend fun decompressFilePart(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
-            val filePartFile = extractCompressFilePart(filePart, archiveDir, enhanceDir)
+        /** copy the [filePart] zip file to [archiveDir] and then decompress to [enhanceDir] */
+        suspend fun copyFilePartToEnhanceDir(filePart: FilePart, archiveDir: String, enhanceDir: String): File {
+            val filePartFile = filePartAsArchiveFile(filePart, archiveDir, enhanceDir)
             val deCompressFileName = normalizedPathName(enhanceDir)
             return filePartFile.deCompress(deCompressFileName)
         }
 
-        suspend fun compressToFilePart(enhanceDir: String, archiveDir: String,
-                                       outputFileName:String="enhanced-cba.zip"): ResponseEntity<Resource> {
+        /** compress [enhanceDir] to [archiveDir] and return ByteArray */
+        suspend fun compressEnhanceDirAndReturnByteArray(enhanceDir: String, archiveDir: String,
+                                                         outputFileName: String = "enhanced-cba.zip"): ByteArray {
             val compressedFile = normalizedFile(archiveDir, outputFileName)
             BluePrintArchiveUtils.compress(Paths.get(enhanceDir).toFile(), compressedFile)
-            return prepareResourceEntity(compressedFile.name, compressedFile.readBytes())
+            return compressedFile.readBytes()
         }
 
-        suspend fun prepareResourceEntity(fileName: String, file: ByteArray): ResponseEntity<Resource> {
+        /** compress [enhanceDir] to [archiveDir] and return ResponseEntity */
+        suspend fun compressEnhanceDirAndReturnFilePart(enhanceDir: String, archiveDir: String,
+                                                        outputFileName: String = "enhanced-cba.zip")
+                : ResponseEntity<Resource> {
+            val compressedFile = normalizedFile(archiveDir, outputFileName)
+            BluePrintArchiveUtils.compress(Paths.get(enhanceDir).toFile(), compressedFile)
+            return prepareResourceEntity(compressedFile)
+        }
+
+        /** convert [file] to ResourceEntity */
+        suspend fun prepareResourceEntity(file: File): ResponseEntity<Resource> {
+            return prepareResourceEntity(file.name, file.readBytes())
+        }
+        /** convert [byteArray] to ResourceEntity with [fileName]*/
+        fun prepareResourceEntity(fileName: String, byteArray: ByteArray): ResponseEntity<Resource> {
             return ResponseEntity.ok()
                     .contentType(MediaType.parseMediaType("text/plain"))
                     .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"$fileName\"")
-                    .body(ByteArrayResource(file))
-        }
-
-        suspend fun cleanEnhancer(archiveLocation: String, enhancementLocation: String) = withContext(Dispatchers.Default) {
-            deleteDir(archiveLocation)
-            deleteDir(enhancementLocation)
+                    .body(ByteArrayResource(byteArray))
         }
 
-        /**
-         * This is a saveCBAFile method
-         * take a [FilePart], transfer it to disk using a Flux of FilePart and return a [Mono] representing the CBA file name
-         *
-         * @param (filePart, targetDirectory) - the request part containing the file to be saved and the default directory where to save
-         * @return a [Mono] String representing the result of the operation
-         * @throws (BluePrintException, IOException) BluePrintException, IOException
-         */
-        @Throws(BluePrintException::class, IOException::class)
-        fun saveCBAFile(filePart: FilePart, targetDirectory: Path): Mono<String> {
-
-            // Normalize file name
-            val fileName = StringUtils.cleanPath(filePart.filename())
-
-            // Check if the file's extension is "CBA"
-            if (StringUtils.getFilenameExtension(fileName) != "zip") {
-                throw BluePrintException(ErrorCode.INVALID_FILE_EXTENSION.value, "Invalid file extension required ZIP")
-            }
-
-            // Change file name to match a pattern
-            val changedFileName = UUID.randomUUID().toString() + ".zip"
-            //String changedFileName = BluePrintFileUtils.Companion.getCBAGeneratedFileName(fileName, this.CBA_FILE_NAME_PATTERN);
-
-            // Copy file to the target location (Replacing existing file with the same name)
-            val targetLocation = targetDirectory.resolve(changedFileName)
-
-            // if a file with the same name already exists in a repository, delete and recreate it
-            val file = File(targetLocation.toString())
-            if (file.exists())
-                file.delete()
-            file.createNewFile()
-
-            return filePart.transferTo(file).thenReturn(changedFileName)
+        suspend fun cleanEnhancer(archiveLocation: String, enhancementLocation: String) {
+            deleteNBDir(archiveLocation)
+            deleteNBDir(enhancementLocation)
         }
     }
 }
  * limitations under the License.
  */
 
-package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
+package org.onap.ccsdk.cds.blueprintsprocessor.designer.api
 
 import com.google.protobuf.ByteString
 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.ActionIdentifiers
 import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
 import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
 import org.onap.ccsdk.cds.controllerblueprints.management.api.*
 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,9 +43,8 @@ import kotlin.test.assertTrue
 @RunWith(SpringRunner::class)
 @EnableAutoConfiguration
 @DirtiesContext
-@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)])
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor",
+    "org.onap.ccsdk.cds.controllerblueprints"])
 @TestPropertySource(locations = ["classpath:application-test.properties"])
 class BluePrintManagementGRPCHandlerTest {
 
@@ -77,7 +74,8 @@ class BluePrintManagementGRPCHandlerTest {
         val output = blockingStub.uploadBlueprint(req)
 
         assertEquals(200, output.status.code)
-        assertTrue(output.status.message.contains("Successfully uploaded CBA"))
+        assertTrue(output.status.message.contentEquals(BluePrintConstants.STATUS_SUCCESS),
+                "failed to get success status")
         assertEquals(id, output.commonHeader.requestId)
     }
 
@@ -89,7 +87,8 @@ class BluePrintManagementGRPCHandlerTest {
 
         var output = blockingStub.uploadBlueprint(req)
         assertEquals(200, output.status.code)
-        assertTrue(output.status.message.contains("Successfully uploaded CBA"))
+        assertTrue(output.status.message.contentEquals(BluePrintConstants.STATUS_SUCCESS),
+                "failed to get success status")
         assertEquals(id, output.commonHeader.requestId)
 
         val removeReq = createRemoveInputRequest(id)
index 877584e..0d834d2 100644 (file)
@@ -32,7 +32,6 @@ import org.onap.ccsdk.cds.blueprintsprocessor.db.BluePrintDBLibConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModelSearch
 import org.onap.ccsdk.cds.controllerblueprints.core.*
 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
-import org.slf4j.LoggerFactory
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.core.io.ByteArrayResource
@@ -67,7 +66,7 @@ import kotlin.test.assertTrue
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 class BlueprintModelControllerTest {
 
-    private val log = LoggerFactory.getLogger(BlueprintModelControllerTest::class.java)!!
+    private val log = logger(BlueprintModelControllerTest::class)
 
     companion object {
         private var bp: BlueprintModelSearch? = null
@@ -176,6 +175,31 @@ class BlueprintModelControllerTest {
 
     @Test
     fun test07_publishBlueprintModel() {
+        bp = runBlocking {
+            val body = MultipartBodyBuilder().apply {
+                part("file", object : ByteArrayResource(testZipFile!!.readBytes()) {
+                    override fun getFilename(): String {
+                        return "test.zip"
+                    }
+                })
+            }.build()
+
+            val publishBP = webTestClient
+                    .post()
+                    .uri("/api/v1/blueprint-model/publish")
+                    .body(BodyInserters.fromMultipartData(body))
+                    .exchange()
+                    .expectStatus().isOk
+                    .returnResult<BlueprintModelSearch>()
+                    .responseBody
+                    .awaitSingle()
+
+            assertNotNull(publishBP, "failed to get response")
+            assertEquals("baseconfiguration", publishBP.artifactName, "mismatch artifact name")
+            assertEquals("1.0.0", publishBP.artifactVersion, "mismatch artifact version")
+            assertEquals("Y", publishBP.published, "mismatch publish")
+            publishBP
+        }
     }
 
     @Test
@@ -196,7 +220,13 @@ class BlueprintModelControllerTest {
 
     @Test
     fun test10_deleteBluePrint() {
-        webTestClient.delete().uri("/api/v1/blueprint-model/${bp!!.id}")
+//        webTestClient.delete().uri("/api/v1/blueprint-model/${bp!!.id}")
+//                .header("Authorization", "Basic " + Base64Utils
+//                        .encodeToString(("ccsdkapps" + ":" + "ccsdkapps").toByteArray(UTF_8)))
+//                .exchange()
+//                .expectStatus().is2xxSuccessful
+
+        webTestClient.delete().uri("/api/v1/blueprint-model/name/${bp!!.artifactName}/version/${bp!!.artifactVersion}")
                 .header("Authorization", "Basic " + Base64Utils
                         .encodeToString(("ccsdkapps" + ":" + "ccsdkapps").toByteArray(UTF_8)))
                 .exchange()
index e34238e..5999873 100644 (file)
@@ -58,8 +58,8 @@ class BluePrintEnhancerUtilsTest {
             val enhanceId = UUID.randomUUID().toString()
             val blueprintArchiveLocation = normalizedPathName(blueprintArchivePath, enhanceId)
             val blueprintEnrichmentLocation = normalizedPathName(blueprintEnrichmentPath, enhanceId)
-            BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchiveLocation, blueprintEnrichmentLocation)
-            BluePrintEnhancerUtils.compressToFilePart(blueprintEnrichmentLocation, blueprintArchiveLocation)
+            BluePrintEnhancerUtils.copyFilePartToEnhanceDir(filePart, blueprintArchiveLocation, blueprintEnrichmentLocation)
+            BluePrintEnhancerUtils.compressEnhanceDirAndReturnFilePart(blueprintEnrichmentLocation, blueprintArchiveLocation)
         }
     }
 }
diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/test-cba.zip b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/test-cba.zip
new file mode 100644 (file)
index 0000000..785ec6c
Binary files /dev/null and b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/test-cba.zip differ
index 8afecab..0542fe3 100644 (file)
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>inbounds</artifactId>
         <module>selfservice-api</module>
     </modules>
     <dependencies>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-core</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
             <artifactId>workflow-service</artifactId>
             <artifactId>kotlinx-coroutines-test</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-testing</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>io.projectreactor</groupId>
             <artifactId>reactor-test</artifactId>
index cf8c61a..da233b8 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>inbounds</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>resource-api</artifactId>
index 2c241cc..7c53e1c 100755 (executable)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>inbounds</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>selfservice-api</artifactId>
 
     <dependencies>
 
-        <dependency>
-            <groupId>org.springframework.security</groupId>
-            <artifactId>spring-security-core</artifactId>
-        </dependency>
-
         <dependency>
             <groupId>org.onap.ccsdk.cds.components</groupId>
             <artifactId>proto-definition</artifactId>
-            <version>${project.version}</version>
         </dependency>
 
         <dependency>
             <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
             <artifactId>blueprint-validation</artifactId>
         </dependency>
-        <dependency>
-            <groupId>io.grpc</groupId>
-            <artifactId>grpc-testing</artifactId>
-        </dependency>
 
         <!-- For Message libraries -->
         <dependency>
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt
new file mode 100644 (file)
index 0000000..b339903
--- /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.selfservice.api
+
+import kotlinx.coroutines.channels.consumeEach
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BlueprintMessageConsumerService
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException
+import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsType
+import org.onap.ccsdk.cds.controllerblueprints.core.logger
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
+import org.springframework.boot.context.event.ApplicationReadyEvent
+import org.springframework.context.event.EventListener
+import org.springframework.stereotype.Service
+import javax.annotation.PreDestroy
+
+@ConditionalOnProperty(name = ["blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable"],
+        havingValue = "true")
+@Service
+open class BluePrintProcessingKafkaConsumer(
+        private val bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService,
+        private val executionServiceHandler: ExecutionServiceHandler) {
+
+    val log = logger(BluePrintProcessingKafkaConsumer::class)
+
+    private lateinit var blueprintMessageConsumerService: BlueprintMessageConsumerService
+
+    companion object {
+        const val CONSUMER_SELECTOR = "self-service-api"
+        const val PRODUCER_SELECTOR = "self-service-api"
+    }
+
+    @EventListener(ApplicationReadyEvent::class)
+    fun setupMessageListener() = runBlocking {
+        try {
+            log.info("Setting up message consumer($CONSUMER_SELECTOR) and " +
+                    "message producer($PRODUCER_SELECTOR)...")
+
+            /** Get the Message Consumer Service **/
+            blueprintMessageConsumerService = try {
+                bluePrintMessageLibPropertyService
+                        .blueprintMessageConsumerService(CONSUMER_SELECTOR)
+            } catch (e: Exception) {
+                throw BluePrintProcessorException("failed to create consumer service ${e.message}")
+            }
+
+            /** Get the Message Producer Service **/
+            val blueprintMessageProducerService = try {
+                bluePrintMessageLibPropertyService
+                        .blueprintMessageProducerService(PRODUCER_SELECTOR)
+            } catch (e: Exception) {
+                throw BluePrintProcessorException("failed to create producer service ${e.message}")
+            }
+
+            launch {
+                /** Subscribe to the consumer topics */
+                val additionalConfig: MutableMap<String, Any> = hashMapOf()
+                val channel = blueprintMessageConsumerService.subscribe(additionalConfig)
+                channel.consumeEach { message ->
+                    launch {
+                        try {
+                            log.trace("Consumed Message : $message")
+                            val executionServiceInput = message.jsonAsType<ExecutionServiceInput>()
+                            val executionServiceOutput = executionServiceHandler.doProcess(executionServiceInput)
+                            //TODO("In future, Message publisher configuration vary with respect to request")
+                            /** Send the response message */
+                            blueprintMessageProducerService.sendMessage(executionServiceOutput)
+                        } catch (e: Exception) {
+                            log.error("failed in processing the consumed message : $message", e)
+                        }
+                    }
+                }
+            }
+        } catch (e: Exception) {
+            log.error("failed to start message consumer($CONSUMER_SELECTOR) and " +
+                    "message producer($PRODUCER_SELECTOR) ", e)
+        }
+    }
+
+    @PreDestroy
+    fun shutdownMessageListener() = runBlocking {
+        try {
+            log.info("Shutting down message consumer($CONSUMER_SELECTOR) and " +
+                    "message producer($PRODUCER_SELECTOR)...")
+            blueprintMessageConsumerService.shutDown()
+        } catch (e: Exception) {
+            log.error("failed to shutdown message listener($CONSUMER_SELECTOR)", e)
+        }
+    }
+
+}
\ No newline at end of file
index d48f0c7..4441d2b 100644 (file)
@@ -27,11 +27,9 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInpu
 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.asJsonPrimitive
-import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.http.MediaType
 import org.springframework.http.ResponseEntity
-import org.springframework.http.codec.multipart.FilePart
 import org.springframework.security.access.prepost.PreAuthorize
 import org.springframework.web.bind.annotation.*
 
@@ -53,30 +51,6 @@ open class ExecutionServiceController {
         "Success".asJsonPrimitive()
     }
 
-    @PostMapping(path = ["/upload"], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
-    @ResponseBody
-    @PreAuthorize("hasRole('USER')")
-    @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 {
-        val uploadId = executionServiceHandler.upload(filePart)
-        """{"upload-id" : "$uploadId"}""".asJsonType()
-    }
-
-    @DeleteMapping("/name/{name}/version/{version}")
-    @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(@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 = "Execute a CBA workflow (action)",
             notes = "Execute the appropriate CBA's action based on the ExecutionServiceInput object passed as input.",
index 2f88780..20af589 100644 (file)
@@ -21,24 +21,16 @@ import io.grpc.stub.StreamObserver
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.reactive.awaitSingle
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.*
 import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.utils.toProto
 import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType
-import org.onap.ccsdk.cds.controllerblueprints.core.*
+import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants
 import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration
-import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintWorkflowExecutionService
-import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache
-import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils
 import org.slf4j.LoggerFactory
-import org.springframework.http.codec.multipart.FilePart
 import org.springframework.stereotype.Service
-import java.io.File
-import java.io.IOException
-import java.util.*
 import java.util.stream.Collectors
 
 @Service
@@ -49,37 +41,6 @@ class ExecutionServiceHandler(private val bluePrintLoadConfiguration: BluePrintL
 
     private val log = LoggerFactory.getLogger(ExecutionServiceHandler::class.toString())
 
-    //TODO("Remove from self service api and move to designer api module")
-    suspend fun upload(filePart: FilePart): String {
-        val saveId = UUID.randomUUID().toString()
-        val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId)
-        val blueprintWorking = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, saveId)
-        try {
-
-            val compressedFile = normalizedFile(blueprintArchive, "cba.zip")
-            compressedFile.parentFile.reCreateNBDirs()
-            // Copy the File Part to Local File
-            copyFromFilePart(filePart, compressedFile)
-            // Save the Copied file to Database
-            return blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, true)
-        } catch (e: IOException) {
-            throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value,
-                "Error in Upload CBA: ${e.message}", e)
-        } finally {
-            // Clean blueprint script cache
-            val cacheKey = BluePrintFileUtils
-                    .compileCacheKey(normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath,saveId))
-            BluePrintCompileCache.cleanClassLoader(cacheKey)
-            deleteNBDir(blueprintArchive)
-            deleteNBDir(blueprintWorking)
-        }
-    }
-
-    //TODO("Remove from self service api and move to designer api module")
-    suspend fun remove(name: String, version: String) {
-        blueprintsProcessorCatalogService.deleteFromDatabase(name, version)
-    }
-
     suspend fun process(executionServiceInput: ExecutionServiceInput,
                         responseObserver: StreamObserver<org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput>) {
         when {
@@ -97,8 +58,8 @@ class ExecutionServiceHandler(private val bluePrintLoadConfiguration: BluePrintL
                 responseObserver.onCompleted()
             }
             else -> responseObserver.onNext(response(executionServiceInput,
-                "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.",
-                true).toProto());
+                    "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.",
+                    true).toProto());
         }
     }
 
@@ -115,7 +76,7 @@ class ExecutionServiceHandler(private val bluePrintLoadConfiguration: BluePrintL
             val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(requestId, basePath.toString())
 
             val output = bluePrintWorkflowExecutionService.executeBluePrintWorkflow(blueprintRuntimeService,
-                executionServiceInput, hashMapOf())
+                    executionServiceInput, hashMapOf())
 
             val errors = blueprintRuntimeService.getBluePrintError().errors
             if (errors.isNotEmpty()) {
@@ -129,12 +90,6 @@ class ExecutionServiceHandler(private val bluePrintLoadConfiguration: BluePrintL
         }
     }
 
-    private suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File {
-        return filePart.transferTo(targetFile)
-            .thenReturn(targetFile)
-            .awaitSingle()
-    }
-
     private fun setErrorStatus(errorMessage: String, status: Status) {
         status.errorMessage = errorMessage
         status.eventType = EventType.EVENT_COMPONENT_FAILURE.name
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
deleted file mode 100644 (file)
index 17e157d..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api
-
-import com.fasterxml.jackson.databind.DeserializationFeature
-import com.fasterxml.jackson.databind.ObjectMapper
-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.config.ConcurrentKafkaListenerContainerFactory
-import org.springframework.kafka.core.ConsumerFactory
-import org.springframework.kafka.core.DefaultKafkaConsumerFactory
-import org.springframework.kafka.support.serializer.ErrorHandlingDeserializer2
-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.AUTO_OFFSET_RESET_CONFIG] = "latest"
-        configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java
-        configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = ErrorHandlingDeserializer2::class.java
-        configProperties[ErrorHandlingDeserializer2.VALUE_DESERIALIZER_CLASS] = JsonDeserializer::class.java.name
-
-        val deserializer = JsonDeserializer<ExecutionServiceInput>()
-        deserializer.setRemoveTypeHeaders(true)
-        deserializer.addTrustedPackages("*")
-
-        val jsonDeserializer =  JsonDeserializer(ExecutionServiceInput::class.java,
-                ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false))
-
-        return DefaultKafkaConsumerFactory(configProperties, StringDeserializer(),
-                ErrorHandlingDeserializer2<ExecutionServiceInput>(jsonDeserializer))
-    }
-
-    /**
-     *  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
deleted file mode 100644 (file)
index 54cc0c1..0000000
+++ /dev/null
@@ -1,73 +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.selfservice.api
-
-import kotlinx.coroutines.async
-import kotlinx.coroutines.runBlocking
-import org.apache.commons.lang3.builder.ToStringBuilder
-import org.apache.kafka.clients.consumer.ConsumerRecord
-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(record: ConsumerRecord<String, ExecutionServiceInput>) {
-
-        runBlocking {
-            log.info("Successfully received a message: {}", ToStringBuilder.reflectionToString(record.value()))
-
-            // Process the message.
-            async {
-                processMessage(record.value())
-            }.await()
-        }
-    }
-
-    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 2cf1c1d..16fe36c 100644 (file)
@@ -22,20 +22,10 @@ import org.springframework.util.StringUtils
 import java.io.File
 import java.io.IOException
 import java.nio.file.Path
-import java.time.LocalDateTime
-import java.time.ZoneId
-import java.time.format.DateTimeFormatter
 import java.util.*
 
 const val INTERNAL_SERVER_ERROR_HTTP_STATUS_CODE = 500
 
-fun currentTimestamp(): String {
-    val now = LocalDateTime.now(ZoneId.systemDefault())
-    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
-    return formatter.format(now)
-}
-
-
 @Throws(BluePrintException::class, IOException::class)
 fun saveCBAFile(filePart: FilePart, targetDirectory: Path): Path {
 
index ce5acd4..8bedc96 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2017-2018 AT&T Intellectual Property.
  * Modifications Copyright © 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.
@@ -35,7 +36,6 @@ 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
@@ -44,8 +44,8 @@ import kotlin.test.BeforeTest
 @RunWith(SpringRunner::class)
 @DirtiesContext
 @EnableAutoConfiguration
-@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"],
-        excludeFilters =arrayOf(ComponentScan.Filter(value = [(MessagingController::class)], type = FilterType.ASSIGNABLE_TYPE)))
+@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor",
+    "org.onap.ccsdk.cds.controllerblueprints"])
 @TestPropertySource(locations = ["classpath:application-test.properties"])
 class BluePrintProcessingGRPCHandlerTest {
     private val log = LoggerFactory.getLogger(BluePrintProcessingGRPCHandlerTest::class.java)
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumerTest.kt
new file mode 100644 (file)
index 0000000..7d43f53
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *  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.selfservice.api
+
+import io.mockk.coEvery
+import io.mockk.mockk
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+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.message.BluePrintMessageLibConfiguration
+import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.test.context.ContextConfiguration
+import org.springframework.test.context.TestPropertySource
+import org.springframework.test.context.junit4.SpringRunner
+import kotlin.test.Test
+import kotlin.test.assertNotNull
+
+@RunWith(SpringRunner::class)
+@ContextConfiguration(classes = [BluePrintMessageLibConfiguration::class,
+    BlueprintPropertyConfiguration::class, BluePrintProperties::class])
+@TestPropertySource(locations = ["classpath:application-test.properties"])
+class BluePrintProcessingKafkaConsumerTest {
+
+    @Autowired
+    lateinit var bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService
+
+    @Test
+    fun testExecutionInputMessageConsumer() {
+        runBlocking {
+            assertNotNull(bluePrintMessageLibPropertyService,
+                    "failed to initialise bluePrintMessageLibPropertyService")
+
+            val executionServiceHandle = mockk<ExecutionServiceHandler>()
+
+            coEvery { executionServiceHandle.doProcess(any()) } returns mockk()
+
+            val bluePrintProcessingKafkaConsumer = BluePrintProcessingKafkaConsumer(bluePrintMessageLibPropertyService,
+                    executionServiceHandle)
+
+            launch {
+                bluePrintProcessingKafkaConsumer.setupMessageListener()
+            }
+            delay(100)
+            bluePrintProcessingKafkaConsumer.shutdownMessageListener()
+        }
+    }
+
+}
\ No newline at end of file
@@ -1,6 +1,7 @@
 /*
  * Copyright © 2017-2018 AT&T Intellectual Property.
  * Modifications Copyright © 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.
  * 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.reactive.awaitSingle
 import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -25,23 +24,18 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration
 import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput
 import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir
 import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService
+import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile
 import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils
 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
 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 java.util.*
 import kotlin.test.AfterTest
 import kotlin.test.BeforeTest
@@ -49,11 +43,12 @@ 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"],
-        excludeFilters =arrayOf(ComponentScan.Filter(value = [(MessagingController::class)], type = FilterType.ASSIGNABLE_TYPE)))
+@ContextConfiguration(classes = [ExecutionServiceHandler::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 ExecutionServiceHandlerTest {
+class ExecutionServiceControllerTest {
 
     @Autowired
     lateinit var blueprintsProcessorCatalogService: BluePrintCatalogService
@@ -70,31 +65,6 @@ class ExecutionServiceHandlerTest {
         deleteDir("target", "blueprints")
     }
 
-
-    @Test
-    fun `test rest upload blueprint`() {
-        runBlocking {
-            val body = MultipartBodyBuilder().apply {
-                part("file", object : ByteArrayResource(Files.readAllBytes(loadTestCbaFile().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()
-        }
-
-    }
-
     @Test
     fun `test rest process`() {
         runBlocking {
@@ -132,7 +102,7 @@ class ExecutionServiceHandlerTest {
     }
 
     private fun loadTestCbaFile(): File {
-        val testCbaFile = Paths.get("./src/test/resources/test-cba.zip").toFile()
+        val testCbaFile = normalizedFile("./src/test/resources/test-cba.zip")
         assertTrue(testCbaFile.exists(), "couldn't get file ${testCbaFile.absolutePath}")
         return testCbaFile
     }
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
deleted file mode 100644 (file)
index facbec5..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.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.Ignore
-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
-//FIXME("testReceive method is failing in server build, It is not stable, may be timing issue.")
-@Ignore
-@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 event: ExecutionServiceInput? = 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)
-
-        assertNotNull(event)
-    }
-
-    @KafkaListener(topicPartitions = [TopicPartition(topic = "\${blueprintsprocessor.messageclient.self-service-api.topic}", partitionOffsets = [PartitionOffset(partition = "0", initialOffset = "0")])])
-    fun receivedEventFromBluePrintProducer(receivedEvent: ExecutionServiceInput) {
-        event = receivedEvent
-    }
-
-    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_enriched.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
deleted file mode 100644 (file)
index dc1f38a..0000000
+++ /dev/null
@@ -1,48 +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.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 ab3bac8..d18b700 100644 (file)
@@ -33,10 +33,15 @@ blueprints.processor.functions.python.executor.executionPath=./../../../../compo
 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
+blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false
+blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t
+blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id
+blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=10
+
+blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth
+blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092
+blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id
+blueprintsprocessor.messageproducer.self-service-api.topic=producer.t
diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration_enriched.zip b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration_enriched.zip
deleted file mode 100755 (executable)
index 9581191..0000000
Binary files a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration_enriched.zip and /dev/null differ
@@ -1,35 +1,35 @@
-<!--\r
-  ~ Copyright © 2017-2018 AT&T Intellectual Property.\r
-  ~\r
-  ~ Licensed under the Apache License, Version 2.0 (the "License");\r
-  ~ you may not use this file except in compliance with the License.\r
-  ~ You may obtain a copy of the License at\r
-  ~\r
-  ~     http://www.apache.org/licenses/LICENSE-2.0\r
-  ~\r
-  ~ Unless required by applicable law or agreed to in writing, software\r
-  ~ distributed under the License is distributed on an "AS IS" BASIS,\r
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-  ~ See the License for the specific language governing permissions and\r
-  ~ limitations under the License.\r
-  -->\r
-\r
-<configuration>\r
-    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">\r
-        <!-- encoders are assigned the type\r
-             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->\r
-        <encoder>\r
-            <pattern>%d{HH:mm:ss.SSS} %-5level %logger{100} - %msg%n</pattern>\r
-        </encoder>\r
-    </appender>\r
-\r
-\r
-    <logger name="org.springframework" level="warn"/>\r
-    <logger name="org.hibernate" level="info"/>\r
-    <logger name="org.onap.ccsdk.cds.blueprintsprocessor" level="info"/>\r
-\r
-    <root level="warn">\r
-        <appender-ref ref="STDOUT"/>\r
-    </root>\r
-\r
-</configuration>\r
+<!--
+  ~ Copyright © 2017-2018 AT&T Intellectual Property.
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<configuration>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- encoders are assigned the type
+             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+
+    <logger name="org.springframework" level="warn"/>
+    <logger name="org.hibernate" level="info"/>
+    <logger name="org.onap.ccsdk.cds.blueprintsprocessor" level="info"/>
+
+    <root level="warn">
+        <appender-ref ref="STDOUT"/>
+    </root>
+
+</configuration>
index 34b6912..34eba83 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>outbounds</artifactId>
index 86a5814..ea39e2a 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
 
index c232f05..4acc224 100644 (file)
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>services</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>execution-service</artifactId>
index 6b9cb2e..0a5f9b6 100755 (executable)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
 
     <artifactId>services</artifactId>
index 1a621f4..c3effa5 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
         <artifactId>services</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
index e79c497..5a54a77 100755 (executable)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>blueprintsprocessor</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId>
     <artifactId>parent</artifactId>
index abe737f..7714d85 100755 (executable)
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>ms</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>blueprintsprocessor</artifactId>
index e99c4ec..5861912 100755 (executable)
   ~  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>
         <artifactId>ms</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <artifactId>command-executor</artifactId>
@@ -35,7 +34,7 @@
         <docker.verbose>true</docker.verbose>
         <ccsdk.project.version>${project.version}</ccsdk.project.version>
         <ccsdk.build.timestamp>${maven.build.timestamp}</ccsdk.build.timestamp>
-        <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+               <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
     </properties>
 
     <build>
index abea4d4..972dad6 100644 (file)
@@ -35,7 +35,6 @@ class CommandExecutorHandler():
         self.request = request
         self.logger = logging.getLogger(self.__class__.__name__)
         self.blueprint_id = utils.get_blueprint_id(request)
-        # FIXME parameterize path
         self.venv_home = '/opt/app/onap/blueprints/deploy/' + self.blueprint_id
         self.installed = self.venv_home + '/.installed'
 
@@ -61,6 +60,7 @@ class CommandExecutorHandler():
             results.append(f.read())
             f.close()
 
+        # deactivate_venv(blueprint_id)
         return True
 
     def execute_command(self, request, results):
@@ -73,7 +73,6 @@ class CommandExecutorHandler():
         if "ansible-playbook" in request.command:
             cmd = cmd + "; " + request.command + " -e 'ansible_python_interpreter=" + self.venv_home + "/bin/python'"
         else:
-            # we append the properties as last agr to the script
             cmd = cmd + "; " + request.command + " " + re.escape(MessageToJson(request.properties))
 
         try:
@@ -171,8 +170,8 @@ class CommandExecutorHandler():
 
         path = "%s/bin/activate_this.py" % self.venv_home
         try:
-            exec(open(path).read(), {'__file__': path})
-            exec(fixpathenvvar)
+            exec (open(path).read(), {'__file__': path})
+            exec (fixpathenvvar)
             self.logger.info("Running with PATH : {}".format(os.environ['PATH']))
             return True
         except Exception as err:
index 0ed3d32..453d751 100644 (file)
@@ -1,4 +1,5 @@
-# !/usr/bin/python
+
+#!/usr/bin/python
 
 #
 # Copyright (C) 2019 Bell Canada.
@@ -42,7 +43,7 @@ def serve():
         'Access denied!')
 
     server = grpc.server(
-        futures.ProcessPoolExecutor(),
+        futures.ThreadPoolExecutor(max_workers=10),
         interceptors=(header_validator,))
 
     CommandExecutor_pb2_grpc.add_CommandExecutorServiceServicer_to_server(
index 4314b28..dc5d008 100644 (file)
@@ -17,7 +17,6 @@ from google.protobuf.timestamp_pb2 import Timestamp
 
 import proto.CommandExecutor_pb2 as CommandExecutor_pb2
 
-
 def get_blueprint_id(request):
     blueprint_name = request.identifiers.blueprintName
     blueprint_version = request.identifiers.blueprintVersion
index 1c1385b..1cb912c 100644 (file)
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>blueprint-core</artifactId>
     <name>Controller Blueprints Core</name>
index 08bc6c3..b74b7e4 100644 (file)
@@ -54,6 +54,10 @@ fun String.asJsonPrimitive(): TextNode {
     return TextNode(this)
 }
 
+inline fun <reified T : Any> String.jsonAsType(): T {
+    return JacksonUtils.readValue<T>(this.trim())
+}
+
 // If you know the string is json content, then use the function directly
 fun String.jsonAsJsonType(): JsonNode {
     return JacksonUtils.jsonNode(this.trim())
diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/utils/DateUtils.kt
new file mode 100644 (file)
index 0000000..e01ba80
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  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.utils
+
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+
+fun currentTimestamp(): String {
+    val now = LocalDateTime.now(ZoneId.systemDefault())
+    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
+    return formatter.format(now)
+}
index 57865fc..04c7511 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>blueprint-validation</artifactId>
     <name>Controller Blueprints Validation Service</name>
index 2ef7016..d493481 100644 (file)
@@ -1,5 +1,6 @@
 /*
  *  Copyright © 2019 IBM.
+ *  Modifications 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.
@@ -51,7 +52,7 @@ open class PropertyAssignmentValidationUtils(private val bluePrintContext: BlueP
                                          properties: MutableMap<String, JsonNode>) {
         properties.forEach { propertyName, propertyAssignment ->
             val propertyDefinition: PropertyDefinition = nodeTypeProperties[propertyName]
-                    ?: throw BluePrintException("failed to get definition for the property ($propertyName)")
+                    ?: throw BluePrintException("validatePropertyAssignments failed to get definition for the property ($propertyName)")
 
             validatePropertyAssignment(propertyName, propertyDefinition, propertyAssignment)
 
@@ -91,7 +92,7 @@ open class PropertyAssignmentValidationUtils(private val bluePrintContext: BlueP
         }
 
         check(isValid) {
-            throw BluePrintException("property($propertyName) defined of type($propertyType) is not comptable with the value ($propertyAssignment)")
+            throw BluePrintException("property($propertyName) defined of type($propertyType) is not compatible with the value ($propertyAssignment)")
         }
     }
 
index 4bc962f..73b2313 100644 (file)
@@ -20,7 +20,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
     <artifactId>modules</artifactId>
index b210b10..4ee4f91 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
         <artifactId>modules</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <artifactId>resource-dict</artifactId>
     <name>Controller Blueprints Resource Dictionary</name>
index 3021c40..925b167 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>controllerblueprints</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId>
     <artifactId>parent</artifactId>
index 909dfa4..8abb36e 100644 (file)
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>ms</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>controllerblueprints</artifactId>
     <name>Controller Blueprints Root</name>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <properties>
         <service.name>ControllerBlueprints</service.name>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
index 973222c..ba5a5b0 100644 (file)
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
 
     <artifactId>ms</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>Micro-services Root</name>
index eb0323b..da24e97 100644 (file)
   <parent>
     <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
     <artifactId>parent</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <relativePath>../parent</relativePath>
   </parent>
 
   <artifactId>application</artifactId>
   <packaging>jar</packaging>
-  <version>0.6.1-SNAPSHOT</version>
+  <version>0.7.0-SNAPSHOT</version>
   <name>SDC Listener Application</name>
 
   <properties>
index be68cd2..8f0120f 100755 (executable)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
         <artifactId>parent</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>../parent</relativePath>
     </parent>
     <artifactId>distribution</artifactId>
index 0648ed7..cfdfc9b 100755 (executable)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>sdclistener</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
     </parent>
     <groupId>org.onap.ccsdk.cds.sdclistener</groupId>
     <artifactId>parent</artifactId>
index b311388..42c6a1a 100644 (file)
@@ -19,7 +19,7 @@
     <parent>
         <groupId>org.onap.ccsdk.cds</groupId>
         <artifactId>ms</artifactId>
-        <version>0.6.1-SNAPSHOT</version>
+        <version>0.7.0-SNAPSHOT</version>
         <relativePath>..</relativePath>
     </parent>
 
diff --git a/pom.xml b/pom.xml
index 12cabac..ddeb8c8 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -20,7 +20,7 @@ limitations under the License.
     <parent>
         <groupId>org.onap.ccsdk.parent</groupId>
         <artifactId>spring-boot-starter-parent</artifactId>
-        <version>1.4.1-SNAPSHOT</version>
+        <version>1.5.0-SNAPSHOT</version>
         <relativePath/>
     </parent>
 
@@ -28,7 +28,7 @@ limitations under the License.
 
     <groupId>org.onap.ccsdk.cds</groupId>
     <artifactId>parent</artifactId>
-    <version>0.6.1-SNAPSHOT</version>
+    <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>cds-parent</name>
diff --git a/releases/0.6.1.yaml b/releases/0.6.1.yaml
new file mode 100644 (file)
index 0000000..46921af
--- /dev/null
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.1'
+project: 'ccsdk-cds'
+log_dir: 'ccsdk-cds-maven-stage-master/208/'
index 5d94f48..fc68f02 100644 (file)
@@ -5,8 +5,8 @@
 
 
 release_name=0
-sprint_number=6
-feature_revision=1
+sprint_number=7
+feature_revision=0
 
 base_version=${release_name}.${sprint_number}.${feature_revision}