From 35481027b3fdf251a3b520ab5b1ae89c7d2d0e34 Mon Sep 17 00:00:00 2001 From: Kavitha P Date: Wed, 25 Aug 2021 16:12:18 +0530 Subject: CCSDK-3434 CBA workflow status store Change-Id: Iaeac6fa534c569bbc152e6c8a78c2dd23b6c4b1a Signed-off-by: Kavitha P Issue-ID: CCSDK-3434 --- .../src/main/resources/application-dev.properties | 4 + .../src/main/resources/application.properties | 4 + .../src/main/resources/sql/schema-local.sql | 24 +- .../application/src/main/resources/sql/schema.sql | 22 ++ .../src/test/resources/application-test.properties | 4 + .../src/test/resources/application.properties | 4 + .../functions/blueprint-audit-status/pom.xml | 63 +++++ .../workflow/audit/DatabaseStoreAuditConstants.kt | 27 +++ .../workflow/audit/DatabaseStoreAuditService.kt | 243 +++++++++++++++++++ .../workflow/audit/NoStoreAuditService.kt | 118 +++++++++ .../functions/workflow/audit/StoreAuditService.kt | 69 ++++++ .../audit/db/BlueprintAuditStatusRepository.kt | 107 ++++++++ .../audit/db/BlueprintWorkflowAuditStatus.kt | 136 +++++++++++ .../audit/DatabaseStoreAuditServiceTest.kt | 270 +++++++++++++++++++++ .../workflow/audit/NoStoreAuditServiceTest.kt | 81 +++++++ .../workflow/audit/TestDatabaseConfiguration.kt | 62 +++++ .../audit/db/BlueprintAuditStatusRepositoryTest.kt | 0 .../src/test/resources/application-test.properties | 36 +++ .../resources/exec-serv-input/multistep-input.json | 23 ++ .../exec-serv-output/multistep-output.json | 26 ++ ms/blueprintsprocessor/functions/pom.xml | 1 + ms/blueprintsprocessor/modules/inbounds/pom.xml | 1 + .../modules/inbounds/selfservice-api/pom.xml | 6 + .../selfservice/api/ExecutionServiceHandler.kt | 13 +- .../api/ExecutionServiceControllerTest.kt | 4 +- .../selfservice/api/ExecutionServiceHandlerTest.kt | 63 ++++- .../selfservice/api/TestDatabaseConfiguration.kt | 4 +- .../src/test/resources/application-test.properties | 4 + .../modules/inbounds/workflow-api/pom.xml | 56 +++++ .../workflow/api/ErrorHandling.kt | 35 +++ .../workflow/api/WorkflowController.kt | 109 +++++++++ .../workflow/api/WorkflowExceptionHandler.kt | 29 +++ .../workflow/api/ErrorCatalogTestConfiguration.kt | 28 +++ .../workflow/api/TestDatabaseConfiguration.kt | 62 +++++ .../workflow/api/WorkflowControllerTest.kt | 268 ++++++++++++++++++++ .../src/test/resources/application-test.properties | 39 +++ 36 files changed, 2038 insertions(+), 7 deletions(-) create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditConstants.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditService.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditService.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/StoreAuditService.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepository.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintWorkflowAuditStatus.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditServiceTest.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditServiceTest.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/TestDatabaseConfiguration.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepositoryTest.kt create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/application-test.properties create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-input/multistep-input.json create mode 100644 ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-output/multistep-output.json create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorHandling.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowController.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowExceptionHandler.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorCatalogTestConfiguration.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/TestDatabaseConfiguration.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowControllerTest.kt create mode 100644 ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/resources/application-test.properties diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties index e7443434a..e20e2649d 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties @@ -175,3 +175,7 @@ blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit- blueprintprocessor.k8s.plugin.username=test blueprintprocessor.k8s.plugin.password=pass blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/ + +#Workflow store configuration +#workflow Audit request +blueprintsprocessor.workflow.self-service-api.audit.storeEnable=false diff --git a/ms/blueprintsprocessor/application/src/main/resources/application.properties b/ms/blueprintsprocessor/application/src/main/resources/application.properties index 9b48359a1..eef45f052 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application.properties @@ -168,3 +168,7 @@ management.info.git.mode=full blueprintprocessor.k8s.plugin.username=test blueprintprocessor.k8s.plugin.password=pass blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/ + +#Workflow store configuration +#workflow Audit request +blueprintsprocessor.workflow.self-service-api.audit.storeEnable=false diff --git a/ms/blueprintsprocessor/application/src/main/resources/sql/schema-local.sql b/ms/blueprintsprocessor/application/src/main/resources/sql/schema-local.sql index 05df4200a..794a3b42a 100644 --- a/ms/blueprintsprocessor/application/src/main/resources/sql/schema-local.sql +++ b/ms/blueprintsprocessor/application/src/main/resources/sql/schema-local.sql @@ -80,4 +80,26 @@ CREATE TABLE IF NOT EXISTS sdnctl.RESOURCE_DICTIONARY ( updated_by VARCHAR(100) NOT NULL, primary key PK_RESOURCE_DICTIONARY (name), INDEX IX_RESOURCE_DICTIONARY (name) -) ENGINE=InnoDB; \ No newline at end of file +) ENGINE=InnoDB; + +-- ----------------------------------------------------- +-- table BLUEPRINT_WORKFLOW_AUDIT_STATUS +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS sdnctl.BLUEPRINT_WORKFLOW_AUDIT_STATUS ( + workflow_audit_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY, + workflow_task_content longtext NOT NULL, + originator_Id varchar(255) NOT NULL, + request_Id varchar(255) NOT NULL, + subRequest_Id varchar(255) NOT NULL, + workflow_name varchar(255) NOT NULL, + status varchar(255) NULL, + start_time datetime NULL, + end_time datetime NULL, + updated_date datetime NULL, + updated_by varchar(255) NULL, + blueprint_version varchar(255) NOT NULL, + blueprint_name varchar(255) NOT NULL, + request_mode varchar(255) NULL, + workflow_response_content longtext NULL, + blueprint_uuid varchar(255) NULL +) AUTO_INCREMENT = 1000 ENGINE=InnoDB; diff --git a/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql b/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql index 6dcd2af89..851adcf6c 100644 --- a/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql +++ b/ms/blueprintsprocessor/application/src/main/resources/sql/schema.sql @@ -77,3 +77,25 @@ CREATE TABLE IF NOT EXISTS configurator.RESOURCE_DICTIONARY ( primary key PK_RESOURCE_DICTIONARY (name), INDEX IX_RESOURCE_DICTIONARY (name) ) ENGINE=InnoDB; + +-- ----------------------------------------------------- +-- table BLUEPRINT_WORKFLOW_AUDIT_STATUS +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS configurator.BLUEPRINT_WORKFLOW_AUDIT_STATUS ( + workflow_audit_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE PRIMARY KEY, + workflow_task_content longtext NOT NULL, + originator_Id varchar(255) NOT NULL, + request_Id varchar(255) NOT NULL, + subRequest_Id varchar(255) NOT NULL, + workflow_name varchar(255) NOT NULL, + status varchar(255) NULL, + start_time datetime NULL, + end_time datetime NULL, + updated_date datetime NULL, + updated_by varchar(255) NULL, + blueprint_version varchar(255) NOT NULL, + blueprint_name varchar(255) NOT NULL, + request_mode varchar(255) NULL, + workflow_response_content longtext NULL, + blueprint_uuid varchar(255) NULL +) AUTO_INCREMENT = 1000 ENGINE=InnoDB; diff --git a/ms/blueprintsprocessor/application/src/test/resources/application-test.properties b/ms/blueprintsprocessor/application/src/test/resources/application-test.properties index c436b3876..b23cdb284 100644 --- a/ms/blueprintsprocessor/application/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/application/src/test/resources/application-test.properties @@ -71,3 +71,7 @@ cdslistener.healthcheck.mapping-service-name-with-service-link=[SDC Listener ser blueprintprocessor.k8s.plugin.username=test blueprintprocessor.k8s.plugin.password=pass blueprintprocessor.k8s.plugin.url=http://multicloud-k8s:9015/ + +#Workflow store configuration +#workflow Audit request +blueprintsprocessor.workflow.self-service-api.audit.storeEnable=false diff --git a/ms/blueprintsprocessor/application/src/test/resources/application.properties b/ms/blueprintsprocessor/application/src/test/resources/application.properties index c6e957b32..6bac3a3d6 100644 --- a/ms/blueprintsprocessor/application/src/test/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/test/resources/application.properties @@ -98,3 +98,7 @@ blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit- endpoints.user.name=eHbVUbJAj4AG2522cSbrOQ== endpoints.user.password=eHbVUbJAj4AG2522cSbrOQ== + +#Workflow store configuration +#workflow Audit request +blueprintsprocessor.workflow.self-service-api.audit.storeEnable=false diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml b/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml new file mode 100644 index 000000000..ec2e72c61 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/pom.xml @@ -0,0 +1,63 @@ + + + + + 4.0.0 + + + org.onap.ccsdk.cds.blueprintsprocessor + blueprintsprocessor-functions + 1.2.0-SNAPSHOT + + + org.onap.ccsdk.cds.blueprintsprocessor.functions + blueprint-audit-status + jar + + MS Blueprints Processor Functions - Blueprint Audit status + Blueprints Processor Function - Blueprint Audit status + + + + org.onap.ccsdk.cds.blueprintsprocessor.modules + db-lib + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-logging + + + + + com.h2database + h2 + + + org.mariadb.jdbc + mariadb-java-client + + + org.hibernate + hibernate-testing + test + + + diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditConstants.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditConstants.kt new file mode 100644 index 000000000..1ca8d1b30 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditConstants.kt @@ -0,0 +1,27 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +/** + * Contants file + */ +object DatabaseStoreAuditConstants { + + const val WORKFLOW_STATUS_INPROGRESS = "In Progress" + const val WORKFLOW_STATUS_COMPLETED = "Completed" + const val WORKFLOW_STATUS_UPDATEDBY = "CBA" +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditService.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditService.kt new file mode 100644 index 000000000..ecfb269f0 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditService.kt @@ -0,0 +1,243 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +import com.fasterxml.jackson.databind.ObjectMapper +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintAuditStatusRepository +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.utils.controllerDate +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.dao.DataIntegrityViolationException +import org.springframework.stereotype.Service +import java.util.Date + +/** + * Workflow request and response details are persisted to database + */ +@ConditionalOnProperty( + name = ["blueprintsprocessor.workflow.self-service-api.audit.storeEnable"], + havingValue = "true" +) +@Service +class DatabaseStoreAuditService( + private val blueprintAuditStatusRepository: BlueprintAuditStatusRepository +) : StoreAuditService { + + private val log = + LoggerFactory.getLogger(DatabaseStoreAuditService::class.toString()) + + /** + * store the blueprint workflow input details to database + * @param executionServiceInput {@link ExecutionServiceInput} + * @throws {@link BluePrintException} + */ + override suspend fun storeExecutionInput( + executionServiceInput: ExecutionServiceInput + ): Long { + log.info( + "storeExecutionInput called to store the Workflow action " + + "input details " + ) + var storedAuditStatus: BlueprintWorkflowAuditStatus = BlueprintWorkflowAuditStatus() + + storedAuditStatus = write( + 0, executionServiceInput.commonHeader.originatorId, + executionServiceInput.commonHeader.requestId, + executionServiceInput.commonHeader.subRequestId, + executionServiceInput.actionIdentifiers.actionName, + executionServiceInput.actionIdentifiers.blueprintName, + executionServiceInput.actionIdentifiers.blueprintVersion, + executionServiceInput.payload.toString(), + DatabaseStoreAuditConstants.WORKFLOW_STATUS_INPROGRESS, controllerDate(), + controllerDate(), controllerDate(), + DatabaseStoreAuditConstants.WORKFLOW_STATUS_UPDATEDBY, + executionServiceInput.actionIdentifiers.mode, "" + ) + + return storedAuditStatus.id + } + + /** + * store the blueprint workflow output to database + * @param auditStoreId + * @param correlationUUID + * @param executionServiceOutput {@link ExecutionServiceOutput} + * @throws {@link BluePrintException} + */ + override suspend fun storeExecutionOutput( + auditStoreId: Long, + correlationUUID: String, + executionServiceOutput: ExecutionServiceOutput + ) { + log.info( + "storeExecutionOutput called to store the Workflow action " + + "output details correlationUUID $correlationUUID " + + "auditStoreId $auditStoreId" + ) + try { + var storedAuditStatus: BlueprintWorkflowAuditStatus + + storedAuditStatus = + blueprintAuditStatusRepository.findById(auditStoreId) + if (storedAuditStatus == null) { + throw BluePrintException("Record not found exception") + } + storedAuditStatus.endDate = controllerDate() + storedAuditStatus.status = DatabaseStoreAuditConstants.WORKFLOW_STATUS_COMPLETED + storedAuditStatus.updatedDate = controllerDate() + ObjectMapper().writeValueAsString(executionServiceOutput.status) + storedAuditStatus.workflowResponseContent = ObjectMapper() + .writeValueAsString(executionServiceOutput) + + log.info( + "Update the Audit status record Id ${storedAuditStatus.id} " + + "bluePrintName ${storedAuditStatus.blueprintName}" + ) + blueprintAuditStatusRepository.saveAndFlush(storedAuditStatus) + } catch (ex: DataIntegrityViolationException) { + log.error( + "Error writing out BLUEPRINT_WORKFLOW_AUDIT_STATUS result: " + + "bpName:" + + " $auditStoreId" + + "correlationUUID $correlationUUID error: {}", + ex.message + ) + throw BluePrintException("Failed to store resource api result.", ex) + } + } + + /** + * retrive workflow records based on request ID + * @param requestId + * @return list of {@link BlueprintWorkflowAuditStatus} + */ + override suspend fun getWorkflowStatusByRequestId( + requestId: String + ): List { + log.info( + "getWorkflowStatusByRequestId called to retrieve all the records " + + "based on request Id" + ) + + var results: List = + blueprintAuditStatusRepository.findByRequestId(requestId) + log.info( + "getWorkflowStatusByRequestId results count " + + "${results.size}" + ) + return results + } + + /** + * Retrive workflow records based on request ID and sub request ID + * @param requestId + * @param subRequestId + * @return list of {@link BlueprintWorkflowAuditStatus} + */ + override suspend fun getWorkflowStatusByRequestIdAndSubRequestId( + requestId: String, + subRequestId: String + ): List { + log.info( + "getWorkflowStatusByRequestIdAndSubRequestId called to retrieve all the records " + + "based on request Id" + ) + + var results: List = + blueprintAuditStatusRepository.findByRequestIdAndSubRequestId(requestId, subRequestId) + log.info( + "getWorkflowStatusByRequestIdAndSubRequestId results count " + + "${results.size}" + ) + return results + } + + /** + * method to save input details to database + */ + suspend fun write( + id: Long, + originatorId: String, + requestId: String, + subRequestId: String, + workflowName: String, + blueprintName: String, + blueprintVersion: String, + workflowTaskContent: String, + status: String, + startDate: Date, + endDate: Date, + updatedDate: Date, + updatedBy: String, + requestMode: String, + workflowResponseContent: String + ): BlueprintWorkflowAuditStatus = + withContext(Dispatchers.IO) { + + val blueprintAuditStatusResult = BlueprintWorkflowAuditStatus() + + blueprintAuditStatusResult.originatorId = originatorId + blueprintAuditStatusResult.requestId = requestId + blueprintAuditStatusResult.subRequestId = subRequestId + blueprintAuditStatusResult.workflowName = workflowName + blueprintAuditStatusResult.blueprintName = blueprintName + blueprintAuditStatusResult.blueprintVersion = blueprintVersion + blueprintAuditStatusResult.workflowTaskContent = workflowTaskContent + blueprintAuditStatusResult.status = status + blueprintAuditStatusResult.startDate = startDate + blueprintAuditStatusResult.endDate = endDate + blueprintAuditStatusResult.updatedDate = updatedDate + blueprintAuditStatusResult.updatedBy = updatedBy + blueprintAuditStatusResult.requestMode = requestMode + blueprintAuditStatusResult.workflowResponseContent = + workflowResponseContent + + var storedAuditStatus: BlueprintWorkflowAuditStatus + try { + log.info( + "Writing out BLUEPRINT_AUDIT_STATUS result: bpName: " + + "$blueprintName bpVer $blueprintVersion " + + "id:$id" + + " (originatorId: $originatorId requestId: " + + "$requestId) subRequestId:$subRequestId" + ) + storedAuditStatus = blueprintAuditStatusRepository.saveAndFlush( + blueprintAuditStatusResult + ) + } catch (ex: DataIntegrityViolationException) { + log.error( + "Error writing out BLUEPRINT_AUDIT_STATUS result: bpName:" + + " $blueprintName bpVer $blueprintVersion " + + "id:$id" + + " (originatorId: $originatorId requestId:" + + " $requestId) subRequestId:$subRequestId error: {}", + ex.message + ) + throw BluePrintException( + "Failed to store resource api result.", + ex + ) + } + storedAuditStatus + } +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditService.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditService.kt new file mode 100644 index 000000000..230e67852 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditService.kt @@ -0,0 +1,118 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintAuditStatusRepository +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Service +import javax.annotation.PostConstruct + +/** + * Workflow request and response details are persisted to database + */ +@ConditionalOnProperty( + name = ["blueprintsprocessor.workflow.self-service-api.audit.storeEnable"], + havingValue = "false" +) +@Service +class NoStoreAuditService( + private val blueprintAuditStatusRepository: BlueprintAuditStatusRepository +) : StoreAuditService { + + private val log = + LoggerFactory.getLogger(NoStoreAuditService::class.toString()) + + @PostConstruct + fun init() { + log.info("Workflow Audit store is disabled") + } + /** + * store the blueprint workflow input details to database + * @param executionServiceInput {@link ExecutionServiceInput} + * @throws {@link BluePrintException} + */ + override suspend fun storeExecutionInput( + executionServiceInput: ExecutionServiceInput + ): Long { + log.info( + "storeExecutionInput called not to store the Workflow action " + + "input details " + ) + val resturnId: Long = -1 + return resturnId + } + + /** + * store the blueprint workflow output to database + * @param auditStoreId + * @param correlationUUID + * @param executionServiceOutput {@link ExecutionServiceOutput} + * @throws {@link BluePrintException} + */ + override suspend fun storeExecutionOutput( + auditStoreId: Long, + correlationUUID: String, + executionServiceOutput: ExecutionServiceOutput + ) { + log.info( + "storeExecutionOutput called not to store the Workflow action " + + "output details correlationUUID $correlationUUID " + + "auditStoreId $auditStoreId" + ) + } + + /** + * retrive workflow records based on request ID + * @param requestId + * @return list of {@link BlueprintWorkflowAuditStatus} + */ + override suspend fun getWorkflowStatusByRequestId( + requestId: String + ): List { + log.info( + "getWorkflowStatusByRequestId placeholer , this doesn't return " + + "any records" + ) + + var results: List = ArrayList() + return results + } + + /** + * Retrive workflow records based on request ID and sub request ID + * @param requestId + * @param subRequestId + * @return list of {@link BlueprintWorkflowAuditStatus} + */ + override suspend fun getWorkflowStatusByRequestIdAndSubRequestId( + requestId: String, + subRequestId: String + ): List { + log.info( + "getWorkflowStatusByRequestIdAndSubRequestId placeholer , this doesn't return " + + "any records" + ) + + var results: List = ArrayList() + + return results + } +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/StoreAuditService.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/StoreAuditService.kt new file mode 100644 index 000000000..a2bfc1121 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/StoreAuditService.kt @@ -0,0 +1,69 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus + +/** + * Workflow request and response details are persisted to database + */ + +interface StoreAuditService { + + /** + * store the blueprint workflow input details to database + * @param executionServiceInput {@link ExecutionServiceInput} + * @throws {@link BluePrintException} + */ + suspend fun storeExecutionInput( + executionServiceInput: ExecutionServiceInput + ): Long + + /** + * store the blueprint workflow output to database + * @param auditStoreId + * @param correlationUUID + * @param executionServiceOutput {@link ExecutionServiceOutput} + */ + suspend fun storeExecutionOutput( + auditStoreId: Long, + correlationUUID: String, + executionServiceOutput: ExecutionServiceOutput + ) + + /** + * retrive workflow records based on request ID + * @param requestId + * @return list of {@link BlueprintWorkflowAuditStatus} + */ + suspend fun getWorkflowStatusByRequestId( + requestId: String + ): List + + /** + * Retrive workflow records based on request ID and sub request ID + * @param requestId + * @param subRequestId + * @return list of {@link BlueprintWorkflowAuditStatus} + */ + suspend fun getWorkflowStatusByRequestIdAndSubRequestId( + requestId: String, + subRequestId: String + ): List +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepository.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepository.kt new file mode 100644 index 000000000..8e7304654 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepository.kt @@ -0,0 +1,107 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db + +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import javax.transaction.Transactional + +/** + * JPA repository managing {@link BlueprintWorkflowAuditStatus} table. + */ +@Repository +interface BlueprintAuditStatusRepository : + JpaRepository { + + /** + * retireve records based on primary key ID. + * @param id + * @return {@link BlueprintWorkflowAuditStatus} + */ + fun findById(id: Long): BlueprintWorkflowAuditStatus + + /** + * retrieve records based on request ID + * @param requestId + * @return list {@link BlueprintWorkflowAuditStatus} + */ + fun findByRequestId( + requestId: String + ): List + + /** + * retrieve records based on request ID and subrequest ID + * @param requestId + * @param subRequestId + * @return list {@link BlueprintWorkflowAuditStatus} + */ + fun findByRequestIdAndSubRequestId( + requestId: String, + subRequestId: String + ): List + + /** + * retrieve records based on request id, blueprint name , blueprint version + * @param requestId + * @param blueprintName + * @param blueprintVersion + * @return {@link BlueprintWorkflowAuditStatus} + */ + fun findByRequestIdAndBlueprintNameAndBlueprintVersion( + requestId: String, + blueprintName: String?, + blueprintVersion: String? + ): BlueprintWorkflowAuditStatus + + /** + * retrieve records based on request id, blueprint name , blueprint version + * @return {@link BlueprintWorkflowAuditStatus} + */ + fun findByOriginatorIdAndRequestIdAndSubRequestIdAndWorkflowNameAndBlueprintNameAndBlueprintVersion( + originatorId: String, + requestId: String?, + subRequestId: String?, + workflowName: String, + blueprintName: String?, + blueprintVersion: String? + ): BlueprintWorkflowAuditStatus + + /** + * retrieve records based on request id, subrequest, originator, workflow, + * blueprint version, blueprint Name + * @return {@link BlueprintWorkflowAuditStatus} + */ + fun findByIdAndOriginatorIdAndRequestIdAndSubRequestIdAndWorkflowNameAndBlueprintNameAndBlueprintVersion( + id: Long, + originatorId: String, + requestId: String?, + subRequestId: String?, + workflowName: String, + blueprintName: String?, + blueprintVersion: String? + ): BlueprintWorkflowAuditStatus + + @Transactional + fun deleteByIdAndBlueprintNameAndBlueprintVersionAndOriginatorIdAndRequestIdAndSubRequestId( + id: Long, + blueprintName: String?, + blueprintVersion: String?, + originatorId: String, + requestId: String?, + subRequestId: String? + ) +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintWorkflowAuditStatus.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintWorkflowAuditStatus.kt new file mode 100644 index 000000000..d9f0269f1 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintWorkflowAuditStatus.kt @@ -0,0 +1,136 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db + +import com.fasterxml.jackson.annotation.JsonFormat +import io.swagger.annotations.ApiModelProperty +import org.hibernate.annotations.Proxy +import org.springframework.data.annotation.LastModifiedDate +import java.io.Serializable +import java.util.Date +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.GenerationType +import javax.persistence.GeneratedValue +import javax.persistence.Id +import javax.persistence.Lob +import javax.persistence.Table +import javax.persistence.Temporal +import javax.persistence.TemporalType + +/** + * BlueprintWorkflowAuditStatus Model. + * Records stored and retrieved in table BLUEPRINT_WORKFLOW_AUDIT_STATUS is + * done through this entity. + */ +@Entity +@Table(name = "BLUEPRINT_WORKFLOW_AUDIT_STATUS") +@Proxy(lazy = false) +class BlueprintWorkflowAuditStatus : Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "workflow_audit_id") + var id: Long = 0 + + @get:ApiModelProperty(value = "Workflow payload.", required = true) + @Lob + @Column(name = "workflow_task_content", nullable = false) + @ApiModelProperty(required = true) + lateinit var workflowTaskContent: String + + @get:ApiModelProperty(value = "request originator Id", required = true) + @Column(name = "originator_Id", nullable = false) + @ApiModelProperty(required = true) + lateinit var originatorId: String + + @get:ApiModelProperty(value = "request Id", required = true) + @Column(name = "request_Id", nullable = false) + @ApiModelProperty(required = true) + lateinit var requestId: String + + @get:ApiModelProperty(value = "sub request Id", required = true) + @Column(name = "subRequest_Id", nullable = false) + @ApiModelProperty(required = true) + lateinit var subRequestId: String + + @get:ApiModelProperty(value = "workflow name", required = true) + @Column(name = "workflow_name", nullable = false) + @ApiModelProperty(required = true) + lateinit var workflowName: String + + @get:ApiModelProperty(value = "status", required = true) + @Column(name = "status", nullable = true) + @ApiModelProperty(required = true) + lateinit var status: String + + @get:ApiModelProperty( + value = "start time when request process started", required = true + ) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + @LastModifiedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "start_time") + var startDate: Date = Date() + + @get:ApiModelProperty( + value = "end time when request process completed", required = true + ) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + @LastModifiedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "end_time") + var endDate: Date = Date() + + @get:ApiModelProperty(value = "current date time", required = true) + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + @LastModifiedDate + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "updated_date") + var updatedDate: Date = Date() + + @get:ApiModelProperty(value = "updated by", required = true) + @Column(name = "updated_by", nullable = true) + @ApiModelProperty(required = true) + lateinit var updatedBy: String + + @get:ApiModelProperty(value = "blueprint version", required = true) + @Column(name = "blueprint_version", nullable = false) + @ApiModelProperty(required = true) + lateinit var blueprintVersion: String + + @get:ApiModelProperty(value = "blueprint name", required = true) + @Column(name = "blueprint_name", nullable = false) + @ApiModelProperty(required = true) + lateinit var blueprintName: String + + @get:ApiModelProperty(value = "request mode", required = true) + @Column(name = "request_mode", nullable = true) + @ApiModelProperty(required = true) + lateinit var requestMode: String + + @get:ApiModelProperty(value = "workflow response content", required = false) + @Lob + @Column(name = "workflow_response_content", nullable = true) + @ApiModelProperty(required = false) + lateinit var workflowResponseContent: String + + @get:ApiModelProperty(value = "bluprint model uuid", required = true) + @Column(name = "blueprint_uuid", nullable = true) + @ApiModelProperty(required = false) + var blueprintUuid: String = "" +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditServiceTest.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditServiceTest.kt new file mode 100644 index 000000000..cd4fc75a7 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/DatabaseStoreAuditServiceTest.kt @@ -0,0 +1,270 @@ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintAuditStatusRepository +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner +import java.util.Date +import kotlin.collections.ArrayList +import kotlin.test.assertNotNull + +@RunWith(SpringRunner::class) +@ContextConfiguration( + classes = [TestDatabaseConfiguration::class] +) +@TestPropertySource(locations = ["classpath:application-test.properties"]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@EnableAutoConfiguration +class DatabaseStoreAuditServiceTest { + + private val blueprintAuditStatusRepository = + mockk() + + private val databaseStoreAuditService = DatabaseStoreAuditService(blueprintAuditStatusRepository) + + @Test + fun storeExecutionInputTest() { + val executionServiceInput = JacksonUtils.readValueFromClassPathFile( + "exec-serv-input/multistep-input.json", + ExecutionServiceInput::class.java + )!! + val wfAudit1 = createWorkflowAuditStatusRecord(1000) + var testOuput: Long = 0 + runBlocking { + every { blueprintAuditStatusRepository.saveAndFlush(any()) } returns wfAudit1 + testOuput = databaseStoreAuditService.storeExecutionInput(executionServiceInput) + assertNotNull(testOuput, "failed to resolve the resources") + } + } + + @Test + fun storeExecutionOutputTest() { + val executionServiceOutput = JacksonUtils.readValueFromClassPathFile( + "exec-serv-output/multistep-output.json", + ExecutionServiceOutput::class.java + )!! + val inputAudit = createWorkflowAuditStatusRecord(1001) + val outputAudit = createWorkflowAuditStatusOutputRecord(1001) + + var testOutput: Long = 1001 + runBlocking { + every { blueprintAuditStatusRepository.findById(testOutput) } returns inputAudit + every { blueprintAuditStatusRepository.saveAndFlush(any()) } returns outputAudit + databaseStoreAuditService.storeExecutionOutput( + testOutput, + "12345", executionServiceOutput + ) + } + } + + @Test(expected = Exception::class) + fun storeExecutionOutputErrorTest() { + val executionServiceOutput = JacksonUtils.readValueFromClassPathFile( + "exec-serv-output/multistep-output.json", + ExecutionServiceOutput::class.java + )!! + // val inputAudit = createWorkflowAuditStatusRecord(1001) + val outputAudit = createWorkflowAuditStatusOutputRecord(1001) + + var testOutput: Long = -1 + runBlocking { + every { blueprintAuditStatusRepository.findById(-1) } returns null + every { blueprintAuditStatusRepository.saveAndFlush(any()) } returns outputAudit + databaseStoreAuditService.storeExecutionOutput( + testOutput, + "12345", executionServiceOutput + ) + } + } + + @Test + fun getWorkflowStatusByRequestIdAndSubRequestIdTest() { + val inputAudit = createWorkflowAuditStatusList(1003) + val testRequestId: String = "ab543-3asd4" + val testSubRequestId: String = "81c9-4910" + runBlocking { + every { + blueprintAuditStatusRepository.findByRequestIdAndSubRequestId(testRequestId, testSubRequestId) + } returns inputAudit + assertNotNull( + inputAudit.get(0).blueprintName, "Blueprint Name should not be null" + ) + assertNotNull( + inputAudit.get(0).blueprintVersion, "Blueprint should not be null" + ) + assertNotNull( + inputAudit.get(0).requestId, "Request ID should not be null" + ) + assertNotNull( + inputAudit.get(0).subRequestId, "Subrequest ID should not be null" + ) + assertNotNull( + inputAudit.get(0).status, "Status should not be null" + ) + assertNotNull( + inputAudit.get(0).startDate, "Start Date should not be null" + ) + assertNotNull( + inputAudit.get(0).updatedBy, "Updatedby should not be null" + ) + assertNotNull( + inputAudit.get(0).updatedDate, "updated Date should not be null" + ) + assertNotNull( + inputAudit.get(0).originatorId, "Originator ID should not be null" + ) + assertNotNull( + inputAudit.get(0).requestMode, "Request Mode should not be null" + ) + assertNotNull( + inputAudit.get(0).id, "ID should not be null" + ) + databaseStoreAuditService.getWorkflowStatusByRequestIdAndSubRequestId(testRequestId, testSubRequestId) + } + } + + @Test + fun getWorkflowStatusByRequestIdTest() { + val inputAudit = createWorkflowAuditStatusList(1004) + val testRequestId: String = "ab543-3asd4" + runBlocking { + every { blueprintAuditStatusRepository.findByRequestId(testRequestId) } returns inputAudit + databaseStoreAuditService.getWorkflowStatusByRequestId(testRequestId) + } + } + + private fun createWorkflowAuditStatusRecord( + id: Long + ): BlueprintWorkflowAuditStatus { + + var blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus = + BlueprintWorkflowAuditStatus() + blueprintWorkflowAuditStatus.id = id + blueprintWorkflowAuditStatus.originatorId = "SDNC_DG" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.requestId = "ab543-3asd4" + blueprintWorkflowAuditStatus.subRequestId = "81c9-4910" + blueprintWorkflowAuditStatus.status = "In progress" + blueprintWorkflowAuditStatus.blueprintName = "multi-steps" + blueprintWorkflowAuditStatus.blueprintVersion = "1.0.0" + blueprintWorkflowAuditStatus.workflowName = "multi-steps-workflow" + blueprintWorkflowAuditStatus.updatedBy = DatabaseStoreAuditConstants.WORKFLOW_STATUS_UPDATEDBY + blueprintWorkflowAuditStatus.endDate = Date() + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.workflowTaskContent = "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }" + blueprintWorkflowAuditStatus.workflowResponseContent = " " + return blueprintWorkflowAuditStatus + } + + private fun createWorkflowAuditStatusOutputRecord( + id: Long + ): BlueprintWorkflowAuditStatus { + + var blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus = + BlueprintWorkflowAuditStatus() + blueprintWorkflowAuditStatus.id = id + blueprintWorkflowAuditStatus.originatorId = "SDNC_DG" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.requestId = "ab543-3asd4" + blueprintWorkflowAuditStatus.subRequestId = "81c9-4910" + blueprintWorkflowAuditStatus.status = DatabaseStoreAuditConstants.WORKFLOW_STATUS_INPROGRESS + blueprintWorkflowAuditStatus.blueprintName = "multi-steps" + blueprintWorkflowAuditStatus.blueprintVersion = "1.0.0" + blueprintWorkflowAuditStatus.workflowName = "multi-steps-workflow" + blueprintWorkflowAuditStatus.updatedBy = "CBA" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.workflowTaskContent = "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }" + blueprintWorkflowAuditStatus.workflowResponseContent = "{\n" + + " \"correlationUUID\": null,\n" + + " \"commonHeader\": {\n" + + " \"timestamp\": \"2021-08-05T08:18:35.690Z\",\n" + + " \"originatorId\": \"SDNC_DG\",\n" + + " \"requestId\": \"ab543-3asd4\",\n" + + " \"subRequestId\": \"81c9-4910\",\n" + + " \"flags\": null\n" + + " },\n" + + " \"actionIdentifiers\": {\n" + + " \"blueprintName\": \"multi-steps\",\n" + + " \"blueprintVersion\": \"1.0.0\",\n" + + " \"actionName\": \"multi-steps-workflow\",\n" + + " \"mode\": \"sync\"\n" + + " },\n" + + " \"status\": {\n" + + " \"code\": 200,\n" + + " \"eventType\": \"EVENT_COMPONENT_EXECUTED\",\n" + + " \"timestamp\": \"2021-08-05T08:18:35.727Z\",\n" + + " \"errorMessage\": null,\n" + + " \"message\": \"success\"\n" + + " },\n" + + " \"payload\": {\n" + + " \"multi-steps-workflow-response\": {}\n" + + " }\n" + + "} " + return blueprintWorkflowAuditStatus + } + + private fun createWorkflowAuditStatusList( + id: Long + ): List { + + var blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus = + BlueprintWorkflowAuditStatus() + blueprintWorkflowAuditStatus.id = id + blueprintWorkflowAuditStatus.originatorId = "SDNC_DG" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.requestId = "ab543-3asd4" + blueprintWorkflowAuditStatus.subRequestId = "81c9-4910" + blueprintWorkflowAuditStatus.status = DatabaseStoreAuditConstants.WORKFLOW_STATUS_INPROGRESS + blueprintWorkflowAuditStatus.blueprintName = "multi-steps" + blueprintWorkflowAuditStatus.blueprintVersion = "1.0.0" + blueprintWorkflowAuditStatus.workflowName = "multi-steps-workflow" + blueprintWorkflowAuditStatus.updatedBy = DatabaseStoreAuditConstants.WORKFLOW_STATUS_UPDATEDBY + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.workflowTaskContent = "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }" + blueprintWorkflowAuditStatus.workflowResponseContent = " " + var testList: ArrayList = ArrayList() + testList.add(blueprintWorkflowAuditStatus) + return testList + } +} + +private infix fun Any.returns(nothing: Nothing?) { +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditServiceTest.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditServiceTest.kt new file mode 100644 index 000000000..16abe95d3 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/NoStoreAuditServiceTest.kt @@ -0,0 +1,81 @@ +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +import io.mockk.mockk +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintAuditStatusRepository +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +@RunWith(SpringRunner::class) +@ContextConfiguration( + classes = [TestDatabaseConfiguration::class] +) +@TestPropertySource(locations = ["classpath:application-test.properties"]) +@ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) +@EnableAutoConfiguration +class NoStoreAuditServiceTest { + + private val blueprintAuditStatusRepository = + mockk() + + private val storeAuditService = NoStoreAuditService(blueprintAuditStatusRepository) + + @Test + fun storeExecutionInputTest() { + val executionServiceInput = JacksonUtils.readValueFromClassPathFile( + "exec-serv-input/multistep-input.json", + ExecutionServiceInput::class.java + )!! + var testOuput: Long = 0 + runBlocking { + testOuput = storeAuditService.storeExecutionInput(executionServiceInput) + assertEquals(-1, testOuput, "Failed to resolve the workflow") + } + } + + @Test + fun storeExecutionOutputTest() { + val executionServiceOutput = JacksonUtils.readValueFromClassPathFile( + "exec-serv-output/multistep-output.json", + ExecutionServiceOutput::class.java + )!! + var testOutput: Long = -1 + runBlocking { + storeAuditService.storeExecutionOutput( + testOutput, "12345", executionServiceOutput + ) + } + } + + @Test + fun getWorkflowStatusByRequestIdAndSubRequestIdTest() { + val testRequestId: String = "ab543-3asd4" + val testSubRequestId: String = "81c9-4910" + var testList: List? = null + runBlocking { + testList = storeAuditService.getWorkflowStatusByRequestIdAndSubRequestId(testRequestId, testSubRequestId) + assertNotNull(testList, " Returned null instead of empty list ") + } + } + + @Test + fun getWorkflowStatusByRequestIdTest() { + val testRequestId: String = "ab543-3asd4" + var testList: List? = null + runBlocking { + testList = storeAuditService.getWorkflowStatusByRequestId(testRequestId) + assertNotNull(testList, " Returned null instead of empty list ") + } + } +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/TestDatabaseConfiguration.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/TestDatabaseConfiguration.kt new file mode 100644 index 000000000..682b89155 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/TestDatabaseConfiguration.kt @@ -0,0 +1,62 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit + +import org.onap.ccsdk.cds.blueprintsprocessor.db.BluePrintDBLibConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.db.PrimaryDataSourceProperties +import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.PrimaryDatabaseConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import +import org.springframework.data.jpa.repository.config.EnableJpaAuditing +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean +import org.springframework.transaction.PlatformTransactionManager +import javax.sql.DataSource + +@Configuration +@Import(BluePrintDBLibConfiguration::class) +@EnableJpaRepositories( + basePackages = [ + "org.onap.ccsdk.cds.blueprintsprocessor.db.primary", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit" + ], + entityManagerFactoryRef = "primaryEntityManager", + transactionManagerRef = "primaryTransactionManager" +) +@EnableJpaAuditing +open class TestDatabaseConfiguration(primaryDataSourceProperties: PrimaryDataSourceProperties) : + PrimaryDatabaseConfiguration(primaryDataSourceProperties) { + + @Bean("primaryEntityManager") + open fun primaryEntityManager(): LocalContainerEntityManagerFactoryBean { + return primaryEntityManager( + "org.onap.ccsdk.cds.blueprintsprocessor.db.primary", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db" + ) + } + + @Bean("primaryDataSource") + override fun primaryDataSource(): DataSource { + return super.primaryDataSource() + } + + @Bean("primaryTransactionManager") + override fun primaryTransactionManager(): PlatformTransactionManager { + return super.primaryTransactionManager() + } +} diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepositoryTest.kt b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/workflow/audit/db/BlueprintAuditStatusRepositoryTest.kt new file mode 100644 index 000000000..e69de29bb diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/application-test.properties b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/application-test.properties new file mode 100644 index 000000000..6a707b08e --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/application-test.properties @@ -0,0 +1,36 @@ +# +# Copyright © 2021 Aarna Networks, Inc. +# All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +blueprintsprocessor.db.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 +blueprintsprocessor.db.username=sa +blueprintsprocessor.db.password= +blueprintsprocessor.db.driverClassName=org.h2.Driver +blueprintsprocessor.db.hibernateHbm2ddlAuto=create-drop +blueprintsprocessor.db.hibernateDDLAuto=update +blueprintsprocessor.db.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy +blueprintsprocessor.db.hibernateDialect=org.hibernate.dialect.H2Dialect +# Controller Blueprints Core Configuration +blueprintsprocessor.blueprintDeployPath=./target/blueprints/deploy +blueprintsprocessor.blueprintWorkingPath=./target/blueprints/work +blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive + +# Error Managements +error.catalog.applicationId=cds +error.catalog.type=properties +error.catalog.errorDefinitionDir=./../../../application/src/test/resources/ + +# Python executor +blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints +blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-input/multistep-input.json b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-input/multistep-input.json new file mode 100644 index 000000000..8e2552c00 --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-input/multistep-input.json @@ -0,0 +1,23 @@ +{ + "actionIdentifiers": { + "mode": "sync", + "blueprintName": "multi-steps", + "blueprintVersion": "1.0.0", + "actionName": "multi-steps-workflow" + }, + "payload": { + "multi-steps-workflow-request": { + "multi-steps-workflow-properties": { + "prop1": "testing", + "prop2": "testing description", + "prop3": "user name ", + "prop4" : "test project" + } + } + }, + "commonHeader": { + "subRequestId": "81c9-4910", + "requestId": "ab543-3asd4", + "originatorId": "SDNC_DG" + } +} \ No newline at end of file diff --git a/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-output/multistep-output.json b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-output/multistep-output.json new file mode 100644 index 000000000..ca12b893d --- /dev/null +++ b/ms/blueprintsprocessor/functions/blueprint-audit-status/src/test/resources/exec-serv-output/multistep-output.json @@ -0,0 +1,26 @@ +{ + "correlationUUID": null, + "commonHeader": { + "timestamp": "2021-08-05T08:18:35.690Z", + "originatorId": "SDNC_DG", + "requestId": "ab543-3asd4", + "subRequestId": "81c9-4910", + "flags": null + }, + "actionIdentifiers": { + "blueprintName": "multi-steps", + "blueprintVersion": "1.0.0", + "actionName": "multi-steps-workflow", + "mode": "sync" + }, + "status": { + "code": 200, + "eventType": "EVENT_COMPONENT_EXECUTED", + "timestamp": "2021-08-05T08:18:35.727Z", + "errorMessage": null, + "message": "success" + }, + "payload": { + "multi-steps-workflow-response": {} + } +} diff --git a/ms/blueprintsprocessor/functions/pom.xml b/ms/blueprintsprocessor/functions/pom.xml index a1a4daad4..a019c6266 100755 --- a/ms/blueprintsprocessor/functions/pom.xml +++ b/ms/blueprintsprocessor/functions/pom.xml @@ -42,6 +42,7 @@ config-snapshots message-prioritization k8s-connection-plugin + blueprint-audit-status diff --git a/ms/blueprintsprocessor/modules/inbounds/pom.xml b/ms/blueprintsprocessor/modules/inbounds/pom.xml index 2b474bb3f..b29dc36b5 100644 --- a/ms/blueprintsprocessor/modules/inbounds/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/pom.xml @@ -37,6 +37,7 @@ selfservice-api health-api health-api-common + workflow-api diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml index 94cc382d7..d7d0a0ffb 100755 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml @@ -52,6 +52,12 @@ org.onap.ccsdk.cds.blueprintsprocessor.modules message-lib + + + org.onap.ccsdk.cds.blueprintsprocessor.functions + blueprint-audit-status + 1.2.0-SNAPSHOT + diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt index e604987a7..c2c7a60e9 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt @@ -33,6 +33,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.SelfServiceMetricC import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.SelfServiceMetricConstants.TIMER_PROCESS import org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api.utils.cbaMetricTags import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractServiceFunction +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.StoreAuditService import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration @@ -50,6 +51,7 @@ class ExecutionServiceHandler( private val bluePrintWorkflowExecutionService: BluePrintWorkflowExecutionService, private val publishAuditService: PublishAuditService, + private val storeAuditService: StoreAuditService, private val meterRegistry: MeterRegistry ) { @@ -102,6 +104,10 @@ class ExecutionServiceHandler( // Audit input publishAuditService.publishExecutionInput(executionServiceInput) + // store audit input details + val auditStoreId: Long = storeAuditService.storeExecutionInput(executionServiceInput) + log.info("StoreAuditService ID $auditStoreId") + val sample = Timer.start() try { /** Check Blueprint is needed for this request */ @@ -130,9 +136,14 @@ class ExecutionServiceHandler( // Update process metrics sample.stop(meterRegistry.timer(TIMER_PROCESS, cbaMetricTags(executionServiceInput))) meterRegistry.counter(COUNTER_PROCESS, cbaMetricTags(executionServiceOutput)).increment() - // Audit output publishAuditService.publishExecutionOutput(executionServiceInput.correlationUUID, executionServiceOutput) + + // store audit input details + storeAuditService.storeExecutionOutput( + auditStoreId, executionServiceInput.correlationUUID, + executionServiceOutput + ) return executionServiceOutput } diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt index d7d7aaa2a..ebaa8bd7e 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt @@ -23,6 +23,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.DatabaseStoreAuditService import org.onap.ccsdk.cds.controllerblueprints.core.compress import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService @@ -46,7 +47,8 @@ import kotlin.test.assertTrue @ContextConfiguration( classes = [ ExecutionServiceHandler::class, BluePrintCoreConfiguration::class, - BluePrintCatalogService::class, SelfServiceApiTestConfiguration::class, + BluePrintCatalogService::class, DatabaseStoreAuditService::class, + SelfServiceApiTestConfiguration::class, ErrorCatalogTestConfiguration::class, SimpleMeterRegistry::class ] ) 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 0a89c5782..af3cbd89a 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 @@ -16,11 +16,14 @@ package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.node.ObjectNode import io.micrometer.core.instrument.MeterRegistry import io.mockk.coVerify import io.mockk.Runs import io.mockk.coEvery import io.mockk.coVerify +import io.mockk.every import io.mockk.just import io.mockk.mockk import kotlinx.coroutines.runBlocking @@ -30,9 +33,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.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.DatabaseStoreAuditService +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintAuditStatusRepository +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractServiceFunction import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.mock.mockito.MockBean import org.springframework.context.ApplicationContext @@ -60,6 +67,11 @@ class ExecutionServiceHandlerTest { @Autowired lateinit var applicationContext: ApplicationContext + private val blueprintAuditStatusRepository = + mockk() + + private val testDatabaseStoreAuditService = DatabaseStoreAuditService(blueprintAuditStatusRepository) + @Before fun init() { BluePrintDependencyService.inject(applicationContext) @@ -80,7 +92,7 @@ class ExecutionServiceHandlerTest { } } runBlocking { - val executionServiceHandler = ExecutionServiceHandler(mockk(), mockk(), mockk(), mockk(), mockk(relaxed = true)) + val executionServiceHandler = ExecutionServiceHandler(mockk(), mockk(), mockk(), mockk(), testDatabaseStoreAuditService, mockk(relaxed = true)) val isServiceFunction = executionServiceHandler.checkServiceFunction(executionServiceInput) assertTrue(isServiceFunction, "failed to checkServiceFunction") val executionServiceOutput = executionServiceHandler.executeServiceFunction(executionServiceInput) @@ -90,6 +102,10 @@ class ExecutionServiceHandlerTest { @Test fun testPublishAuditFunction() { + + val jsonContent = JacksonUtils.getClassPathFileContent("execution-input/sample-payload.json") + val json: ObjectNode = ObjectMapper().readTree(jsonContent) as ObjectNode + val executionServiceInput = ExecutionServiceInput().apply { commonHeader = CommonHeader().apply { requestId = "1234" @@ -100,20 +116,29 @@ class ExecutionServiceHandlerTest { blueprintName = "default" blueprintVersion = "1.0.0" actionName = "mock-service-action" + mode = "async" } } - + executionServiceInput.payload = json val publishAuditService = mockk(relaxed = true) + val wfAudit = createWorkflowAuditStatusRecord(1000) + val executionServiceHandler = ExecutionServiceHandler( mockk(), mockk(), mockk(), publishAuditService, + testDatabaseStoreAuditService, mockk(relaxed = true) ) - + var testOutput: Long = 1000 coEvery { publishAuditService.publishExecutionInput(ExecutionServiceInput()) } just Runs + runBlocking { + every { blueprintAuditStatusRepository.findById(testOutput) } returns wfAudit + every { blueprintAuditStatusRepository.saveAndFlush(any()) } returns wfAudit + } + var executionServiceOutput: ExecutionServiceOutput? = null runBlocking { executionServiceOutput = executionServiceHandler.doProcess(executionServiceInput) @@ -122,8 +147,40 @@ class ExecutionServiceHandlerTest { coVerify { publishAuditService.publishExecutionInput(executionServiceInput) publishAuditService.publishExecutionOutput(executionServiceInput.correlationUUID, executionServiceOutput!!) + testOutput = testDatabaseStoreAuditService.storeExecutionInput(executionServiceInput) } } + + private fun createWorkflowAuditStatusRecord( + id: Long + ): BlueprintWorkflowAuditStatus { + + var blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus = + BlueprintWorkflowAuditStatus() + blueprintWorkflowAuditStatus.id = id + blueprintWorkflowAuditStatus.originatorId = "SDNC_DG" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.requestId = "ab543-3asd4" + blueprintWorkflowAuditStatus.subRequestId = "81c9-4910" + blueprintWorkflowAuditStatus.status = "In progress" + blueprintWorkflowAuditStatus.blueprintName = "multi-steps" + blueprintWorkflowAuditStatus.blueprintVersion = "1.0.0" + blueprintWorkflowAuditStatus.workflowName = "multi-steps-workflow" + blueprintWorkflowAuditStatus.updatedBy = "CBA" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.workflowTaskContent = "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }" + blueprintWorkflowAuditStatus.workflowResponseContent = " " + return blueprintWorkflowAuditStatus + } } @Service("mock-service-action") diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/TestDatabaseConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/TestDatabaseConfiguration.kt index bca05f68b..5a2c5e5db 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/TestDatabaseConfiguration.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/TestDatabaseConfiguration.kt @@ -33,7 +33,8 @@ import javax.sql.DataSource @EnableJpaRepositories( basePackages = [ "org.onap.ccsdk.cds.blueprintsprocessor.db.primary", - "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution" + "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit" ], entityManagerFactoryRef = "primaryEntityManager", transactionManagerRef = "primaryTransactionManager" @@ -46,6 +47,7 @@ open class TestDatabaseConfiguration(primaryDataSourceProperties: PrimaryDataSou open fun primaryEntityManager(): LocalContainerEntityManagerFactoryBean { return primaryEntityManager( "org.onap.ccsdk.cds.blueprintsprocessor.db.primary", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit", "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution" ) } 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 77b61a421..8dfaf7896 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 @@ -68,3 +68,7 @@ blueprintsprocessor.messageproducer.self-service-api.audit.response.type=kafka-b blueprintsprocessor.messageproducer.self-service-api.audit.response.bootstrapServers=127.0.0.1:9092 blueprintsprocessor.messageproducer.self-service-api.audit.response.clientId=audit-response-producer-client-id blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit-response-producer.t + +#Workflow Audit store enable +blueprintsprocessor.workflow.self-service-api.audit.storeEnable=true + diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml new file mode 100644 index 000000000..7e5ebecb8 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/pom.xml @@ -0,0 +1,56 @@ + + + + + 4.0.0 + + + org.onap.ccsdk.cds.blueprintsprocessor + modules-inbounds + 1.2.0-SNAPSHOT + + + org.onap.ccsdk.cds.blueprintsprocessor.modules + workflow-api + jar + + MS Blueprints Processor Modules - Inbounds - Workflow API + + + + org.springframework.security + spring-security-core + + + org.onap.ccsdk.cds.blueprintsprocessor.modules + blueprint-core + + + org.onap.ccsdk.cds.error.catalog + error-catalog-services + + + org.onap.ccsdk.cds.blueprintsprocessor.functions + blueprint-audit-status + ${project.version} + + + org.onap.ccsdk.cds.blueprintsprocessor.modules + db-lib + + + diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorHandling.kt b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorHandling.kt new file mode 100644 index 000000000..5e4289e7b --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorHandling.kt @@ -0,0 +1,35 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.workflow.api + +object WorkflowApiDomains { + + // Workflow Api Domains Constants + const val WORKFLOW_API = "org.onap.ccsdk.cds.blueprintsprocessor.workflow.api" +} + +object WorkflowApiHttpErrorCodes { + init { + // Register HttpErrorCodes + } +} + +object WorkflowGrpcErrorCodes { + init { + // Register GrpcErrorCodes + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowController.kt b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowController.kt new file mode 100644 index 000000000..e131bf378 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowController.kt @@ -0,0 +1,109 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.workflow.api + +import com.fasterxml.jackson.databind.JsonNode +import io.swagger.annotations.Api +import io.swagger.annotations.ApiOperation +import io.swagger.annotations.ApiParam +import kotlinx.coroutines.runBlocking +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.StoreAuditService +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes +import org.slf4j.LoggerFactory +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestMethod +import org.springframework.web.bind.annotation.ResponseBody +import org.springframework.web.bind.annotation.RestController + +/** + * Rest API which handles retrieving the workflow store records + */ +@RestController +@RequestMapping("/api/v1/workflow") +@Api( + value = "/api/v1/workflow", + description = "Interaction with blueprint workflow status resources" +) +class WorkflowController { + private val log = + LoggerFactory.getLogger(WorkflowController::class.toString()) + + @Autowired + lateinit var databaseStoreAuditService: StoreAuditService + + private val JSON_MIME_TYPE = "application/json" + + /** + * workflow healthcheck api + */ + @RequestMapping( + path = ["/health-check"], + method = [RequestMethod.GET], + produces = [MediaType.APPLICATION_JSON_VALUE] + ) + @ResponseBody + @ApiOperation(value = "Health Check", hidden = true) + fun workflowControllerHealthCheck(): JsonNode = runBlocking { + JacksonUtils.getJsonNode("Success") + } + + /** + * API to retreive records based on request and subrequest ID * + */ + @GetMapping( + "/audit-status/{requestId}/{subRequestId}", + produces = [MediaType.APPLICATION_JSON_VALUE] + ) + @ApiOperation( + value = "Get all workflow status records using request and Subrequest", + notes = "Retrieve all stored workflow audit records based on " + + "requestId and SubrequestId", + response = BlueprintWorkflowAuditStatus::class, + responseContainer = "List", + produces = MediaType.APPLICATION_JSON_VALUE + ) + @ResponseBody + @PreAuthorize("hasRole('USER')") + suspend fun getWorkFlowByRequestAndSubRequest( + @ApiParam(value = "request ID", required = true) + @PathVariable(value = "requestId") requestId: String, + @ApiParam(value = "sub request ID", required = true) + @PathVariable(value = "subRequestId") subRequestId: String + ): ResponseEntity> = runBlocking { + var requestIdResults: List + if (requestId.isNotEmpty()) { + requestIdResults = databaseStoreAuditService + .getWorkflowStatusByRequestIdAndSubRequestId(requestId, subRequestId) + } else { + throw httpProcessorException( + ErrorCatalogCodes.REQUEST_NOT_FOUND, WorkflowApiDomains.WORKFLOW_API, + "Missing param." + ) + } + val expectedMediaType: MediaType = MediaType.valueOf(JSON_MIME_TYPE) + ResponseEntity.ok().contentType(expectedMediaType).body(requestIdResults) + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowExceptionHandler.kt new file mode 100644 index 000000000..18dfe085b --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowExceptionHandler.kt @@ -0,0 +1,29 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.workflow.api + +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService +import org.springframework.web.bind.annotation.RestControllerAdvice + +/** + * Handle exceptions in Workflow API and provide relevant HTTP status codes and + * messages + * + */ +@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.workflow.api") +open class WorkflowExceptionHandler(private val errorCatalogService: ErrorCatalogService) : + ErrorCatalogExceptionHandler(errorCatalogService) diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorCatalogTestConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorCatalogTestConfiguration.kt new file mode 100644 index 000000000..a05f569c0 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/ErrorCatalogTestConfiguration.kt @@ -0,0 +1,28 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.workflow.api + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan( + basePackages = ["org.onap.ccsdk.cds.error.catalog"] +) +@EnableAutoConfiguration +open class ErrorCatalogTestConfiguration diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/TestDatabaseConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/TestDatabaseConfiguration.kt new file mode 100644 index 000000000..7ca90e9ec --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/TestDatabaseConfiguration.kt @@ -0,0 +1,62 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.workflow.api + +import org.onap.ccsdk.cds.blueprintsprocessor.db.BluePrintDBLibConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.db.PrimaryDataSourceProperties +import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.PrimaryDatabaseConfiguration +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.context.annotation.Import +import org.springframework.data.jpa.repository.config.EnableJpaAuditing +import org.springframework.data.jpa.repository.config.EnableJpaRepositories +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean +import org.springframework.transaction.PlatformTransactionManager +import javax.sql.DataSource + +@Configuration +@Import(BluePrintDBLibConfiguration::class) +@EnableJpaRepositories( + basePackages = [ + "org.onap.ccsdk.cds.blueprintsprocessor.db.primary", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit" + ], + entityManagerFactoryRef = "primaryEntityManager", + transactionManagerRef = "primaryTransactionManager" +) +@EnableJpaAuditing +open class TestDatabaseConfiguration(primaryDataSourceProperties: PrimaryDataSourceProperties) : + PrimaryDatabaseConfiguration(primaryDataSourceProperties) { + + @Bean("primaryEntityManager") + open fun primaryEntityManager(): LocalContainerEntityManagerFactoryBean { + return primaryEntityManager( + "org.onap.ccsdk.cds.blueprintsprocessor.db.primary", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db" + ) + } + + @Bean("primaryDataSource") + override fun primaryDataSource(): DataSource { + return super.primaryDataSource() + } + + @Bean("primaryTransactionManager") + override fun primaryTransactionManager(): PlatformTransactionManager { + return super.primaryTransactionManager() + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowControllerTest.kt new file mode 100644 index 000000000..bf6960f02 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/workflow/api/WorkflowControllerTest.kt @@ -0,0 +1,268 @@ +/* + * Copyright © 2021 Aarna Networks, Inc. + * All rights reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.workflow.api + +import kotlinx.coroutines.runBlocking +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.DatabaseStoreAuditService +import org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit.db.BlueprintWorkflowAuditStatus +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest +import org.springframework.context.annotation.ComponentScan +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import org.springframework.test.context.junit4.SpringRunner +import org.springframework.test.web.reactive.server.WebTestClient +import java.text.SimpleDateFormat +import java.util.List + +@RunWith(SpringRunner::class) +@WebFluxTest +@ContextConfiguration( + classes = [ + TestDatabaseConfiguration::class, ErrorCatalogTestConfiguration::class, + WorkflowController::class, DatabaseStoreAuditService::class + ] +) +@ComponentScan( + basePackages = [ + "org.onap.ccsdk.cds.controllerblueprints.core.service", + "org.onap.ccsdk.cds.blueprintsprocessor.functions.workflow.audit", + "org.onap.ccsdk.cds.blueprintsprocessor.workflow.api" + ] +) +@TestPropertySource(locations = ["classpath:application-test.properties"]) +class WorkflowControllerTest { + + @Autowired + lateinit var databaseStoreAuditService: DatabaseStoreAuditService + @Autowired + lateinit var testWebClient: WebTestClient + + @Test + fun testWorkflowControllerHealthCheck() { + runBlocking { + testWebClient.get().uri("/api/v1/workflow/health-check") + .exchange() + .expectStatus().isOk + .expectBody() + .equals("Success") + } + } + + @Test + fun testGetWorkFlowByRequestAndSubRequest() { + + val wfAudit1 = createWorkflowAuditStatusRecord(1000) + val wfAudit2 = createWorkflowAuditStatusRecord(1001) + runBlocking { + + storeToDB(wfAudit1) + storeToDB(wfAudit2) + val testRequestId: String = "ab543-3asd4" + val testSubRequestId: String = "81c9-4910" + testWebClient + .get() + .uri("/api/v1/workflow/audit-status/$testRequestId/$testSubRequestId") + .exchange() + .expectStatus().isOk + .expectBody() + .consumeWith { + val json = String(it.responseBody!!) + val typeFactory = JacksonUtils.objectMapper.typeFactory + val list: List = JacksonUtils.objectMapper.readValue( + json, + typeFactory.constructCollectionType(List::class.java, BlueprintWorkflowAuditStatus::class.java) + ) + Assert.assertEquals(2, list.size) + assertEqual(list[0]) + assertEqual(list[1]) + } + } + } + + @Test + fun testEmptyRequestAndSubRequest() { + + val wfAudit1 = createWorkflowAuditStatusRecordSetTwo(1002) + val wfAudit2 = createWorkflowAuditStatusRecordSetTwo(1003) + runBlocking { + + storeToDB(wfAudit1) + storeToDB(wfAudit2) + val testRequestId: String = "" + val testSubRequestId: String = "" + testWebClient + .get() + .uri("/api/v1/workflow/audit-status/$testRequestId/$testSubRequestId") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + } + } + + @Test + @Throws(BluePrintException::class) + fun testErrorRequestAndSubRequest() { + + val wfAudit1 = createWorkflowAuditStatusRecordSetTwo(1002) + val wfAudit2 = createWorkflowAuditStatusRecordSetTwo(1003) + runBlocking { + + storeToDB(wfAudit1) + storeToDB(wfAudit2) + val testRequestId: String = "" + val testSubRequestId: String = "" + testWebClient + .get() + .uri("/api/v1/workflow/audit-status/$testRequestId/$testSubRequestId") + .exchange() + .expectStatus().is4xxClientError + .expectBody() + .consumeWith { + Assert.assertTrue( + "Cause: request Id and requesy sub Id is empty. \n " + + "Action : Please verify your request.", + it.status.is4xxClientError + ) + } + } + } + + private fun assertEqual(blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus) { + Assert.assertEquals(blueprintWorkflowAuditStatus.status, "In progress") + Assert.assertEquals(blueprintWorkflowAuditStatus.requestId, "ab543-3asd4") + Assert.assertEquals(blueprintWorkflowAuditStatus.subRequestId, "81c9-4910") + Assert.assertEquals(blueprintWorkflowAuditStatus.blueprintName, "multi-steps") + Assert.assertEquals(blueprintWorkflowAuditStatus.blueprintVersion, "1.0.0") + Assert.assertEquals(blueprintWorkflowAuditStatus.requestMode, "sync") + Assert.assertEquals(blueprintWorkflowAuditStatus.workflowName, "multi-steps-workflow") + Assert.assertEquals(blueprintWorkflowAuditStatus.originatorId, "SDNC_DG") + } + + private fun createWorkflowAuditStatusRecord( + id: Long + ): BlueprintWorkflowAuditStatus { + + var blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus = + BlueprintWorkflowAuditStatus() + blueprintWorkflowAuditStatus.id = id + blueprintWorkflowAuditStatus.originatorId = "SDNC_DG" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.requestId = "ab543-3asd4" + blueprintWorkflowAuditStatus.subRequestId = "81c9-4910" + blueprintWorkflowAuditStatus.status = "In progress" + blueprintWorkflowAuditStatus.blueprintName = "multi-steps" + blueprintWorkflowAuditStatus.blueprintVersion = "1.0.0" + blueprintWorkflowAuditStatus.workflowName = "multi-steps-workflow" + blueprintWorkflowAuditStatus.updatedBy = "CBA" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.workflowTaskContent = "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }" + blueprintWorkflowAuditStatus.workflowResponseContent = " " + return blueprintWorkflowAuditStatus + } + + private fun createWorkflowAuditStatusRecordSetTwo( + id: Long + ): BlueprintWorkflowAuditStatus { + + var blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus = + BlueprintWorkflowAuditStatus() + blueprintWorkflowAuditStatus.id = id + blueprintWorkflowAuditStatus.originatorId = "SDNC_DG" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.requestId = "ab543-3asd5" + blueprintWorkflowAuditStatus.subRequestId = "81c9-4911" + blueprintWorkflowAuditStatus.status = "In progress" + blueprintWorkflowAuditStatus.blueprintName = "multi-steps" + blueprintWorkflowAuditStatus.blueprintVersion = "1.0.0" + blueprintWorkflowAuditStatus.workflowName = "multi-steps-workflow" + blueprintWorkflowAuditStatus.updatedBy = "CBA" + blueprintWorkflowAuditStatus.requestMode = "sync" + blueprintWorkflowAuditStatus.workflowTaskContent = "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }" + blueprintWorkflowAuditStatus.workflowResponseContent = " " + return blueprintWorkflowAuditStatus + } + + private suspend fun store( + id: Long + ) { + val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + val dateString = "2021-08-08T18:25:43.511Z" + val dateForTest = formatter.parse(dateString) + databaseStoreAuditService.write( + id, "SDNC_DG", "ab543-3asd4", + "81c9-4910", + "multi-steps-workflow", "multi-steps", "1.0.0", + "{\n" + + " \"multi-steps-workflow-request\": {\n" + + " \"multi-steps-workflow-properties\": {\n" + + " \"prop1\": \"testing\",\n" + + " \"prop2\": \"testing description\",\n" + + " \"prop3\": \"user name \",\n" + + " \"prop4\" : \"test project\"\n" + + " }\n" + + " }\n" + + " }", + "In progress", dateForTest, dateForTest, dateForTest, "CBA", "sync", " " + ) + } + + private suspend fun storeToDB( + blueprintWorkflowAuditStatus: BlueprintWorkflowAuditStatus + ) { + databaseStoreAuditService.write( + blueprintWorkflowAuditStatus.id, + blueprintWorkflowAuditStatus.originatorId, + blueprintWorkflowAuditStatus.requestId, + blueprintWorkflowAuditStatus.subRequestId, + blueprintWorkflowAuditStatus.workflowName, + blueprintWorkflowAuditStatus.blueprintName, + blueprintWorkflowAuditStatus.blueprintVersion, + blueprintWorkflowAuditStatus.workflowTaskContent, + blueprintWorkflowAuditStatus.status, + blueprintWorkflowAuditStatus.startDate, + blueprintWorkflowAuditStatus.endDate, + blueprintWorkflowAuditStatus.updatedDate, + blueprintWorkflowAuditStatus.updatedBy, + blueprintWorkflowAuditStatus.requestMode, + blueprintWorkflowAuditStatus.workflowResponseContent + ) + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/resources/application-test.properties new file mode 100644 index 000000000..b970c53ef --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/workflow-api/src/test/resources/application-test.properties @@ -0,0 +1,39 @@ +# +# Copyright © 2021 Aarna Networks, Inc. +# All rights reserved. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +blueprintsprocessor.db.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1 +blueprintsprocessor.db.username=sa +blueprintsprocessor.db.password= +blueprintsprocessor.db.driverClassName=org.h2.Driver +blueprintsprocessor.db.hibernateHbm2ddlAuto=create-drop +blueprintsprocessor.db.hibernateDDLAuto=update +blueprintsprocessor.db.hibernateNamingStrategy=org.hibernate.cfg.ImprovedNamingStrategy +blueprintsprocessor.db.hibernateDialect=org.hibernate.dialect.H2Dialect +# Controller Blueprints Core Configuration +blueprintsprocessor.blueprintDeployPath=./target/blueprints/deploy +blueprintsprocessor.blueprintWorkingPath=./target/blueprints/work +blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive + +# Error Managements +error.catalog.applicationId=cds +error.catalog.type=properties +error.catalog.errorDefinitionDir=./../../../application/src/test/resources/ + +# Python executor +blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints +blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints + +#Workflow Audit store enable +blueprintsprocessor.workflow.self-service-api.audit.storeEnable=true -- cgit 1.2.3-korg