diff options
52 files changed, 1208 insertions, 221 deletions
diff --git a/cds-ui/client/src/app/feature-modules/blueprint/select-template/template-options/template-options.component.html b/cds-ui/client/src/app/feature-modules/blueprint/select-template/template-options/template-options.component.html index d66b559f3..57ff00df5 100644 --- a/cds-ui/client/src/app/feature-modules/blueprint/select-template/template-options/template-options.component.html +++ b/cds-ui/client/src/app/feature-modules/blueprint/select-template/template-options/template-options.component.html @@ -19,7 +19,7 @@ limitations under the License. ============LICENSE_END============================================ --> <mat-radio-group> - <mat-radio-button value="1" (click)="selected(1)">Upload Template file</mat-radio-button><br><br> - <!-- <mat-radio-button value="2" (click)="selected(2)">Starter Template</mat-radio-button><br><br> - <mat-radio-button value="3" (click)="selected(3)">Existing Model File</mat-radio-button> --> + <mat-radio-button value="1" (click)="selected(1)">Upload Template file</mat-radio-button><br> <br> + <mat-radio-button value="2" (click)="selected(2)">Starter Template</mat-radio-button><br> <br> + <mat-radio-button value="3" (click)="selected(3)">Existing Model File</mat-radio-button> </mat-radio-group>
\ No newline at end of file diff --git a/cds-ui/server/config/app-config.ts b/cds-ui/server/config/app-config.ts deleted file mode 100644 index 80f246427..000000000 --- a/cds-ui/server/config/app-config.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const controllerApiConfig = Object.freeze({ - url: process.env.API_BLUEPRINT_CONTROLLER_BASE_URL || "http://localhost:8080/api/v1", - authToken: process.env.API_BLUEPRINT_CONTROLLER_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==" -}); - -export const processorApiConfig = Object.freeze({ - url: process.env.API_BLUEPRINT_PROCESSOR_BASE_URL || "http://localhost:8081/api/v1", - authToken: process.env.API_BLUEPRINT_PROCESSOR_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==" -});
\ No newline at end of file diff --git a/cds-ui/server/package.json b/cds-ui/server/package.json index 5b8f7e67c..2f33abae7 100644 --- a/cds-ui/server/package.json +++ b/cds-ui/server/package.json @@ -12,7 +12,7 @@ }, "scripts": { "build:apidocs": "lb-apidocs", - "build": "lb-tsc es2017 --outDir dist", + "build": "npm run copy:proto && lb-tsc es2017 --copy-resources --outDir dist", "build:watch": "lb-tsc --watch", "clean": "lb-clean dist", "lint": "npm run prettier:check && npm run tslint", @@ -29,7 +29,8 @@ "migrate": "node ./dist/src/migrate", "prestart": "npm run build", "start": "node .", - "prepublishOnly": "npm run test" + "prepublishOnly": "npm run test", + "copy:proto": "mkdir -p dist; cp -R target/generated/proto-definition/proto/ dist/proto" }, "repository": { "type": "git" @@ -45,6 +46,7 @@ "src" ], "dependencies": { + "@grpc/proto-loader": "^0.5.1", "@loopback/boot": "^1.0.8", "@loopback/context": "^1.16.0", "@loopback/core": "^1.1.3", @@ -55,6 +57,7 @@ "@loopback/service-proxy": "^1.0.8", "@types/form-data": "^2.2.1", "@types/jszip": "^3.1.5", + "@types/uuid": "^3.4.4", "bluebird": "^3.5.3", "cors": "^2.8.5", "file": "^0.2.2", @@ -63,11 +66,13 @@ "form-data": "^2.3.3", "formidable": "^1.2.1", "fs": "0.0.1-security", + "grpc": "^1.21.1", "jszip": "^3.2.1", "loopback-connector-rest": "^3.4.1", "multer": "^1.4.1", "multiparty": "^4.2.1", "nodemon": "^1.18.10", + "uuid": "^3.3.2", "winston": "^3.2.1" }, "devDependencies": { diff --git a/cds-ui/server/pom.xml b/cds-ui/server/pom.xml index ae9b1b293..8d758c710 100644 --- a/cds-ui/server/pom.xml +++ b/cds-ui/server/pom.xml @@ -42,9 +42,38 @@ limitations under the License. <docker.push.phase>deploy</docker.push.phase> </properties> + <build> <plugins> <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.1.1</version> + <executions> + <execution> + <id>unpack-blueprint-grpc-proto</id> + <phase>generate-resources</phase> + <goals> + <goal>unpack</goal> + </goals> + <configuration> + <artifactItems> + <artifactItem> + <groupId>org.onap.ccsdk.cds.components</groupId> + <artifactId>proto-definition</artifactId> + <version>${project.version}</version> + <type>jar</type> + <overWrite>true</overWrite> + <outputDirectory>${project.build.directory}/generated/proto-definition/proto</outputDirectory> + <includes>**/*.proto</includes> + </artifactItem> + </artifactItems> + </configuration> + </execution> + </executions> + </plugin> + + <plugin> <groupId>com.github.eirslett</groupId> <artifactId>frontend-maven-plugin</artifactId> <!-- Use the latest released version: https://repo1.maven.org/maven2/com/github/eirslett/frontend-maven-plugin/ --> diff --git a/cds-ui/server/src/clients/blueprint-management-service-grpc-client.ts b/cds-ui/server/src/clients/blueprint-management-service-grpc-client.ts new file mode 100644 index 000000000..b66b2a771 --- /dev/null +++ b/cds-ui/server/src/clients/blueprint-management-service-grpc-client.ts @@ -0,0 +1,86 @@ +/** + ~ Copyright © 2019 Bell Canada. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +*/ +import * as fs from 'fs'; +import * as uuidv1 from 'uuid/v1'; +const grpc = require('grpc'); +import * as protoLoader from '@grpc/proto-loader'; +import {processorApiConfig} from '../config/app-config'; + +const PROTO_PATH = processorApiConfig.grpc.bluePrintManagement.protoPath; + +// Suggested options for similarity to existing grpc.load behavior +const packageDefinition: protoLoader.PackageDefinition = protoLoader.loadSync( + PROTO_PATH, + { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true + }); + +const protoDescriptor = grpc.loadPackageDefinition(packageDefinition); +// The protoDescriptor object has the full package hierarchy + +const stub = new protoDescriptor.org.onap.ccsdk.cds.controllerblueprints.management.api.BluePrintManagementService( + "" + processorApiConfig.grpc.host + ":" + processorApiConfig.grpc.port + "", + grpc.credentials.createInsecure()); + +const metadata = new grpc.Metadata(); +metadata.add('Authorization', processorApiConfig.grpc.authToken); + +class BluePrintManagementServiceGrpcClient { + + async uploadBlueprint(filePath: string): Promise<any> { + + let input = { + commonHeader: { + timestamp: new Date(), + originatorId: "cds-ui", + requestId: uuidv1(), + subRequestId: "1234-56", + }, + fileChunk: { + chunk: fs.readFileSync(filePath) + } + } + + let removeTempFile = () => { + fs.unlink(filePath, (err: any) => { + if (err) { + console.error(err); + } + }); + } + + return new Promise<any>((resolve, reject) => { + stub.uploadBlueprint(input, metadata, (err: any, output: any) => { + if (err) { + removeTempFile(); + reject(err); + return; + } + + removeTempFile(); + resolve(output); + }); + }); + + } +} + +export const bluePrintManagementServiceGrpcClient = new BluePrintManagementServiceGrpcClient(); + diff --git a/cds-ui/server/src/config/app-config.ts b/cds-ui/server/src/config/app-config.ts new file mode 100644 index 000000000..24aeb26b5 --- /dev/null +++ b/cds-ui/server/src/config/app-config.ts @@ -0,0 +1,47 @@ +/** + ~ Copyright © 2019 Bell Canada. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. +*/ +export const appConfig = Object.freeze({ + action: Object.freeze({ + deployBlueprint: Object.freeze({ + grpcEnabled: process.env.APP_ACTION_DEPLOY_BLUEPRINT_GRPC_ENABLED || true + }) + }) +}); + +export const controllerApiConfig = Object.freeze({ + http: Object.freeze({ + url: process.env.API_BLUEPRINT_CONTROLLER_HTTP_BASE_URL || "http://localhost:8080/api/v1", + authToken: process.env.API_BLUEPRINT_CONTROLLER_HTTP_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==" + }) +}); + +export const processorApiConfig = Object.freeze({ + http: Object.freeze({ + url: process.env.API_BLUEPRINT_PROCESSOR_HTTP_BASE_URL || "http://localhost:8081/api/v1", + authToken: process.env.API_BLUEPRINT_PROCESSOR_HTTP_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==" + }), + grpc: Object.freeze({ + host: process.env.API_BLUEPRINT_PROCESSOR_GRPC_HOST || "localhost", + port: process.env.API_BLUEPRINT_PROCESSOR_GRPC_PORT || 9111, + authToken: process.env.API_BLUEPRINT_PROCESSOR_GRPC_AUTH_TOKEN || "Basic Y2NzZGthcHBzOmNjc2RrYXBwcw==", + bluePrintManagement: Object.freeze({ + //this path is relative to 'dist' folder + protoPath: __dirname + '../../../proto/BluePrintManagement.proto' + }) + }) +}); + + diff --git a/cds-ui/server/src/controllers/blueprint-rest.controller.ts b/cds-ui/server/src/controllers/blueprint-rest.controller.ts index 877fa02bb..52e77ee7b 100644 --- a/cds-ui/server/src/controllers/blueprint-rest.controller.ts +++ b/cds-ui/server/src/controllers/blueprint-rest.controller.ts @@ -48,7 +48,8 @@ import { BlueprintService } from '../services'; import * as fs from 'fs'; import * as multiparty from 'multiparty'; import * as request_lib from 'request'; -import {controllerApiConfig, processorApiConfig} from '../../config/app-config'; +import {controllerApiConfig, processorApiConfig, appConfig} from '../config/app-config'; +import {bluePrintManagementServiceGrpcClient} from '../clients/blueprint-management-service-grpc-client'; export class BlueprintRestController { constructor( @@ -197,11 +198,10 @@ export class BlueprintRestController { ): Promise<Response> { return new Promise((resolve, reject) => { this.getFileFromMultiPartForm(request).then(file=>{ - this.uploadFileToBlueprintProcessor(file, "/execution-service/upload/", response).then(resp=>{ - resolve(resp); - }, err=>{ - reject(err); - }); + if(appConfig.action.deployBlueprint.grpcEnabled) + return this.uploadFileToBlueprintProcessorGrpc(file, response); + else + return this.uploadFileToBlueprintProcessor(file, "/execution-service/upload/", response); }, err=>{ reject(err); }); @@ -209,11 +209,11 @@ export class BlueprintRestController { } async uploadFileToBlueprintController(file: multiparty.File, uri: string, response: Response): Promise<Response>{ - return this.uploadFileToBlueprintService(file, controllerApiConfig.url + uri, controllerApiConfig.authToken, response); + return this.uploadFileToBlueprintService(file, controllerApiConfig.http.url + uri, controllerApiConfig.http.authToken, response); } async uploadFileToBlueprintProcessor(file: multiparty.File, uri: string, response: Response): Promise<Response>{ - return this.uploadFileToBlueprintService(file, processorApiConfig.url + uri, processorApiConfig.authToken, response); + return this.uploadFileToBlueprintService(file, processorApiConfig.http.url + uri, processorApiConfig.http.authToken, response); } async uploadFileToBlueprintService(file: multiparty.File, url: string, authToken: string, response: Response): Promise<Response>{ @@ -256,7 +256,7 @@ export class BlueprintRestController { } async downloadFileFromBlueprintController(uri: string, response: Response): Promise<Response> { - return this.downloadFileFromBlueprintService(controllerApiConfig.url + uri, controllerApiConfig.authToken, response); + return this.downloadFileFromBlueprintService(controllerApiConfig.http.url + uri, controllerApiConfig.http.authToken, response); } async downloadFileFromBlueprintService(url: string, authToken: string, response: Response): Promise<Response> { @@ -277,4 +277,16 @@ export class BlueprintRestController { }); }) } + + async uploadFileToBlueprintProcessorGrpc(file: multiparty.File, response: Response): Promise<Response> { + return new Promise<Response>((resolve, reject) => { + bluePrintManagementServiceGrpcClient.uploadBlueprint(file.path).then(output=>{ + response.send(output.status.message); + resolve(response); + }, err=>{ + response.status(500).send(err); + resolve(response); + }); + }); + } }
\ No newline at end of file diff --git a/cds-ui/server/src/datasources/blueprint.datasource-template.ts b/cds-ui/server/src/datasources/blueprint.datasource-template.ts index f5dad3a1e..35edf33e3 100644 --- a/cds-ui/server/src/datasources/blueprint.datasource-template.ts +++ b/cds-ui/server/src/datasources/blueprint.datasource-template.ts @@ -1,19 +1,19 @@ -import {controllerApiConfig} from '../../config/app-config'; +import {controllerApiConfig} from '../config/app-config'; export default { "name": "blueprint", "connector": "rest", - "baseURL": controllerApiConfig.url, + "baseURL": controllerApiConfig.http.url, "crud": false, "debug": true, "operations": [{ "template": { "method": "GET", - "url": controllerApiConfig.url + "/blueprint-model/", + "url": controllerApiConfig.http.url + "/blueprint-model/", "headers": { "accepts": "application/json", "content-type": "application/json", - "authorization": controllerApiConfig.authToken + "authorization": controllerApiConfig.http.authToken }, "responsePath": "$.*" }, diff --git a/cds-ui/server/src/datasources/resource-dictionary.datasource-template.ts b/cds-ui/server/src/datasources/resource-dictionary.datasource-template.ts index 1c459e0e7..c749eee62 100644 --- a/cds-ui/server/src/datasources/resource-dictionary.datasource-template.ts +++ b/cds-ui/server/src/datasources/resource-dictionary.datasource-template.ts @@ -1,19 +1,19 @@ -import {controllerApiConfig} from '../../config/app-config'; +import {controllerApiConfig} from '../config/app-config'; export default { "name": "resourceDictionary", "connector": "rest", - "baseURL": controllerApiConfig.url + "/dictionary", + "baseURL": controllerApiConfig.http.url + "/dictionary", "crud": false, "debug": true, "operations": [{ "template": { "method": "GET", - "url": controllerApiConfig.url + "/dictionary/{name}", + "url": controllerApiConfig.http.url + "/dictionary/{name}", "headers": { "accepts": "application/json", "content-type": "application/json", - "authorization": controllerApiConfig.authToken + "authorization": controllerApiConfig.http.authToken }, "responsePath": "$.*" }, @@ -25,11 +25,11 @@ export default { { "template": { "method": "GET", - "url": controllerApiConfig.url + "/dictionary/source-mapping", + "url": controllerApiConfig.http.url + "/dictionary/source-mapping", "headers": { "accepts": "application/json", "content-type": "application/json", - "authorization": controllerApiConfig.authToken + "authorization": controllerApiConfig.http.authToken }, "responsePath": "$.*" }, @@ -41,11 +41,11 @@ export default { { "template": { "method": "GET", - "url": controllerApiConfig.url + "/dictionary/search/{tags}", + "url": controllerApiConfig.http.url + "/dictionary/search/{tags}", "headers": { "accepts": "application/json", "content-type": "application/json", - "authorization": controllerApiConfig.authToken + "authorization": controllerApiConfig.http.authToken }, "responsePath": "$.*" }, @@ -57,11 +57,11 @@ export default { { "template": { "method": "POST", - "url": controllerApiConfig.url + "/dictionary", + "url": controllerApiConfig.http.url + "/dictionary", "headers": { "accepts": "application/json", "content-type": "application/json", - "authorization": controllerApiConfig.authToken + "authorization": controllerApiConfig.http.authToken }, "body": "{resourceDictionary}", "responsePath": "$.*" @@ -74,11 +74,11 @@ export default { { "template": { "method": "POST", - "url": controllerApiConfig.url + "/dictionary/by-names", + "url": controllerApiConfig.http.url + "/dictionary/by-names", "headers": { "accepts": "application/json", "content-type": "application/json", - "authorization": controllerApiConfig.authToken + "authorization": controllerApiConfig.http.authToken }, "body": "{resourceDictionaryList}", "responsePath": "$.*" diff --git a/cds-ui/server/src/sequence.ts b/cds-ui/server/src/sequence.ts index b282cbc62..84da5249d 100644 --- a/cds-ui/server/src/sequence.ts +++ b/cds-ui/server/src/sequence.ts @@ -31,6 +31,7 @@ import { SequenceHandler, } from '@loopback/rest'; import { logger } from './logger/logger'; +import { v4 as uuid } from 'uuid'; const SequenceActions = RestBindings.SequenceActions; @@ -44,16 +45,22 @@ export class MySequence implements SequenceHandler { ) { } async handle(context: RequestContext) { + const { request, response } = context; try { - const { request, response } = context; - logger.info("Incoming request from %s %s and with header %s query %s params %s", - request.method, request.url, JSON.stringify(request.headers), JSON.stringify(request.query), JSON.stringify(request.params)) + if (!('X-ONAP-RequestID' in request.headers || 'x-onap-requestid' in request.headers)) { + request.headers = { 'X-ONAP-RequestID': uuid(), ...request.headers} + logger.info(JSON.stringify(request.headers)) + } const route = this.findRoute(request); const args = await this.parseParams(request, route); const result = await this.invoke(route, args); this.send(response, result); } catch (err) { this.reject(context, err); + } finally { + const { authorization, ...headers} = request.headers; + logger.info("Incoming request from %s %s and with header %s query %s params %s and response code: %s", + request.method, request.url, JSON.stringify(headers), JSON.stringify(request.query), JSON.stringify(request.params), JSON.stringify(response.statusCode)) } } } diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml index 06726ad11..0f9e08b5f 100755 --- a/ms/blueprintsprocessor/application/pom.xml +++ b/ms/blueprintsprocessor/application/pom.xml @@ -17,7 +17,8 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> @@ -124,10 +125,6 @@ </resources> <plugins> <plugin> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-maven-plugin</artifactId> - </plugin> - <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <executions> diff --git a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java index 2b6f8bcf1..c6400db35 100644 --- a/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java +++ b/ms/blueprintsprocessor/application/src/main/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplication.java @@ -29,8 +29,7 @@ import org.springframework.context.annotation.ComponentScan; */ @SpringBootApplication @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) -@ComponentScan(basePackages = {"org.onap.ccsdk.cds.controllerblueprints", - "org.onap.ccsdk.cds.blueprintsprocessor"}) +@ComponentScan(basePackages = {"org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"}) public class BlueprintProcessorApplication { public static void main(String[] args) { diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties index a94fdf390..fae1adb72 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties @@ -1,3 +1,4 @@ +<<<<<<< HEAD # # Copyright � 2017-2018 AT&T Intellectual Property. # @@ -73,3 +74,12 @@ blueprintsprocessor.cliExecutor.enabled=true ### If enabling remote python executor, set this value to true ### blueprintprocessor.remoteScriptCommand.enabled=true blueprintprocessor.remoteScriptCommand.enabled=false + +# Kafka-message-lib Configurations +blueprintsprocessor.messageclient.self-service-api.topic=producer.t +blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth +blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t +blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id +blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id +blueprintsprocessor.messageclient.self-service-api.kafkaEnable=false diff --git a/ms/blueprintsprocessor/application/src/main/resources/application.properties b/ms/blueprintsprocessor/application/src/main/resources/application.properties index 1319d9fb5..d6e7dc890 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application.properties @@ -72,3 +72,11 @@ blueprintsprocessor.restclient.primary-aai-data.url=https://aai.onap:8443 blueprintsprocessor.restclient.primary-aai-data.username=aai@aai.onap.org blueprintsprocessor.restclient.primary-aai-data.password=demo123456! +# Kafka-message-lib Configuration +blueprintsprocessor.messageclient.self-service-api.topic=producer.t +blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth +blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t +blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id +blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id +blueprintsprocessor.messageclient.self-service-api.kafkaEnable=false diff --git a/ms/blueprintsprocessor/application/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplicationTest.java b/ms/blueprintsprocessor/application/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplicationTest.java index 90783d40f..fc36e6287 100644 --- a/ms/blueprintsprocessor/application/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplicationTest.java +++ b/ms/blueprintsprocessor/application/src/test/java/org/onap/ccsdk/cds/blueprintsprocessor/BlueprintProcessorApplicationTest.java @@ -16,7 +16,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor; - import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -34,7 +33,6 @@ import org.springframework.test.context.junit4.SpringRunner; * @author Brinda Santh * DATE : 8/14/2018 */ - @RunWith(SpringRunner.class) @ContextConfiguration(classes = {BlueprintProcessorApplication.class, BluePrintLoadConfiguration.class}) @SpringBootTest(classes = BlueprintProcessorApplication.class, diff --git a/ms/blueprintsprocessor/application/src/test/resources/application.properties b/ms/blueprintsprocessor/application/src/test/resources/application.properties index 09ee651a4..ea2f976a3 100644 --- a/ms/blueprintsprocessor/application/src/test/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/test/resources/application.properties @@ -46,3 +46,13 @@ blueprintprocessor.netconfExecutor.enabled=true blueprintprocessor.restConfExecutor.enabled=true blueprintsprocessor.cliExecutor.enabled=true blueprintprocessor.remoteScriptCommand.enabled=false + + +# Kafka-message-lib Configuration +blueprintsprocessor.messageclient.self-service-api.topic=producer.t +blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth +blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t +blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id +blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id +blueprintsprocessor.messageclient.self-service-api.kafkaEnable=false diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt deleted file mode 100644 index 65d1c3eee..000000000 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/CliComponentFunction.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright © 2019 IBM. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor - -import kotlinx.coroutines.runBlocking -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants -import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService -import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction -import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshLibConstants -import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BluePrintSshLibPropertyService -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile -import org.onap.ccsdk.cds.controllerblueprints.core.readNBLines -import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService - -abstract class CliComponentFunction : AbstractScriptComponentFunction() { - - open fun bluePrintSshLibPropertyService(): BluePrintSshLibPropertyService = - functionDependencyInstanceAsType(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY) - - open fun resourceResolutionService(): ResourceResolutionService = - functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) - - - open suspend fun readCommandLinesFromArtifact(artifactName: String): List<String> { - val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) - val file = normalizedFile(bluePrintRuntimeService.bluePrintContext().rootPath, artifactDefinition.file) - return file.readNBLines() - } - - fun generateMessage(artifactName: String): String { - return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) - } - - fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking { - resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) - } - - fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { - resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, - artifactPrefix, mapOf()) - } -}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt index 0c1c52320..e1d8825ba 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutor.kt @@ -16,12 +16,8 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor -import com.fasterxml.jackson.databind.node.ArrayNode -import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput -import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService -import org.onap.ccsdk.cds.blueprintsprocessor.ssh.SshLibConstants -import org.onap.ccsdk.cds.controllerblueprints.core.getAsString +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.context.annotation.Scope import org.springframework.stereotype.Component @@ -29,43 +25,4 @@ import org.springframework.stereotype.Component @Component("component-cli-executor") @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) open class ComponentCliExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService) - : AbstractComponentFunction() { - - companion object { - const val SCRIPT_TYPE = "script-type" - const val SCRIPT_CLASS_REFERENCE = "script-class-reference" - const val INSTANCE_DEPENDENCIES = "instance-dependencies" - const val RESPONSE_DATA = "response-data" - } - - private lateinit var scriptComponent: CliComponentFunction - - override suspend fun processNB(executionRequest: ExecutionServiceInput) { - - val scriptType = operationInputs.getAsString(SCRIPT_TYPE) - val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE) - val instanceDependenciesNode = operationInputs[INSTANCE_DEPENDENCIES] as? ArrayNode - - val scriptDependencies: MutableList<String> = arrayListOf() - scriptDependencies.add(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY) - // May be injected from model, not by default - //scriptDependencies.add(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) - - instanceDependenciesNode?.forEach { instanceName -> - scriptDependencies.add(instanceName.textValue()) - } - - scriptComponent = componentFunctionScriptingService.scriptInstance(this, scriptType, - scriptClassReference, scriptDependencies) - - - // Handles both script processing and error handling - scriptComponent.executeScript(executionServiceInput) - } - - override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { - bluePrintRuntimeService.getBluePrintError() - .addError("Failed in ComponentCliExecutor : ${runtimeException.message}") - - } -}
\ No newline at end of file + : ComponentScriptExecutor(componentFunctionScriptingService)
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ScriptComponentExtensions.kt new file mode 100644 index 000000000..81f1fd821 --- /dev/null +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ScriptComponentExtensions.kt @@ -0,0 +1,22 @@ +/* + * Copyright © 2019 IBM. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor + +/** + * Register the CLI module exposed dependency + */ + diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts index 0955ace79..e62374747 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts +++ b/ms/blueprintsprocessor/functions/cli-executor/src/main/kotlin/scripts/InternalSimpleCli.cba.kts @@ -17,22 +17,23 @@ @file:Suppress("unused") import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput -import org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor.CliComponentFunction -import org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor.ComponentCliExecutor +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor +import org.onap.ccsdk.cds.blueprintsprocessor.ssh.sshClientService import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive -import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintTemplateService +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService import org.slf4j.LoggerFactory -open class TestCliScriptFunction : CliComponentFunction() { +open class TestCliScriptFunction : AbstractScriptComponentFunction() { - private val log = LoggerFactory.getLogger(CliComponentFunction::class.java)!! + private val log = LoggerFactory.getLogger(TestCliScriptFunction::class.java.canonicalName)!! override fun getName(): String { return "SimpleCliConfigure" } override suspend fun processNB(executionRequest: ExecutionServiceInput) { - log.info("Executing process") + log.info("Executing process ...") } override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { @@ -41,9 +42,9 @@ open class TestCliScriptFunction : CliComponentFunction() { } -open class Check : CliComponentFunction() { +open class Check : AbstractScriptComponentFunction() { - private val log = LoggerFactory.getLogger(CliComponentFunction::class.java)!! + private val log = LoggerFactory.getLogger(AbstractScriptComponentFunction::class.java)!! override fun getName(): String { return "Check" @@ -54,12 +55,12 @@ open class Check : CliComponentFunction() { val deviceInformation = bluePrintRuntimeService.resolveDSLExpression("device-properties") // Get the Client Service - val sshClientService = bluePrintSshLibPropertyService().blueprintSshClientService(deviceInformation) + val sshClientService = BluePrintDependencyService.sshClientService(deviceInformation) sshClientService.startSessionNB() // Read Commands - val commands = readCommandLinesFromArtifact("command-template") + val commands = readLinesFromArtifact("command-template") // Execute multiple Commands val responseLog = sshClientService.executeCommandsNB(commands, 5000) @@ -68,7 +69,7 @@ open class Check : CliComponentFunction() { sshClientService.closeSessionNB() // Set the Response Data - setAttribute(ComponentCliExecutor.RESPONSE_DATA, responseLog.asJsonPrimitive()) + setAttribute(ComponentScriptExecutor.RESPONSE_DATA, responseLog.asJsonPrimitive()) log.info("Executing process") } diff --git a/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt b/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt index 6455513f2..658092f0a 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/cli-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/cli/executor/ComponentCliExecutorTest.kt @@ -17,7 +17,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.node.ArrayNode import com.fasterxml.jackson.databind.node.ObjectNode import io.mockk.every import io.mockk.mockk @@ -30,11 +29,13 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentScriptExecutor import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.ssh.BluePrintSshLibConfiguration import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService import org.onap.ccsdk.cds.controllerblueprints.core.service.DefaultBluePrintRuntimeService import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.scripts.BluePrintScriptsServiceImpl @@ -49,7 +50,7 @@ import kotlin.test.assertNotNull @ContextConfiguration(classes = [CliExecutorConfiguration::class, ExecutionServiceConfiguration::class, BluePrintSshLibConfiguration::class, BluePrintScriptsServiceImpl::class, - BlueprintPropertyConfiguration::class, BluePrintProperties::class]) + BlueprintPropertyConfiguration::class, BluePrintProperties::class, BluePrintDependencyService::class]) @DirtiesContext @TestPropertySource(properties = [], locations = ["classpath:application-test.properties"]) class ComponentCliExecutorTest { @@ -78,10 +79,9 @@ class ComponentCliExecutorTest { operationInputs[BluePrintConstants.PROPERTY_CURRENT_NODE_TEMPLATE] = "activate-cli".asJsonPrimitive() operationInputs[BluePrintConstants.PROPERTY_CURRENT_INTERFACE] = "interfaceName".asJsonPrimitive() operationInputs[BluePrintConstants.PROPERTY_CURRENT_OPERATION] = "operationName".asJsonPrimitive() - operationInputs[ComponentCliExecutor.SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive() - operationInputs[ComponentCliExecutor.SCRIPT_CLASS_REFERENCE] = + operationInputs[ComponentScriptExecutor.SCRIPT_TYPE] = BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive() + operationInputs[ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE] = "InternalSimpleCli_cba\$TestCliScriptFunction".asJsonPrimitive() - operationInputs[ComponentCliExecutor.INSTANCE_DEPENDENCIES] = JacksonUtils.jsonNode("[]") as ArrayNode val stepInputData = StepData().apply { name = "activate-cli" diff --git a/ms/blueprintsprocessor/functions/netconf-executor/pom.xml b/ms/blueprintsprocessor/functions/netconf-executor/pom.xml index a46e7433d..ca5423432 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/netconf-executor/pom.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - ~ Copyright © 2017-2018 AT&T Intellectual Property. + ~ Copyright © 2017-2019 AT&T, Bell Canada. ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -32,12 +32,6 @@ <artifactId>resource-resolution</artifactId> </dependency> <dependency> - <groupId>org.codehaus.jettison</groupId> - <artifactId>jettison</artifactId> - <version>${jettison.version}</version> - <scope>provided</scope> - </dependency> - <dependency> <groupId>org.apache.sshd</groupId> <artifactId>sshd-core</artifactId> </dependency> diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt index 4cec6a2bf..5e0b4a117 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/NetconfComponentFunction.kt @@ -17,51 +17,48 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor -import com.fasterxml.jackson.databind.JsonNode import kotlinx.coroutines.runBlocking -import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction -import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +@Deprecated("Methods defined as extension function of AbstractComponentFunction") abstract class NetconfComponentFunction : AbstractScriptComponentFunction() { + @Deprecated(" Use resourceResolutionService method directly", + replaceWith = ReplaceWith("resourceResolutionService()", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resourceResolutionService")) open fun resourceResolutionService(): ResourceResolutionService = functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) // Called from python script + @Deprecated(" Use netconfDeviceInfo method directly", + replaceWith = ReplaceWith("netconfDeviceInfo(requirementName)", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.netconfDeviceInfo")) fun initializeNetconfConnection(requirementName: String): NetconfDevice { - val deviceInfo = deviceProperties(requirementName) + val deviceInfo = netconfDeviceInfo(requirementName) return NetconfDevice(deviceInfo) } + @Deprecated(" Use artifactContent method directly", + replaceWith = ReplaceWith("artifactContent(artifactName)", + "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.artifactContent")) fun generateMessage(artifactName: String): String { return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) } + @Deprecated(" Use storedContentFromResolvedArtifact method directly", + replaceWith = ReplaceWith("storedContentFromResolvedArtifact(resolutionKey, artifactName)", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifact")) fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking { resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) } + @Deprecated(" Use contentFromResolvedArtifact method directly", + replaceWith = ReplaceWith("resolveAndGenerateMessage(artifactPrefix)", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resolveAndGenerateMessage")) fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) } - - private fun deviceProperties(requirementName: String): DeviceInfo { - - val blueprintContext = bluePrintRuntimeService.bluePrintContext() - - val requirement = blueprintContext.nodeTemplateRequirement(nodeTemplateName, requirementName) - - val capabilityProperties = bluePrintRuntimeService.resolveNodeTemplateCapabilityProperties(requirement - .node!!, requirement.capability!!) - - return deviceProperties(capabilityProperties) - } - - private fun deviceProperties(capabilityProperty: MutableMap<String, JsonNode>): DeviceInfo { - return JacksonUtils.getInstanceFromMap(capabilityProperty, DeviceInfo::class.java) - } }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ScriptComponentExtensions.kt new file mode 100644 index 000000000..bac211ab2 --- /dev/null +++ b/ms/blueprintsprocessor/functions/netconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/netconf/executor/ScriptComponentExtensions.kt @@ -0,0 +1,53 @@ +/* + * Copyright © 2019 IBM. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor + +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor.api.DeviceInfo +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionService +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils + +/** + * Register the Netconf module exposed dependency + */ +fun BluePrintDependencyService.netconfClientService(): ResourceResolutionService = + instance(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) + + +fun AbstractComponentFunction.netconfDevice(requirementName: String): NetconfDevice { + val deviceInfo = netconfDeviceInfo(requirementName) + return NetconfDevice(deviceInfo) +} + +fun AbstractComponentFunction.netconfDeviceInfo(requirementName: String): DeviceInfo { + + val blueprintContext = bluePrintRuntimeService.bluePrintContext() + + val requirement = blueprintContext.nodeTemplateRequirement(nodeTemplateName, requirementName) + + val capabilityProperties = bluePrintRuntimeService.resolveNodeTemplateCapabilityProperties(requirement + .node!!, requirement.capability!!) + + return netconfDeviceInfo(capabilityProperties) +} + +private fun AbstractComponentFunction.netconfDeviceInfo(capabilityProperty: MutableMap<String, JsonNode>): DeviceInfo { + return JacksonUtils.getInstanceFromMap(capabilityProperty, DeviceInfo::class.java) +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt index 2de22424e..c45fb881f 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt @@ -16,6 +16,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor +import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.* import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceConstant @@ -75,8 +76,19 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic val dynamicProperties = getOptionalOperationInput(INPUT_DYNAMIC_PROPERTIES) val packages = getOptionalOperationInput(INPUT_PACKAGES)?.returnNullIfMissing() - val args = getOptionalOperationInput(INPUT_ARGUMENT_PROPERTIES)?.returnNullIfMissing() - ?.rootFieldsToMap()?.toSortedMap()?.values?.map { it.textValue() }?.joinToString(" ") + val argsNode = getOptionalOperationInput(INPUT_ARGUMENT_PROPERTIES)?.returnNullIfMissing() + + // This prevents unescaping values, as well as quoting the each parameter, in order to allow for spaces in values + var args = "" + argsNode?.fields()?.forEach { + if (it.value.isValueNode) { + args = "$args ${it.value}" + } else { + it.value.fields().forEach { item -> + args = "$args ${item.value}" + } + } + } val command = getOperationInput(INPUT_COMMAND).asText() var scriptCommand = command.replace(pythonScript.name, pythonScript.absolutePath) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ScriptComponentExtensions.kt new file mode 100644 index 000000000..ab01b15b7 --- /dev/null +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ScriptComponentExtensions.kt @@ -0,0 +1,57 @@ +/* + * Copyright © 2019 IBM. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution + +import kotlinx.coroutines.runBlocking +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService + + +/** + * Register the Resolution module exposed dependency + */ +fun BluePrintDependencyService.resourceResolutionService(): ResourceResolutionService = + instance(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) + + +suspend fun AbstractComponentFunction.storedContentFromResolvedArtifactNB(resolutionKey: String, + artifactName: String): String { + return BluePrintDependencyService.resourceResolutionService() + .resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) +} + +/** + * Return resolved and mashed artifact content for artifact prefix [artifactPrefix] + */ +suspend fun AbstractComponentFunction.contentFromResolvedArtifactNB(artifactPrefix: String): String { + return BluePrintDependencyService.resourceResolutionService() + .resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) +} + + +/** + * Blocking Methods called from Jython Scripts + */ + +fun AbstractComponentFunction.storedContentFromResolvedArtifact(resolutionKey: String, artifactName: String) + : String = runBlocking { + storedContentFromResolvedArtifactNB(resolutionKey, artifactName) +} + +fun AbstractComponentFunction.contentFromResolvedArtifact(artifactPrefix: String): String = runBlocking { + contentFromResolvedArtifactNB(artifactPrefix) +} diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt index b2064cb54..ede833cfb 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfComponentFunction.kt @@ -25,28 +25,42 @@ import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPrope import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractScriptComponentFunction - +@Deprecated("Methods defined as extension function of AbstractComponentFunction") abstract class RestconfComponentFunction : AbstractScriptComponentFunction() { + @Deprecated("Defined in AbstractScriptComponentFunction extension class") open fun bluePrintRestLibPropertyService(): BluePrintRestLibPropertyService = functionDependencyInstanceAsType(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY) + @Deprecated(" Use resourceResolutionService method directly", + replaceWith = ReplaceWith("resourceResolutionService()", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resourceResolutionService")) open fun resourceResolutionService(): ResourceResolutionService = functionDependencyInstanceAsType(ResourceResolutionConstants.SERVICE_RESOURCE_RESOLUTION) + @Deprecated("Defined in AbstractScriptComponentFunction extension class") fun restClientService(selector: String): BlueprintWebClientService { return bluePrintRestLibPropertyService().blueprintWebClientService(selector) } + @Deprecated(" Use storedContentFromResolvedArtifact method directly", + replaceWith = ReplaceWith("storedContentFromResolvedArtifact(resolutionKey, artifactName)", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.storedContentFromResolvedArtifact")) fun resolveFromDatabase(resolutionKey: String, artifactName: String): String = runBlocking { resourceResolutionService().resolveFromDatabase(bluePrintRuntimeService, artifactName, resolutionKey) } + @Deprecated(" Use artifactContent method directly", + replaceWith = ReplaceWith("artifactContent(artifactName)", + "org.onap.ccsdk.cds.blueprintsprocessor.services.execution.artifactContent")) fun generateMessage(artifactName: String): String { return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) } + @Deprecated(" Use contentFromResolvedArtifact method directly", + replaceWith = ReplaceWith("resolveAndGenerateMessage(artifactPrefix)", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.resolveAndGenerateMessage")) fun resolveAndGenerateMessage(artifactPrefix: String): String = runBlocking { resourceResolutionService().resolveResources(bluePrintRuntimeService, nodeTemplateName, artifactPrefix, mapOf()) diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ScriptComponentExtensions.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ScriptComponentExtensions.kt new file mode 100644 index 000000000..9fc685e19 --- /dev/null +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/ScriptComponentExtensions.kt @@ -0,0 +1,36 @@ +/* + * Copyright © 2019 IBM. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor + +/** + * Register the Restconf module exposed dependency + */ + + +/** + * Generic Mount function + */ + + +/** + * Generic Configure function + */ + + +/** + * Generic Unmount function + */
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt index 19e482aab..efefe0290 100644 --- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt @@ -16,7 +16,9 @@ package org.onap.ccsdk.cds.blueprintsprocessor.db +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintProperties +import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.BluePrintDBLibPropertySevice import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan @@ -34,8 +36,18 @@ open class BluePrintDBLibConfiguration(private var bluePrintProperties: BluePrin } } +/** + * Exposed Dependency Service by this SSH Lib Module + */ +//TODO("right now not wired with name ") +fun BluePrintDependencyService.dbLibPropertyService(): BluePrintDBLibPropertySevice = + instance(DBLibConstants.SERVICE_BLUEPRINT_DB_LIB_PROPERTY) + + class DBLibConstants { companion object { + //TODO("right now not wired with name ") + const val SERVICE_BLUEPRINT_DB_LIB_PROPERTY = "blueprint-db-lib-property-service" const val PREFIX_DB_PRIMARY: String = "blueprintsprocessor.db.primary" //list of database diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt index 52ac346db..008e92437 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt @@ -16,6 +16,7 @@ package org.onap.ccsdk.cds.blueprintsprocessor.message.service +import org.apache.commons.lang.builder.ToStringBuilder import org.apache.kafka.clients.producer.ProducerConfig.* import org.apache.kafka.common.serialization.StringSerializer import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageProducerProperties @@ -27,7 +28,6 @@ import org.springframework.kafka.core.ProducerFactory import org.springframework.kafka.support.SendResult import org.springframework.util.concurrent.ListenableFutureCallback - class KafkaBasicAuthMessageProducerService( private val messageProducerProperties: KafkaBasicAuthMessageProducerProperties) : BlueprintMessageProducerService { @@ -64,9 +64,8 @@ class KafkaBasicAuthMessageProducerService( return true } - private fun producerFactory(additionalConfig: Map<String, Any>? = null): ProducerFactory<String, Any> { - log.info("Client Properties : $messageProducerProperties") + log.info("Client Properties : ${ToStringBuilder.reflectionToString(messageProducerProperties)}") val configProps = hashMapOf<String, Any>() configProps[BOOTSTRAP_SERVERS_CONFIG] = messageProducerProperties.bootstrapServers configProps[KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/BluePrintCoreConfiguration.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/BluePrintCoreConfiguration.kt index 5f1ae7d37..1cb66b8ab 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/BluePrintCoreConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/BluePrintCoreConfiguration.kt @@ -17,16 +17,19 @@ package org.onap.ccsdk.cds.blueprintsprocessor.core import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintPathConfiguration +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService +import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.context.properties.bind.Bindable import org.springframework.boot.context.properties.bind.Binder import org.springframework.boot.context.properties.source.ConfigurationPropertySources +import org.springframework.context.ApplicationContext +import org.springframework.context.ApplicationContextAware import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration import org.springframework.core.env.Environment import org.springframework.stereotype.Service - @Configuration open class BluePrintCoreConfiguration(private val bluePrintProperties: BlueprintProcessorProperties) { @@ -59,4 +62,17 @@ open class BlueprintProcessorProperties(private var bluePrintPropertyBinder: Bin fun <T> propertyBeanType(prefix: String, type: Class<T>): T { return bluePrintPropertyBinder.bind(prefix, Bindable.of(type)).get() } +} + +@Configuration +// Add Conditional property , If we try to manage on Application level +open class BlueprintDependencyConfiguration : ApplicationContextAware { + + private val log = LoggerFactory.getLogger(BlueprintDependencyConfiguration::class.java)!! + + override fun setApplicationContext(applicationContext: ApplicationContext) { + BluePrintDependencyService.inject(applicationContext) + log.info("Dependency Management module created...") + } + }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt index fa4ff231d..25d1de881 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/BluePrintRestLibConfiguration.kt @@ -18,6 +18,10 @@ package org.onap.ccsdk.cds.blueprintsprocessor.rest +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService +import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration @@ -27,6 +31,22 @@ import org.springframework.context.annotation.Configuration @EnableConfigurationProperties open class BluePrintRestLibConfiguration +/** + * Exposed Dependency Service by this Rest Lib Module + */ +fun BluePrintDependencyService.restLibPropertyService(): BluePrintRestLibPropertyService = + instance(RestLibConstants.SERVICE_BLUEPRINT_REST_LIB_PROPERTY) + + +fun BluePrintDependencyService.restClientService(selector: String): BlueprintWebClientService { + return restLibPropertyService().blueprintWebClientService(selector) +} + + +fun BluePrintDependencyService.restClientService(jsonNode: JsonNode): BlueprintWebClientService { + return restLibPropertyService().blueprintWebClientService(jsonNode) +} + class RestLibConstants { companion object { diff --git a/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/BluePrintSshLibConfiguration.kt b/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/BluePrintSshLibConfiguration.kt index 48e451f03..3c625a6d3 100644 --- a/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/BluePrintSshLibConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/ssh-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/ssh/BluePrintSshLibConfiguration.kt @@ -16,6 +16,10 @@ package org.onap.ccsdk.cds.blueprintsprocessor.ssh +import com.fasterxml.jackson.databind.JsonNode +import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BluePrintSshLibPropertyService +import org.onap.ccsdk.cds.blueprintsprocessor.ssh.service.BlueprintSshClientService +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration @@ -25,6 +29,21 @@ import org.springframework.context.annotation.Configuration @EnableConfigurationProperties open class BluePrintSshLibConfiguration +/** + * Exposed Dependency Service by this SSH Lib Module + */ +fun BluePrintDependencyService.sshLibPropertyService(): BluePrintSshLibPropertyService = + instance(SshLibConstants.SERVICE_BLUEPRINT_SSH_LIB_PROPERTY) + + +fun BluePrintDependencyService.sshClientService(selector: String): BlueprintSshClientService = + sshLibPropertyService().blueprintSshClientService(selector) + + +fun BluePrintDependencyService.sshClientService(jsonNode: JsonNode): BlueprintSshClientService = + sshLibPropertyService().blueprintSshClientService(jsonNode) + + class SshLibConstants { companion object { const val SERVICE_BLUEPRINT_SSH_LIB_PROPERTY = "blueprint-ssh-lib-property-service" diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml index 340f2c618..89ad720f6 100755 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml @@ -42,6 +42,7 @@ <artifactId>proto-definition</artifactId> <version>${project.version}</version> </dependency> + <dependency> <groupId>org.onap.ccsdk.cds.controllerblueprints</groupId> <artifactId>blueprint-core</artifactId> @@ -59,6 +60,30 @@ <artifactId>h2</artifactId> <scope>test</scope> </dependency> + + <!-- For Message libraries --> + <dependency> + <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> + <artifactId>message-lib</artifactId> + </dependency> + + <!-- For spring-kafka --> + <dependency> + <groupId>org.springframework.kafka</groupId> + <artifactId>spring-kafka</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.kafka</groupId> + <artifactId>spring-kafka-test</artifactId> + <scope>test</scope> + </dependency> + + <!-- Apache Kafka --> + <dependency> + <groupId>org.apache.kafka</groupId> + <artifactId>kafka_2.11</artifactId> + <version>${kafka.version}</version> + </dependency> </dependencies> </project> diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt new file mode 100644 index 000000000..a04a79921 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingConfig.kt @@ -0,0 +1,47 @@ +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import org.apache.kafka.clients.CommonClientConfigs +import org.apache.kafka.clients.consumer.ConsumerConfig +import org.apache.kafka.common.serialization.StringDeserializer +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.kafka.annotation.EnableKafka +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory +import org.springframework.kafka.core.ConsumerFactory +import org.springframework.kafka.core.DefaultKafkaConsumerFactory +import org.springframework.kafka.support.serializer.JsonDeserializer + +@Configuration +open class MessagingConfig { + + @Value("\${blueprintsprocessor.messageclient.self-service-api.groupId}") + lateinit var groupId: String + + @Value("\${blueprintsprocessor.messageclient.self-service-api.bootstrapServers}") + lateinit var bootstrapServers: String + + open fun consumerFactory(): ConsumerFactory<String, ExecutionServiceInput>? { + val configProperties = hashMapOf<String, Any>() + configProperties[CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers + configProperties[ConsumerConfig.GROUP_ID_CONFIG] = groupId + configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java.name + configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.java.name + configProperties.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest") + + return DefaultKafkaConsumerFactory(configProperties, StringDeserializer(), JsonDeserializer(ExecutionServiceInput::class.java)) + } + + /** + * Creation of a Kafka MessageListener Container + * + * @return KafkaListener instance. + */ + @Bean + open fun kafkaListenerContainerFactory(): ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput> { + val factory = ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput>() + factory.consumerFactory = consumerFactory() + return factory + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt new file mode 100644 index 000000000..1d219a83e --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/MessagingController.kt @@ -0,0 +1,74 @@ +/* + * Copyright © 2019 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import kotlinx.coroutines.async +import kotlinx.coroutines.runBlocking +import org.apache.commons.lang3.builder.ToStringBuilder +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.kafka.annotation.KafkaListener +import org.springframework.stereotype.Service + +@ConditionalOnProperty(name = ["blueprintsprocessor.messageclient.self-service-api.kafkaEnable"], havingValue = "true") +@Service +open class MessagingController(private val propertyService: BluePrintMessageLibPropertyService, + private val executionServiceHandler: ExecutionServiceHandler) { + + private val log = LoggerFactory.getLogger(MessagingController::class.java)!! + + companion object { + // TODO PREFIX should be retrieved from model or from request. + const val PREFIX = "self-service-api" + const val EXECUTION_STATUS = 200 + } + + @KafkaListener(topics = ["\${blueprintsprocessor.messageclient.self-service-api.consumerTopic}"]) + open fun receive(input: ExecutionServiceInput) { + + log.info("Successfully received a message: {}", ToStringBuilder.reflectionToString(input)) + + runBlocking { + log.info("Successfully received a message: {}", ToStringBuilder.reflectionToString(input)) + + // Process the message. + async { + processMessage(input) + } + } + } + + private suspend fun processMessage(executionServiceInput: ExecutionServiceInput) { + + val executionServiceOutput = executionServiceHandler.doProcess(executionServiceInput) + + if (executionServiceOutput.status.code == EXECUTION_STATUS) { + val bluePrintMessageClientService = propertyService + .blueprintMessageClientService(PREFIX) + + val payload = executionServiceOutput.payload + + log.info("The payload to publish is {}", payload) + + bluePrintMessageClientService.sendMessage(payload) + } + else { + log.error("Fail to process the given event due to {}", executionServiceOutput.status.errorMessage) + } + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandlerTest.kt index fd764d78f..e084c60cf 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintManagementGRPCHandlerTest.kt @@ -23,6 +23,8 @@ import io.grpc.testing.GrpcServerRule import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.messaginglib.MessagingControllerTest +import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.messaginglib.ProducerConfiguration import org.onap.ccsdk.cds.controllerblueprints.common.api.CommonHeader import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile @@ -33,6 +35,7 @@ import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.FilterType import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner @@ -44,7 +47,9 @@ import kotlin.test.assertTrue @RunWith(SpringRunner::class) @EnableAutoConfiguration @DirtiesContext -@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"], + excludeFilters = [ComponentScan.Filter(value = [MessagingConfig::class, MessagingController::class, ProducerConfiguration::class, + MessagingControllerTest.ConsumerConfiguration::class, MessagingControllerTest::class], type = FilterType.ASSIGNABLE_TYPE)]) @TestPropertySource(locations = ["classpath:application-test.properties"]) class BluePrintManagementGRPCHandlerTest { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt index f8b972e64..5072b3c6a 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt @@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.FilterType import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner @@ -45,7 +46,8 @@ import kotlin.test.BeforeTest @RunWith(SpringRunner::class) @DirtiesContext @EnableAutoConfiguration -@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"], + excludeFilters =arrayOf(ComponentScan.Filter(value = [(MessagingController::class)], type = FilterType.ASSIGNABLE_TYPE))) @TestPropertySource(locations = ["classpath:application-test.properties"]) class BluePrintProcessingGRPCHandlerTest { private val log = LoggerFactory.getLogger(BluePrintProcessingGRPCHandlerTest::class.java) diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt index 9cbd898dc..65b41262b 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt @@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.security.SecurityProperties import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.FilterType import org.springframework.core.io.ByteArrayResource import org.springframework.http.client.MultipartBodyBuilder import org.springframework.test.context.ContextConfiguration @@ -49,7 +50,8 @@ import kotlin.test.assertTrue @RunWith(SpringRunner::class) @WebFluxTest @ContextConfiguration(classes = [ExecutionServiceHandler::class, BluePrintCoreConfiguration::class, BluePrintCatalogService::class, SecurityProperties::class]) -@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"], + excludeFilters =arrayOf(ComponentScan.Filter(value = [(MessagingController::class)], type = FilterType.ASSIGNABLE_TYPE))) @TestPropertySource(locations = ["classpath:application-test.properties"]) class ExecutionServiceHandlerTest { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt new file mode 100644 index 000000000..f7459f522 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/MessagingControllerTest.kt @@ -0,0 +1,211 @@ +/* + * Copyright © 2019 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.messaginglib + +import com.fasterxml.jackson.databind.node.ObjectNode +import kotlinx.coroutines.reactive.awaitSingle +import kotlinx.coroutines.runBlocking +import org.apache.commons.lang.builder.ToStringBuilder +import org.apache.kafka.clients.CommonClientConfigs +import org.apache.kafka.clients.consumer.ConsumerConfig +import org.apache.kafka.common.serialization.StringDeserializer +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData +import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.MessagingController +import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.boot.autoconfigure.security.SecurityProperties +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration +import org.springframework.core.io.ByteArrayResource +import org.springframework.http.client.MultipartBodyBuilder +import org.springframework.kafka.annotation.EnableKafka +import org.springframework.kafka.annotation.KafkaListener +import org.springframework.kafka.annotation.PartitionOffset +import org.springframework.kafka.annotation.TopicPartition +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory +import org.springframework.kafka.core.ConsumerFactory +import org.springframework.kafka.core.DefaultKafkaConsumerFactory +import org.springframework.kafka.core.KafkaTemplate +import org.springframework.kafka.support.serializer.JsonDeserializer +import org.springframework.kafka.test.context.EmbeddedKafka +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner +import org.springframework.test.web.reactive.server.WebTestClient +import org.springframework.test.web.reactive.server.returnResult +import org.springframework.web.reactive.function.BodyInserters +import java.io.File +import java.nio.file.Files +import java.nio.file.Paths +import kotlin.test.assertNotNull + +@RunWith(SpringRunner::class) +@EnableAutoConfiguration +@ContextConfiguration(classes = [MessagingControllerTest::class, SecurityProperties::class]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@TestPropertySource(locations = ["classpath:application-test.properties"]) +@DirtiesContext +@EmbeddedKafka(ports = [9092]) +@WebFluxTest +class MessagingControllerTest { + + private val log = LoggerFactory.getLogger(MessagingControllerTest::class.java)!! + + @Autowired + lateinit var controller: MessagingController + + @Value("\${blueprintsprocessor.messageclient.self-service-api.consumerTopic}") + lateinit var topicUsedForConsumer: String + + @Autowired + lateinit var kt: KafkaTemplate<String, ExecutionServiceInput> + + @Autowired + lateinit var webTestClient: WebTestClient + + var receivedEvent: String? = null + + @Before + fun setup() { + deleteDir("target", "blueprints") + uploadBluePrint() + } + + @After + fun clean() { + deleteDir("target", "blueprints") + } + + @Test + fun testReceive() { + val samplePayload = "{\n" + + " \"resource-assignment-request\": {\n" + + " \"artifact-name\": [\"hostname\"],\n" + + " \"store-result\": true,\n" + + " \"resource-assignment-properties\" : {\n" + + " \"hostname\": \"demo123\"\n" + + " }\n" + + " }\n" + + " }" + + kt.defaultTopic = topicUsedForConsumer + + val input = ExecutionServiceInput().apply { + commonHeader = CommonHeader().apply { + originatorId = "1" + requestId = "1234" + subRequestId = "1234-1234" + } + + actionIdentifiers = ActionIdentifiers().apply { + blueprintName = "golden" + blueprintVersion = "1.0.0" + actionName = "resource-assignment" + mode = "sync" + } + + stepData = StepData().apply { + name = "resource-assignment" + } + + payload = JacksonUtils.jsonNode(samplePayload) as ObjectNode + } + + kt.sendDefault(input) + log.info("test-sender sent message='{}'", ToStringBuilder.reflectionToString(input)) + + Thread.sleep(1000) + } + + @KafkaListener(topicPartitions = [TopicPartition(topic = "\${blueprintsprocessor.messageclient.self-service-api.topic}", partitionOffsets = [PartitionOffset(partition = "0", initialOffset = "0")])]) + fun receivedEventFromBluePrintProducer(event: ExecutionServiceInput) { + assertNotNull(event) + } + + private fun uploadBluePrint() { + runBlocking { + val body = MultipartBodyBuilder().apply { + part("file", object : ByteArrayResource(Files.readAllBytes(loadCbaArchive().toPath())) { + override fun getFilename(): String { + return "test-cba.zip" + } + }) + }.build() + + webTestClient + .post() + .uri("/api/v1/execution-service/upload") + .body(BodyInserters.fromMultipartData(body)) + .exchange() + .expectStatus().isOk + .returnResult<String>() + .responseBody + .awaitSingle() + } + } + + private fun loadCbaArchive():File { + return Paths.get("./src/test/resources/cba-for-kafka-integration.zip").toFile() + } + + @Configuration + @EnableKafka + open class ConsumerConfiguration { + + @Value("\${blueprintsprocessor.messageclient.self-service-api.bootstrapServers}") + lateinit var bootstrapServers: String + + @Value("\${blueprintsprocessor.messageclient.self-service-api.groupId}") + lateinit var groupId:String + + @Bean + open fun consumerFactory2(): ConsumerFactory<String, ExecutionServiceInput>? { + val configProperties = hashMapOf<String, Any>() + configProperties[CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers + configProperties[ConsumerConfig.GROUP_ID_CONFIG] = groupId + configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java.name + configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.java.name + configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = "earliest" + configProperties[ConsumerConfig.MAX_POLL_INTERVAL_MS_CONFIG] = 1000 + + return DefaultKafkaConsumerFactory(configProperties, StringDeserializer(), + JsonDeserializer(ExecutionServiceInput::class.java)) + } + + @Bean + open fun listenerFactory(): ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput> { + val factory = ConcurrentKafkaListenerContainerFactory<String, ExecutionServiceInput>() + factory.consumerFactory = consumerFactory2() + return factory + } + } +} + + diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt new file mode 100644 index 000000000..dc1f38a63 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/messaginglib/ProducerConfiguration.kt @@ -0,0 +1,48 @@ +/* + * Copyright © 2019 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.messaginglib + +import org.apache.kafka.clients.producer.ProducerConfig +import org.apache.kafka.common.serialization.StringSerializer +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.kafka.annotation.EnableKafka +import org.springframework.kafka.core.DefaultKafkaProducerFactory +import org.springframework.kafka.core.KafkaTemplate +import org.springframework.kafka.core.ProducerFactory +import org.springframework.kafka.support.serializer.JsonSerializer + +@Configuration +open class ProducerConfiguration { + + @Value("\${blueprintsprocessor.messageclient.self-service-api.bootstrapServers}") + lateinit var bootstrapServers: String + + open fun kpf(): ProducerFactory<String, ExecutionServiceInput> { + val configs = HashMap<String, Any>() + configs[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers + configs[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java + configs[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = JsonSerializer::class.java + return DefaultKafkaProducerFactory(configs) + } + + @Bean + open fun kt(): KafkaTemplate<String, ExecutionServiceInput> { + return KafkaTemplate<String, ExecutionServiceInput>(kpf()) + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties index 6705523df..d532b1582 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties @@ -31,3 +31,12 @@ blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive # Python executor blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints + +# Kafka-message-lib Configuration +blueprintsprocessor.messageclient.self-service-api.kafkaEnable=true +blueprintsprocessor.messageclient.self-service-api.topic=producer.t +blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth +blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t +blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id +blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip Binary files differnew file mode 100644 index 000000000..23070380c --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/cba-for-kafka-integration.zip diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt index 23588d25a..408bb58ed 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt @@ -27,6 +27,7 @@ import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.core.* import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BlueprintFunctionNode import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService import org.slf4j.LoggerFactory /** @@ -146,4 +147,19 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic bluePrintRuntimeService.getBluePrintError().addError(error) } + fun artifactContent(artifactName: String): String { + return bluePrintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, artifactName) + } + + suspend fun mashTemplateNData(artifactName: String, json: String): String { + val content = artifactContent(artifactName) + return BluePrintVelocityTemplateService.generateContent(content, json) + } + + suspend fun readLinesFromArtifact(artifactName: String): List<String> { + val artifactDefinition = bluePrintRuntimeService.resolveNodeTemplateArtifactDefinition(nodeTemplateName, artifactName) + val file = normalizedFile(bluePrintRuntimeService.bluePrintContext().rootPath, artifactDefinition.file) + return file.readNBLines() + } + }
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractScriptComponentFunction.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractScriptComponentFunction.kt index 27cde8a49..f17085ef1 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractScriptComponentFunction.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractScriptComponentFunction.kt @@ -36,11 +36,13 @@ abstract class AbstractScriptComponentFunction : AbstractComponentFunction() { /** * Store Dynamic Script Dependency Instances, Objects present inside won't be persisted or state maintained. */ + @Deprecated("Dependencies will be resolved dynamically") var functionDependencyInstances: MutableMap<String, Any> = hashMapOf() /** * This will be called from the scripts to serve instance from runtime to scripts. */ + @Deprecated("Dependencies will be resolved dynamically") open fun <T> functionDependencyInstanceAsType(name: String): T { return functionDependencyInstances[name] as? T ?: throw BluePrintProcessorException("couldn't get script property instance ($name)") diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt new file mode 100644 index 000000000..056f7e96d --- /dev/null +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ComponentScriptExecutor.kt @@ -0,0 +1,108 @@ +/* + * Copyright © 2019 IBM. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.data.NodeType +import org.onap.ccsdk.cds.controllerblueprints.core.dsl.nodeType +import org.onap.ccsdk.cds.controllerblueprints.core.getAsString +import org.springframework.beans.factory.config.ConfigurableBeanFactory +import org.springframework.context.annotation.Scope +import org.springframework.stereotype.Component + +/** + * This is generic Script Component Executor function + * @author Brinda Santh + */ +@Component("component-script-executor") +@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +open class ComponentScriptExecutor(private var componentFunctionScriptingService: ComponentFunctionScriptingService) + : AbstractComponentFunction() { + + companion object { + const val SCRIPT_TYPE = "script-type" + const val SCRIPT_CLASS_REFERENCE = "script-class-reference" + const val DYNAMIC_PROPERTIES = "dynamic-properties" + const val RESPONSE_DATA = "response-data" + const val STATUS = "status" + } + + lateinit var scriptComponentFunction: AbstractScriptComponentFunction + + override suspend fun processNB(executionRequest: ExecutionServiceInput) { + + val scriptType = operationInputs.getAsString(SCRIPT_TYPE) + val scriptClassReference = operationInputs.getAsString(SCRIPT_CLASS_REFERENCE) + + val scriptDependencies: MutableList<String> = arrayListOf() + populateScriptDependencies(scriptDependencies) + + scriptComponentFunction = componentFunctionScriptingService.scriptInstance(this, scriptType, + scriptClassReference, scriptDependencies) + + // Handles both script processing and error handling + scriptComponentFunction.executeScript(executionServiceInput) + } + + override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { + bluePrintRuntimeService.getBluePrintError() + .addError("Failed in ComponentCliExecutor : ${runtimeException.message}") + + } + + open fun populateScriptDependencies(scriptDependencies: MutableList<String>) { + /** Place holder for Child to add extra dependencies */ + } +} + +/** Component Extensions **/ + +fun BluePrintTypes.componentScriptExecutor(): NodeType { + return nodeType(id = "component-script-executor", version = BluePrintConstants.DEFAULT_VERSION_NUMBER, + derivedFrom = BluePrintConstants.MODEL_TYPE_NODES_ROOT, + description = "Generic Script Component Executor") { + attribute(ComponentScriptExecutor.RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false) + attribute(ComponentScriptExecutor.STATUS, BluePrintConstants.DATA_TYPE_STRING, true) + + operation("ComponentScriptExecutor", "ComponentScriptExecutor Operation") { + inputs { + property(ComponentScriptExecutor.SCRIPT_TYPE, BluePrintConstants.DATA_TYPE_STRING, true, + "Script Type") { + defaultValue(BluePrintConstants.SCRIPT_INTERNAL) + constrains { + validValues(listOf(BluePrintConstants.SCRIPT_INTERNAL.asJsonPrimitive(), + BluePrintConstants.SCRIPT_JYTHON.asJsonPrimitive(), + BluePrintConstants.SCRIPT_KOTLIN.asJsonPrimitive())) + } + } + property(ComponentScriptExecutor.SCRIPT_CLASS_REFERENCE, BluePrintConstants.DATA_TYPE_STRING, + true, "Kotlin Script class name or jython script name.") + property(ComponentScriptExecutor.DYNAMIC_PROPERTIES, BluePrintConstants.DATA_TYPE_JSON, false, + "Dynamic Json Content or DSL Json reference.") + } + outputs { + property(ComponentScriptExecutor.RESPONSE_DATA, BluePrintConstants.DATA_TYPE_JSON, false, + "Output Response") + property(ComponentScriptExecutor.STATUS, BluePrintConstants.DATA_TYPE_STRING, true, + "Status of the Component Execution ( success or failure )") + } + } + } +}
\ No newline at end of file diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt index b404fbed6..224319c24 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/scripts/AbstractComponentFunctionTest.kt @@ -34,7 +34,9 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInpu import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractComponentFunction import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ComponentFunctionScriptingService +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.componentScriptExecutor import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintTypes import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext @@ -53,7 +55,7 @@ import kotlin.test.assertNotNull */ @RunWith(SpringRunner::class) @ContextConfiguration(classes = [ComponentFunctionScriptingService::class, - BluePrintScriptsServiceImpl::class,PythonExecutorProperty::class, + BluePrintScriptsServiceImpl::class, PythonExecutorProperty::class, BlueprintJythonService::class]) class AbstractComponentFunctionTest { @@ -183,5 +185,10 @@ class AbstractComponentFunctionTest { return executionServiceInput } + @Test + fun testComponentScriptExecutorNodeType() { + val componentScriptExecutor = BluePrintTypes.componentScriptExecutor() + assertNotNull(componentScriptExecutor.interfaces, "failed to get interface operations") + } } diff --git a/ms/blueprintsprocessor/parent/pom.xml b/ms/blueprintsprocessor/parent/pom.xml index 82c2e6153..5e6502fcb 100755 --- a/ms/blueprintsprocessor/parent/pom.xml +++ b/ms/blueprintsprocessor/parent/pom.xml @@ -1,8 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - ~ Copyright © 2017-2018 AT&T Intellectual Property. - ~ - ~ Modifications Copyright © 2018 - 2019 IBM, Bell Canada + ~ Copyright © 2017-2019 AT&T, IBM, Bell Canada. ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. @@ -479,6 +477,13 @@ <scope>test</scope> </dependency> + <!-- message-lib dependency --> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>message-lib</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> </dependencyManagement> diff --git a/ms/command-executor/src/main/python/command_executor_handler.py b/ms/command-executor/src/main/python/command_executor_handler.py index 365c00188..305c83e17 100644 --- a/ms/command-executor/src/main/python/command_executor_handler.py +++ b/ms/command-executor/src/main/python/command_executor_handler.py @@ -163,9 +163,16 @@ class CommandExecutorHandler(): def activate_venv(self): self.logger.info("{} - Activate Python Virtual Environment".format(self.blueprint_id)) + # Fix: The python generated activate_this.py script concatenates the env bin dir to PATH on every call + # eventually this process PATH variable was so big (128Kb) that no child process could be spawn + # This script will remove all duplicates; while keeping the order of the PATH folders + fixpathenvvar = "os.environ['PATH']=os.pathsep.join(list(dict.fromkeys(os.environ['PATH'].split(':'))))" + path = "%s/bin/activate_this.py" % self.venv_home try: exec (open(path).read(), {'__file__': path}) + exec (fixpathenvvar) + self.logger.info("Running with PATH : {}".format(os.environ['PATH'])) return True except Exception as err: self.logger.info( diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTypeDSLBuilder.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTypeDSLBuilder.kt index 07cc20ebd..0f011948d 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTypeDSLBuilder.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/dsl/BluePrintTypeDSLBuilder.kt @@ -18,6 +18,7 @@ package org.onap.ccsdk.cds.controllerblueprints.core.dsl import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType import org.onap.ccsdk.cds.controllerblueprints.core.data.* @@ -266,16 +267,16 @@ class OperationDefinitionBuilder(private val id: String, class AttributesDefinitionBuilder { private val attributes: MutableMap<String, AttributeDefinition> = hashMapOf() - fun property(id: String, attribute: AttributeDefinition) { + fun attribute(id: String, attribute: AttributeDefinition) { attributes[id] = attribute } - fun property(id: String, type: String?, required: Boolean?, description: String?) { + fun attribute(id: String, type: String?, required: Boolean?, description: String?) { val attribute = AttributeDefinitionBuilder(id, type, required, description).build() attributes[id] = attribute } - fun property(id: String, type: String?, required: Boolean?, description: String?, + fun attribute(id: String, type: String?, required: Boolean?, description: String?, block: AttributeDefinitionBuilder.() -> Unit) { val attribute = AttributeDefinitionBuilder(id, type, required, description).apply(block).build() attributes[id] = attribute @@ -353,7 +354,14 @@ class PropertyDefinitionBuilder(private val id: String, fun entrySchema(entrySchemaType: String, block: EntrySchemaBuilder.() -> Unit) { propertyDefinition.entrySchema = EntrySchemaBuilder(entrySchemaType).apply(block).build() } - // TODO("Constrains") + + fun constrains(block: ConstraintClauseBuilder.() -> Unit) { + propertyDefinition.constraints = ConstraintClauseBuilder().apply(block).build() + } + + fun defaultValue(defaultValue: Any) { + defaultValue(defaultValue.asJsonType()) + } fun defaultValue(defaultValue: JsonNode) { propertyDefinition.defaultValue = defaultValue @@ -372,6 +380,22 @@ class PropertyDefinitionBuilder(private val id: String, } } +class ConstraintClauseBuilder { + private val constraints: MutableList<ConstraintClause> = mutableListOf() + //TODO("Implementation") + + fun validValues(values: List<JsonNode>) { + val constraintClause = ConstraintClause() + constraintClause.validValues = values.toMutableList() + constraints.add(constraintClause) + } + + fun build(): MutableList<ConstraintClause> { + return constraints + } +} + + class EntrySchemaBuilder(private val type: String) { private var entrySchema: EntrySchema = EntrySchema() diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintDependencyService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintDependencyService.kt new file mode 100644 index 000000000..fdaf25c15 --- /dev/null +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/service/BluePrintDependencyService.kt @@ -0,0 +1,47 @@ +/* + * Copyright © 2019 IBM. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.controllerblueprints.core.service + +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.springframework.context.ApplicationContext + +/** + * Generic Bluepring Dependency Service, which will be used mainly in scripts. + * This will be initialised only once during the Application startup. + * Function modules, shall add their own dependency function names as an extension function. + * + * @author Brinda Santh + */ + +object BluePrintDependencyService { + + lateinit var applicationContext: ApplicationContext + + fun inject(applicationContext: ApplicationContext) { + BluePrintDependencyService.applicationContext = applicationContext + } + + inline fun <reified T> instance(name: String): T { + return applicationContext.getBean(name) as? T + ?: throw BluePrintProcessorException("failed to get instance($name)") + } + + inline fun <reified T> instance(type: Class<T>): T { + return applicationContext.getBean(type) + ?: throw BluePrintProcessorException("failed to get instance($type)") + } +}
\ No newline at end of file @@ -15,7 +15,8 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.onap.ccsdk.parent</groupId> @@ -35,8 +36,8 @@ limitations under the License. <description>CCSDK Controller Design Studio</description> <modules> - <module>cds-ui</module> <module>components</module> + <module>cds-ui</module> <module>ms</module> </modules> @@ -54,12 +55,7 @@ limitations under the License. <sonar.tests>src/test</sonar.tests> <!--Only include java and kt files to the scan--> <sonar.inclusions>**/*.java,**/*.kt</sonar.inclusions> - <!--Specify path to load jacoco XLM report, as Sonar can't load Kotlin coverage from binary report. - Note: coverage for now is invalid and is failing to load because of: - "Cannot import coverage information for file '{file}', coverage data is invalid." - see https://github.com/jacoco/jacoco/issues/763 - That issue has been fixed in 0.8.3 , so we override the default ONAP - version here to pick up that fix --> + <!--Specify path to load jacoco XLM report, as Sonar can't load Kotlin coverage from binary report--> <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml </sonar.coverage.jacoco.xmlReportPaths> <jacoco.version>0.8.3</jacoco.version> |