From c3811effed948926f8d94615df7530c99d490092 Mon Sep 17 00:00:00 2001 From: "Muthuramalingam, Brinda Santh" Date: Mon, 25 Mar 2019 17:01:08 -0400 Subject: Improve blueprint save Change-Id: Ibac2ef9cd7e217db809a6a695ea0ee39a6bd2e21 Issue-ID: CCSDK-1137 Signed-off-by: Muthuramalingam, Brinda Santh --- .../core/FileExtensionFunctions.kt | 8 + .../core/config/BluePrintLoadConfiguration.kt | 7 +- .../core/interfaces/BluePrintCatalogService.kt | 14 +- .../db/resources/BlueprintCatalogServiceImpl.kt | 65 ++++---- .../service/load/BluePrintCatalogLoadService.kt | 69 +++++++++ .../ControllerBluePrintCoreConfiguration.kt | 4 +- .../service/controller/BlueprintModelController.kt | 5 +- .../service/handler/BluePrintModelHandler.kt | 57 +++---- .../service/load/BluePrintCatalogLoadService.kt | 3 +- .../load/ControllerBlueprintCatalogServiceImpl.kt | 24 ++- .../service/utils/BluePrintEnhancerUtils.kt | 2 +- .../controller/BlueprintModelControllerTest.kt | 165 ++++++++++++--------- .../src/test/resources/application.properties | 2 +- 13 files changed, 275 insertions(+), 150 deletions(-) create mode 100644 ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/service/load/BluePrintCatalogLoadService.kt (limited to 'ms/controllerblueprints/modules') diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/FileExtensionFunctions.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/FileExtensionFunctions.kt index 6744b625e..bda60ea73 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/FileExtensionFunctions.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/FileExtensionFunctions.kt @@ -84,6 +84,14 @@ fun normalizedPathName(path: String, vararg more: String?): String { return normalizedPath(path, *more).toString() } +suspend fun File.reCreateNBDirs(): File = withContext(Dispatchers.IO) { + reCreateDirs() +} + +suspend fun deleteNBDir(path: String, vararg more: String?) = withContext(Dispatchers.IO) { + normalizedFile(path, *more).deleteRecursively() +} + suspend fun File.readNBText(): String = withContext(Dispatchers.IO) { readText(Charset.defaultCharset()) } diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/config/BluePrintLoadConfiguration.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/config/BluePrintLoadConfiguration.kt index 2815bad4c..8674c4d40 100644 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/config/BluePrintLoadConfiguration.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/config/BluePrintLoadConfiguration.kt @@ -16,12 +16,15 @@ package org.onap.ccsdk.cds.controllerblueprints.core.config -open class BluePrintLoadConfiguration { +open class BluePrintPathConfiguration { lateinit var blueprintDeployPath: String lateinit var blueprintArchivePath: String - lateinit var blueprintEnrichmentPath: String + lateinit var blueprintWorkingPath: String +} + +open class BluePrintLoadConfiguration : BluePrintPathConfiguration() { var loadInitialData: Boolean = false var loadBluePrint: Boolean = false var loadBluePrintPaths: String? = null diff --git a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintCatalogService.kt b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintCatalogService.kt index d71569ea2..9b4f6b56e 100755 --- a/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintCatalogService.kt +++ b/ms/controllerblueprints/modules/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/interfaces/BluePrintCatalogService.kt @@ -16,8 +16,6 @@ package org.onap.ccsdk.cds.controllerblueprints.core.interfaces -import org.jetbrains.annotations.NotNull -import org.jetbrains.annotations.Nullable import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException import java.io.File import java.nio.file.Path @@ -26,14 +24,14 @@ interface BluePrintCatalogService { /** * Save the CBA to database. + * @param processingId Processing Id * @param blueprintFile Either a directory, or an archive * @param validate whether to validate blueprint content. Default true. * @return The unique blueprint identifier * @throws BluePrintException if process failed */ - @NotNull @Throws(BluePrintException::class) - fun saveToDatabase(@NotNull blueprintFile: File, @Nullable validate: Boolean = true): String + suspend fun saveToDatabase(processingId: String, blueprintFile: File, validate: Boolean = true): String /** * Retrieve the CBA from database either archived or extracted. @@ -43,9 +41,9 @@ interface BluePrintCatalogService { * @return Path where CBA is located * @throws BluePrintException if process failed */ - @NotNull + @Throws(BluePrintException::class) - fun getFromDatabase(@NotNull name: String, @NotNull version: String, @Nullable extract: Boolean = true): Path + suspend fun getFromDatabase(name: String, version: String, extract: Boolean = true): Path /** * Delete the CBA from database. @@ -53,7 +51,7 @@ interface BluePrintCatalogService { * @param version Version of the blueprint * @throws BluePrintException if process failed */ - @NotNull + @Throws(BluePrintException::class) - fun deleteFromDatabase(@NotNull name: String, @NotNull version: String) + suspend fun deleteFromDatabase(name: String, version: String) } \ No newline at end of file diff --git a/ms/controllerblueprints/modules/db-resources/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/db/resources/BlueprintCatalogServiceImpl.kt b/ms/controllerblueprints/modules/db-resources/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/db/resources/BlueprintCatalogServiceImpl.kt index 3be56480f..9780bbd31 100644 --- a/ms/controllerblueprints/modules/db-resources/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/db/resources/BlueprintCatalogServiceImpl.kt +++ b/ms/controllerblueprints/modules/db-resources/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/db/resources/BlueprintCatalogServiceImpl.kt @@ -18,69 +18,70 @@ package org.onap.ccsdk.cds.controllerblueprints.db.resources -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.* +import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintPathConfiguration import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintValidatorService import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils -import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils +import org.slf4j.LoggerFactory import java.io.File import java.nio.file.Path -import java.util.* import javax.persistence.MappedSuperclass @MappedSuperclass -abstract class BlueprintCatalogServiceImpl(private val blueprintValidator: BluePrintValidatorService) - : BluePrintCatalogService { +abstract class BlueprintCatalogServiceImpl( + private val bluePrintPathConfiguration: BluePrintPathConfiguration, + private val blueprintValidator: BluePrintValidatorService) : BluePrintCatalogService { - override fun saveToDatabase(blueprintFile: File, validate: Boolean): String { - val extractedDirectory: File - val archivedDirectory: File - val toDeleteDirectory: File - val blueprintId = UUID.randomUUID().toString() + private val log = LoggerFactory.getLogger(BlueprintCatalogServiceImpl::class.java)!! + + override suspend fun saveToDatabase(processingId: String, blueprintFile: File, validate: Boolean): String { + + var archiveFile: File? = null + var workingDir: String? = null if (blueprintFile.isDirectory) { - extractedDirectory = blueprintFile - archivedDirectory = File("$blueprintFile.zip") - toDeleteDirectory = archivedDirectory + log.info("Save processing($processingId) Working Dir(${blueprintFile.absolutePath})") + workingDir = blueprintFile.absolutePath + archiveFile = normalizedFile(bluePrintPathConfiguration.blueprintArchivePath, processingId, "cba.zip") - if (!BluePrintArchiveUtils.compress(blueprintFile, archivedDirectory, true)) { + if (!BluePrintArchiveUtils.compress(blueprintFile, archiveFile, true)) { throw BluePrintException("Fail to compress blueprint") } } else { - val targetDir = "${blueprintFile.parent}/${BluePrintFileUtils.stripFileExtension(blueprintFile.name)}" - - extractedDirectory = BluePrintArchiveUtils.deCompress(blueprintFile, targetDir) - archivedDirectory = blueprintFile - toDeleteDirectory = extractedDirectory + // Compressed File + log.info("Save processing($processingId) CBA(${blueprintFile.absolutePath})") + workingDir = normalizedPathName(bluePrintPathConfiguration.blueprintWorkingPath, processingId) + archiveFile = blueprintFile + // Decompress the CBA file to working Directory + blueprintFile.deCompress(workingDir) } var valid = BluePrintConstants.FLAG_N if (validate) { - blueprintValidator.validateBluePrints(extractedDirectory.path) + blueprintValidator.validateBluePrints(workingDir!!) valid = BluePrintConstants.FLAG_Y } - val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(blueprintId, extractedDirectory.path) + val bluePrintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(processingId, workingDir!!) val metadata = bluePrintRuntimeService.bluePrintContext().metadata!! - metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] = blueprintId + metadata[BluePrintConstants.PROPERTY_BLUEPRINT_PROCESS_ID] = processingId metadata[BluePrintConstants.PROPERTY_BLUEPRINT_VALID] = valid - save(metadata, archivedDirectory) - - toDeleteDirectory.deleteRecursively() + save(metadata, archiveFile) - return blueprintId + return processingId } - override fun getFromDatabase(name: String, version: String, extract: Boolean): Path = get(name, version, extract) + override suspend fun getFromDatabase(name: String, version: String, extract: Boolean): Path = get(name, version, + extract) ?: throw BluePrintException("Could not find blueprint $name:$version from database") - override fun deleteFromDatabase(name: String, version: String) = delete(name, version) + override suspend fun deleteFromDatabase(name: String, version: String) = delete(name, version) - abstract fun save(metadata: MutableMap, archiveFile: File) - abstract fun get(name: String, version: String, extract: Boolean): Path? - abstract fun delete(name: String, version: String) + abstract suspend fun save(metadata: MutableMap, archiveFile: File) + abstract suspend fun get(name: String, version: String, extract: Boolean): Path? + abstract suspend fun delete(name: String, version: String) } \ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/service/load/BluePrintCatalogLoadService.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/service/load/BluePrintCatalogLoadService.kt new file mode 100644 index 000000000..0ae618f3a --- /dev/null +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/apps/controllerblueprints/service/load/BluePrintCatalogLoadService.kt @@ -0,0 +1,69 @@ +/* + * Copyright © 2017-2018 AT&T Intellectual Property. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.apps.controllerblueprints.service.load + +import com.att.eelf.configuration.EELFManager +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.async +import kotlinx.coroutines.runBlocking +import org.apache.commons.lang3.text.StrBuilder +import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService +import org.springframework.stereotype.Service +import java.io.File +import java.util.* + +@Service +open class BluePrintCatalogLoadService(private val bluePrintCatalogService: BluePrintCatalogService) { + + private val log = EELFManager.getInstance().getLogger(BluePrintCatalogLoadService::class.java) + + open fun loadPathsBluePrintModelCatalog(paths: List) { + paths.forEach { loadPathBluePrintModelCatalog(it) } + } + + open fun loadPathBluePrintModelCatalog(path: String) { + + val files = File(path).listFiles() + runBlocking { + val errorBuilder = StrBuilder() + val deferredResults = mutableListOf>() + + for (file in files) { + deferredResults += async { + loadBluePrintModelCatalog(errorBuilder, file) + } + } + + for (deferredResult in deferredResults) { + deferredResult.await() + } + + if (!errorBuilder.isEmpty) { + log.error(errorBuilder.toString()) + } + } + } + + open suspend fun loadBluePrintModelCatalog(errorBuilder: StrBuilder, file: File) { + try { + bluePrintCatalogService.saveToDatabase(UUID.randomUUID().toString(), file) + } catch (e: Exception) { + errorBuilder.appendln("Couldn't load BlueprintModel(${file.name}: ${e.message}") + } + } + +} \ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/ControllerBluePrintCoreConfiguration.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/ControllerBluePrintCoreConfiguration.kt index 8a7c01851..790c61ebc 100644 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/ControllerBluePrintCoreConfiguration.kt +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/ControllerBluePrintCoreConfiguration.kt @@ -34,7 +34,7 @@ open class ControllerBluePrintCoreConfiguration(private val bluePrintProperties: } @Bean - open fun controlelrBlueprintLoadConfiguration(): BluePrintLoadConfiguration { + open fun bluePrintLoadConfiguration(): BluePrintLoadConfiguration { return bluePrintProperties .propertyBeanType(PREFIX_BLUEPRINT_LOAD_CONFIGURATION, BluePrintLoadConfiguration::class.java) } @@ -53,7 +53,7 @@ open class ControllerBlueprintPropertyConfiguration { } @Service -open class ControllerBlueprintProperties(var bluePrintPropertyBinder: Binder) { +open class ControllerBlueprintProperties(private var bluePrintPropertyBinder: Binder) { fun propertyBeanType(prefix: String, type: Class): T { return bluePrintPropertyBinder.bind(prefix, Bindable.of(type)).get() } diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelController.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelController.kt index 0ea753fd1..a214f961e 100644 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelController.kt +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelController.kt @@ -26,7 +26,6 @@ import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.http.codec.multipart.FilePart import org.springframework.web.bind.annotation.* -import reactor.core.publisher.Mono /** * BlueprintModelController Purpose: Handle controllerBlueprint API request @@ -41,8 +40,8 @@ open class BlueprintModelController(private val bluePrintModelHandler: BluePrint @PostMapping("", produces = [MediaType.APPLICATION_JSON_VALUE], consumes = [MediaType.MULTIPART_FORM_DATA_VALUE]) @ResponseBody @Throws(BluePrintException::class) - fun saveBlueprint(@RequestPart("file") file: FilePart): Mono { - return bluePrintModelHandler.saveBlueprintModel(file) + fun saveBlueprint(@RequestPart("file") filePart: FilePart): BlueprintModelSearch = runBlocking { + bluePrintModelHandler.saveBlueprintModel(filePart) } @GetMapping("", produces = [MediaType.APPLICATION_JSON_VALUE]) diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/handler/BluePrintModelHandler.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/handler/BluePrintModelHandler.kt index 72c27adc1..c54bf87fe 100644 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/handler/BluePrintModelHandler.kt +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/handler/BluePrintModelHandler.kt @@ -18,19 +18,18 @@ package org.onap.ccsdk.cds.controllerblueprints.service.handler -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.* import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName -import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModel import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModelSearch import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelContentRepository import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelRepository import org.onap.ccsdk.cds.controllerblueprints.service.repository.ControllerBlueprintModelSearchRepository import org.onap.ccsdk.cds.controllerblueprints.service.utils.BluePrintEnhancerUtils +import org.slf4j.LoggerFactory import org.springframework.core.io.ByteArrayResource import org.springframework.core.io.Resource import org.springframework.http.HttpHeaders @@ -39,7 +38,6 @@ import org.springframework.http.ResponseEntity import org.springframework.http.codec.multipart.FilePart import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional -import reactor.core.publisher.Mono import java.io.File import java.io.IOException import java.util.* @@ -59,6 +57,8 @@ open class BluePrintModelHandler(private val bluePrintCatalogService: BluePrintC private val blueprintModelContentRepository: ControllerBlueprintModelContentRepository, private val bluePrintEnhancerService: BluePrintEnhancerService) { + private val log = LoggerFactory.getLogger(BluePrintModelHandler::class.java)!! + /** * This is a getAllBlueprintModel method to retrieve all the BlueprintModel in Database * @@ -76,23 +76,28 @@ open class BluePrintModelHandler(private val bluePrintCatalogService: BluePrintC * @throws BluePrintException BluePrintException */ @Throws(BluePrintException::class) - open fun saveBlueprintModel(filePart: FilePart): Mono { + open suspend fun saveBlueprintModel(filePart: FilePart): BlueprintModelSearch { + val saveId = UUID.randomUUID().toString() + val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, saveId) try { - val cbaLocation = BluePrintFileUtils.getCbaStorageDirectory(bluePrintLoadConfiguration.blueprintArchivePath) - return BluePrintEnhancerUtils.saveCBAFile(filePart, cbaLocation).map { fileName -> - var blueprintId: String? = null - try { - blueprintId = bluePrintCatalogService.saveToDatabase(cbaLocation.resolve(fileName).toFile(), false) - } catch (e: BluePrintException) { - // FIXME handle expection - } - blueprintModelSearchRepository.findById(blueprintId!!).get() - } + //Recreate the Dir + normalizedFile(bluePrintLoadConfiguration.blueprintArchivePath, saveId).reCreateDirs() + val deCompressedFile = normalizedFile(blueprintArchive, "cba.zip") + // Copy the File Part to Local File + BluePrintEnhancerUtils.copyFromFilePart(filePart, deCompressedFile) + // Save the Copied file to Database + val blueprintId = bluePrintCatalogService.saveToDatabase(saveId, deCompressedFile, false) + // Check and Return the Saved File + val blueprintModelSearch = blueprintModelSearchRepository.findById(blueprintId).get() + log.info("Save($saveId) successful for blueprint(${blueprintModelSearch.artifactName}) " + + "version(${blueprintModelSearch.artifactVersion})") + return blueprintModelSearch } catch (e: IOException) { throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value, - String.format("I/O Error while uploading the CBA file: %s", e.message), e) + "Error in Save CBA: ${e.message}", e) + } finally { + deleteDir(blueprintArchive) } - } @@ -277,20 +282,20 @@ open class BluePrintModelHandler(private val bluePrintCatalogService: BluePrintC open suspend fun enrichBlueprint(filePart: FilePart): ResponseEntity { val enhanceId = UUID.randomUUID().toString() val blueprintArchive = normalizedPathName(bluePrintLoadConfiguration.blueprintArchivePath, enhanceId) - val blueprintEnrichmentDir = normalizedPathName(bluePrintLoadConfiguration.blueprintEnrichmentPath, enhanceId) + val blueprintWorkingDir = normalizedPathName(bluePrintLoadConfiguration.blueprintWorkingPath, enhanceId) try { - BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchive, blueprintEnrichmentDir) + BluePrintEnhancerUtils.decompressFilePart(filePart, blueprintArchive, blueprintWorkingDir) // Enhance the Blue Prints - bluePrintEnhancerService.enhance(blueprintEnrichmentDir) + bluePrintEnhancerService.enhance(blueprintWorkingDir) - return BluePrintEnhancerUtils.compressToFilePart(blueprintEnrichmentDir, blueprintArchive) + return BluePrintEnhancerUtils.compressToFilePart(blueprintWorkingDir, blueprintArchive) } catch (e: IOException) { throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value, "Error in Enriching CBA: ${e.message}", e) } finally { - BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintEnrichmentDir) + BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir) } } @@ -305,12 +310,12 @@ open class BluePrintModelHandler(private val bluePrintCatalogService: BluePrintC open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch { val publishId = UUID.randomUUID().toString() val blueprintArchive = bluePrintLoadConfiguration.blueprintArchivePath.plus(File.separator).plus(publishId) - val blueprintEnrichmentDir = bluePrintLoadConfiguration.blueprintEnrichmentPath.plus(File.separator).plus(publishId) + val blueprintWorkingDir = bluePrintLoadConfiguration.blueprintWorkingPath.plus(File.separator).plus(publishId) try { val compressedFilePart = BluePrintEnhancerUtils - .extractCompressFilePart(filePart, blueprintArchive, blueprintEnrichmentDir) + .extractCompressFilePart(filePart, blueprintArchive, blueprintWorkingDir) - val blueprintId = bluePrintCatalogService.saveToDatabase(compressedFilePart, true) + val blueprintId = bluePrintCatalogService.saveToDatabase(publishId, compressedFilePart, true) return blueprintModelSearchRepository.findById(blueprintId).get() @@ -318,7 +323,7 @@ open class BluePrintModelHandler(private val bluePrintCatalogService: BluePrintC throw BluePrintException(ErrorCode.IO_FILE_INTERRUPT.value, "Error in Publishing CBA: ${e.message}", e) } finally { - BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintEnrichmentDir) + BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir) } } diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt index eca7ce1bf..2278d8019 100644 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/BluePrintCatalogLoadService.kt @@ -22,6 +22,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogS import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile import org.springframework.stereotype.Service import java.io.File +import java.util.* @Service open class BluePrintCatalogLoadService(private val bluePrintCatalogService: BluePrintCatalogService) { @@ -47,7 +48,7 @@ open class BluePrintCatalogLoadService(private val bluePrintCatalogService: Blue open suspend fun loadBluePrintModelCatalog(errorBuilder: MutableList, file: File) { try { log.info("loading blueprint cba(${file.absolutePath})") - bluePrintCatalogService.saveToDatabase(file) + bluePrintCatalogService.saveToDatabase(UUID.randomUUID().toString(), file) } catch (e: Exception) { errorBuilder.add("Couldn't load BlueprintModel(${file.name}: ${e.message}") } diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt index 358a4654a..3d6e134d4 100755 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/load/ControllerBlueprintCatalogServiceImpl.kt @@ -23,7 +23,9 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode +import org.onap.ccsdk.cds.controllerblueprints.core.deleteDir import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintValidatorService +import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPath import org.onap.ccsdk.cds.controllerblueprints.db.resources.BlueprintCatalogServiceImpl import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModel import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModelContent @@ -34,7 +36,7 @@ import org.springframework.stereotype.Service import java.io.File import java.nio.file.Files import java.nio.file.Path -import java.nio.file.Paths +import java.util.* /** * Similar implementation in [org.onap.ccsdk.cds.blueprintsprocessor.db.BlueprintProcessorCatalogServiceImpl] @@ -43,7 +45,7 @@ import java.nio.file.Paths class ControllerBlueprintCatalogServiceImpl(bluePrintValidatorService: BluePrintValidatorService, private val bluePrintLoadConfiguration: BluePrintLoadConfiguration, private val blueprintModelRepository: ControllerBlueprintModelRepository) - : BlueprintCatalogServiceImpl(bluePrintValidatorService) { + : BlueprintCatalogServiceImpl(bluePrintLoadConfiguration, bluePrintValidatorService) { private val log = LoggerFactory.getLogger(ControllerBlueprintCatalogServiceImpl::class.toString()) @@ -52,13 +54,18 @@ class ControllerBlueprintCatalogServiceImpl(bluePrintValidatorService: BluePrint log.info("BlueprintProcessorCatalogServiceImpl initialized") } - override fun delete(name: String, version: String) = blueprintModelRepository.deleteByArtifactNameAndArtifactVersion(name, version) + override suspend fun delete(name: String, version: String) { + // Cleaning Deployed Blueprint + deleteDir(bluePrintLoadConfiguration.blueprintDeployPath, name, version) + // Cleaning Data Base + blueprintModelRepository.deleteByArtifactNameAndArtifactVersion(name, version) + } - override fun get(name: String, version: String, extract: Boolean): Path? { + override suspend fun get(name: String, version: String, extract: Boolean): Path? { val path = if (extract) { - Paths.get("${bluePrintLoadConfiguration.blueprintDeployPath}/$name/$version") + normalizedPath(bluePrintLoadConfiguration.blueprintDeployPath, name, version) } else { - Paths.get("${bluePrintLoadConfiguration.blueprintArchivePath}/$name/$version.zip") + normalizedPath(bluePrintLoadConfiguration.blueprintArchivePath, UUID.randomUUID().toString(), "cba.zip") } blueprintModelRepository.findByArtifactNameAndArtifactVersion(name, version)?.also { it.blueprintModelContent.run { @@ -70,11 +77,14 @@ class ControllerBlueprintCatalogServiceImpl(bluePrintValidatorService: BluePrint return null } - override fun save(metadata: MutableMap, archiveFile: File) { + override suspend fun save(metadata: MutableMap, archiveFile: File) { val artifactName = metadata[BluePrintConstants.METADATA_TEMPLATE_NAME] val artifactVersion = metadata[BluePrintConstants.METADATA_TEMPLATE_VERSION] + check(archiveFile.isFile && !archiveFile.isDirectory) { + throw BluePrintException("Not a valid Archive file(${archiveFile.absolutePath})") + } blueprintModelRepository.findByArtifactNameAndArtifactVersion(artifactName!!, artifactVersion!!)?.let { log.info("Overwriting blueprint model :$artifactName::$artifactVersion") diff --git a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/utils/BluePrintEnhancerUtils.kt b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/utils/BluePrintEnhancerUtils.kt index 166a2b283..d4753e194 100644 --- a/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/utils/BluePrintEnhancerUtils.kt +++ b/ms/controllerblueprints/modules/service/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/utils/BluePrintEnhancerUtils.kt @@ -84,7 +84,7 @@ class BluePrintEnhancerUtils { return artifactType } - private suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File { + suspend fun copyFromFilePart(filePart: FilePart, targetFile: File): File { // Delete the Directory targetFile.deleteRecursively() return filePart.transferTo(targetFile) diff --git a/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelControllerTest.kt b/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelControllerTest.kt index d61e64251..64bd3ff3e 100644 --- a/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelControllerTest.kt +++ b/ms/controllerblueprints/modules/service/src/test/kotlin/org/onap/ccsdk/cds/controllerblueprints/service/controller/BlueprintModelControllerTest.kt @@ -17,9 +17,9 @@ package org.onap.ccsdk.cds.controllerblueprints.service.controller -import com.google.gson.Gson +import kotlinx.coroutines.reactive.awaitSingle +import kotlinx.coroutines.runBlocking import org.json.JSONException -import org.json.JSONObject import org.junit.After import org.junit.Before import org.junit.FixMethodOrder @@ -27,26 +27,31 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.MethodSorters import org.onap.ccsdk.cds.controllerblueprints.TestApplication -import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintArchiveUtils +import org.onap.ccsdk.cds.controllerblueprints.core.* +import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintPathConfiguration +import org.onap.ccsdk.cds.controllerblueprints.service.ControllerBluePrintCoreConfiguration import org.onap.ccsdk.cds.controllerblueprints.service.domain.BlueprintModelSearch +import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Value import org.springframework.boot.autoconfigure.EnableAutoConfiguration import org.springframework.boot.test.context.SpringBootTest import org.springframework.context.annotation.ComponentScan import org.springframework.core.io.ByteArrayResource import org.springframework.http.HttpMethod import org.springframework.http.HttpStatus +import org.springframework.http.client.MultipartBodyBuilder import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.junit4.SpringRunner import org.springframework.test.web.reactive.server.WebTestClient +import org.springframework.test.web.reactive.server.returnResult import org.springframework.util.Base64Utils import org.springframework.web.reactive.function.BodyInserters import java.io.File -import java.io.IOException import java.nio.charset.StandardCharsets.UTF_8 -import java.nio.file.Files import java.nio.file.Paths +import kotlin.test.assertEquals +import kotlin.test.assertNotNull +import kotlin.test.assertTrue /** * BlueprintModelControllerTest Purpose: Integration test at API level @@ -57,109 +62,142 @@ import java.nio.file.Paths @RunWith(SpringRunner::class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@ContextConfiguration(classes = [TestApplication::class]) +@ContextConfiguration(classes = [TestApplication::class, ControllerBluePrintCoreConfiguration::class]) @ComponentScan(basePackages = ["org.onap.ccsdk.cds.controllerblueprints"]) @FixMethodOrder(MethodSorters.NAME_ASCENDING) @EnableAutoConfiguration class BlueprintModelControllerTest { - companion object { + private val log = LoggerFactory.getLogger(BlueprintModelControllerTest::class.java)!! - private var id: String? = null - private var name: String? = null - private var version: String? = null - private var tag: String? = null - private var result: String? = null + companion object { + private var bp: BlueprintModelSearch? = null } - @Value("\${controllerblueprints.loadBluePrintPaths}") - private val loadBluePrintPaths: String? = null - @Autowired - private val webTestClient: WebTestClient? = null + lateinit var webTestClient: WebTestClient + + private var bluePrintLoadConfiguration: BluePrintPathConfiguration? = null - @Value("\${controllerblueprints.loadBlueprintsExamplesPath}") - private val blueprintArchivePath: String? = null + private val blueprintDir = "./../../../../components/model-catalog/blueprint-model/test-blueprint/baseconfiguration" + private var zipBlueprintFileName: String? = null + + private var testZipFile: File? = null - private val filename = "test.zip" - private var blueprintFile: File? = null - private var zipBlueprintFile: File? = null @Before - @Throws(Exception::class) fun setUp() { - blueprintFile = File(loadBluePrintPaths+"/baseconfiguration") - if (blueprintFile!!.isDirectory) { - zipBlueprintFile = File(Paths.get(blueprintArchivePath).resolve(filename).toString()) - BluePrintArchiveUtils.compress(blueprintFile!!, zipBlueprintFile!!, true) + assertNotNull(webTestClient, " Failed to create WebTestClient") + + bluePrintLoadConfiguration = BluePrintPathConfiguration().apply { + blueprintArchivePath = "./target/blueprints/archive" + blueprintWorkingPath = "./target/blueprints/work" + blueprintDeployPath = "./target/blueprints/deploy" } + zipBlueprintFileName = normalizedPathName(bluePrintLoadConfiguration!!.blueprintArchivePath, "test.zip") + + val archiveDir = normalizedFile(bluePrintLoadConfiguration!!.blueprintArchivePath).reCreateDirs() + assertTrue(archiveDir.exists(), "failed to create archiveDir(${archiveDir.absolutePath}") + + val blueprintFile = Paths.get(blueprintDir).toFile().normalize() + testZipFile = blueprintFile.compress(zipBlueprintFileName!!) + assertNotNull(testZipFile, "test zip is null") + assertTrue(testZipFile!!.exists(), "Failed to create blueprint test zip(${testZipFile!!.absolutePath}") } @After - @Throws(Exception::class) fun tearDown() { - zipBlueprintFile!!.delete() + deleteDir(bluePrintLoadConfiguration!!.blueprintArchivePath) + deleteDir(bluePrintLoadConfiguration!!.blueprintWorkingPath) } @Test - @Throws(IOException::class, JSONException::class) - fun test1_saveBluePrint() { - webTestClient(HttpMethod.POST, - BodyInserters.fromMultipartData("file", object : ByteArrayResource(Files.readAllBytes(zipBlueprintFile!!.toPath())) { - override fun getFilename(): String? { + fun test01_saveBluePrint() { + bp = runBlocking { + val body = MultipartBodyBuilder().apply { + part("file", object : ByteArrayResource(testZipFile!!.readBytes()) { + override fun getFilename(): String { return "test.zip" } - }), - "/api/v1/blueprint-model", - HttpStatus.OK, true) + }) + }.build() + + val saveBP = webTestClient + .post() + .uri("/api/v1/blueprint-model") + .body(BodyInserters.fromMultipartData(body)) + .exchange() + .expectStatus().isOk + .returnResult() + .responseBody + .awaitSingle() + + assertNotNull(saveBP, "failed to get response") + assertEquals("baseconfiguration", saveBP.artifactName, "mismatch artifact name") + assertEquals("1.0.0", saveBP.artifactVersion, "mismatch artifact version") + assertEquals("N", saveBP.published, "mismatch publish") + saveBP + } } @Test @Throws(JSONException::class) - fun test2_getBluePrintByNameAndVersion() { - webTestClient(HttpMethod.GET, null, "/api/v1/blueprint-model/by-name/$name/version/$version", HttpStatus.OK, false) + fun test02_getBluePrintByNameAndVersion() { + webTestClient(HttpMethod.GET, null, + "/api/v1/blueprint-model/by-name/${bp!!.artifactName}/version/${bp!!.artifactVersion}", + HttpStatus.OK, false) } @Test @Throws(JSONException::class) - fun test3_getBlueprintModel() { - webTestClient(HttpMethod.GET, null, "/api/v1/blueprint-model/$id", HttpStatus.OK, false) + fun test03_getBlueprintModel() { + webTestClient(HttpMethod.GET, null, + "/api/v1/blueprint-model/${bp!!.id}", + HttpStatus.OK, false) } @Test @Throws(JSONException::class) - fun test4_getAllBlueprintModel() { + fun test04_getAllBlueprintModel() { webTestClient(HttpMethod.GET, null, "/api/v1/blueprint-model", HttpStatus.OK, false) } @Test @Throws(JSONException::class) - fun test5_downloadBluePrint() { - webTestClient(HttpMethod.GET, null, "/api/v1/blueprint-model/download/$id", HttpStatus.OK, false) + fun test05_downloadBluePrint() { + webTestClient(HttpMethod.GET, null, + "/api/v1/blueprint-model/download/${bp!!.id}", + HttpStatus.OK, false) + } + + @Test + fun test06_enrichBlueprintModel() { } @Test - fun test6_publishBlueprintModel() { + fun test07_publishBlueprintModel() { } @Test @Throws(JSONException::class) - fun test7_searchBlueprintModels() { - webTestClient(HttpMethod.GET, null, "/api/v1/blueprint-model/search/$name", HttpStatus.OK, false) + fun test08_searchBlueprintModels() { + webTestClient(HttpMethod.GET, null, + "/api/v1/blueprint-model/search/${bp!!.artifactName}", + HttpStatus.OK, false) } @Test @Throws(JSONException::class) - fun test8_downloadBlueprintByNameAndVersion() { - webTestClient(HttpMethod.GET, null, "/api/v1/blueprint-model/download/by-name/$name/version/$version", HttpStatus.OK, false) + fun test09_downloadBlueprintByNameAndVersion() { + webTestClient(HttpMethod.GET, null, + "/api/v1/blueprint-model/download/by-name/${bp!!.artifactName}/version/${bp!!.artifactVersion}", + HttpStatus.OK, false) } @Test - fun test9_deleteBluePrint() { - //TODO: Use webTestClient function - //webTestClient(HttpMethod.DELETE, null, "/api/v1/blueprint-model/" + id, HttpStatus.OK, false); - webTestClient!!.delete().uri("/api/v1/blueprint-model/$id") + fun test10_deleteBluePrint() { + webTestClient.delete().uri("/api/v1/blueprint-model/${bp!!.id}") .header("Authorization", "Basic " + Base64Utils .encodeToString(("ccsdkapps" + ":" + "ccsdkapps").toByteArray(UTF_8))) .exchange() @@ -167,27 +205,20 @@ class BlueprintModelControllerTest { } @Throws(JSONException::class) - private fun webTestClient(requestMethod: HttpMethod, body: BodyInserters.MultipartInserter?, uri: String, expectedResponceStatus: HttpStatus, setParam: Boolean) { + private fun webTestClient(requestMethod: HttpMethod, body: BodyInserters.MultipartInserter?, uri: String, + expectedResponceStatus: HttpStatus, setParam: Boolean) { - result = String(webTestClient!!.method(requestMethod).uri(uri) + log.info("Requesting($uri): Method(${requestMethod.name})") + + webTestClient.method(requestMethod).uri(uri) .header("Authorization", "Basic " + Base64Utils .encodeToString(("ccsdkapps" + ":" + "ccsdkapps").toByteArray(UTF_8))) .body(body) .exchange() .expectStatus().isEqualTo(expectedResponceStatus) .expectBody() - .returnResult().responseBody!!) - - if (setParam) { - val jsonResponse = JSONObject(result) - val blueprintModelSearchJSON = jsonResponse.getJSONObject("blueprintModel") - val gson = Gson() - val blueprintModelSearch = gson.fromJson(blueprintModelSearchJSON.toString(), BlueprintModelSearch::class.java) - id = blueprintModelSearch.id - name = blueprintModelSearch.artifactName - version = blueprintModelSearch.artifactVersion - tag = blueprintModelSearch.tags - } + .returnResult().responseBody!! + } } \ No newline at end of file diff --git a/ms/controllerblueprints/modules/service/src/test/resources/application.properties b/ms/controllerblueprints/modules/service/src/test/resources/application.properties index 011bad32c..19430ad08 100755 --- a/ms/controllerblueprints/modules/service/src/test/resources/application.properties +++ b/ms/controllerblueprints/modules/service/src/test/resources/application.properties @@ -24,7 +24,7 @@ resourceSourceMappings=processor-db=source-processor-db,input=source-input,defau # Controller Blueprints Core Configuration controllerblueprints.blueprintDeployPath=./target/blueprints/deploy controllerblueprints.blueprintArchivePath=./target/blueprints/archive -controllerblueprints.blueprintEnrichmentPath=./target/blueprints/enrichment +controllerblueprints.blueprintWorkingPath=./target/blueprints/work # Controller Blueprint Load Configurations controllerblueprints.loadInitialData=false controllerblueprints.loadBluePrint=false -- cgit 1.2.3-korg