2  * ============LICENSE_START=======================================================
 
   3  *  Copyright (C) 2019 Nordix Foundation.
 
   4  *  Modifications Copyright © 2023 Deutche Telekom AG
 
   5  * ================================================================================
 
   6  * Licensed under the Apache License, Version 2.0 (the "License");
 
   7  * you may not use this file except in compliance with the License.
 
   8  * You may obtain a copy of the License at
 
  10  *      http://www.apache.org/licenses/LICENSE-2.0
 
  12  * Unless required by applicable law or agreed to in writing, software
 
  13  * distributed under the License is distributed on an "AS IS" BASIS,
 
  14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  15  * See the License for the specific language governing permissions and
 
  16  * limitations under the License.
 
  18  * SPDX-License-Identifier: Apache-2.0
 
  19  * ============LICENSE_END=========================================================
 
  21 package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils
 
  23 import com.fasterxml.jackson.databind.ObjectMapper
 
  24 import kotlinx.coroutines.reactor.awaitSingle
 
  25 import kotlinx.coroutines.runBlocking
 
  26 import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.COLOR_SERVICES
 
  27 import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.resetContextColor
 
  28 import org.onap.ccsdk.cds.blueprintsprocessor.uat.logging.LogColor.setContextColor
 
  29 import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.UAT_SPECIFICATION_FILE
 
  30 import org.springframework.context.annotation.Profile
 
  31 import org.springframework.http.HttpStatus
 
  32 import org.springframework.http.MediaType
 
  33 import org.springframework.http.codec.multipart.FilePart
 
  34 import org.springframework.security.access.prepost.PreAuthorize
 
  35 import org.springframework.web.bind.annotation.PostMapping
 
  36 import org.springframework.web.bind.annotation.RequestMapping
 
  37 import org.springframework.web.bind.annotation.RequestPart
 
  38 import org.springframework.web.bind.annotation.RestController
 
  39 import org.springframework.web.server.ResponseStatusException
 
  41 import java.util.zip.ZipFile
 
  44  * Supporting services to help creating UAT specifications.
 
  46  * @author Eliezio Oliveira
 
  49 @RequestMapping("/api/v1/uat")
 
  51 open class UatServices(private val uatExecutor: UatExecutor, private val mapper: ObjectMapper) {
 
  53     @PostMapping("/verify", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
 
  54     @PreAuthorize("hasRole('USER')")
 
  55     @Suppress("BlockingMethodInNonBlockingContext")
 
  56     open fun verify(@RequestPart("cba") cbaFile: FilePart) = runBlocking {
 
  57         setContextColor(COLOR_SERVICES)
 
  58         val tempFile = createTempFile()
 
  60             cbaFile.transferTo(tempFile)
 
  62                     val uatSpec = readZipEntryAsText(tempFile, UAT_SPECIFICATION_FILE)
 
  63                     val cbaBytes = tempFile.readBytes()
 
  64                     uatExecutor.execute(uatSpec, cbaBytes)
 
  66         } catch (e: AssertionError) {
 
  67             throw ResponseStatusException(HttpStatus.BAD_REQUEST, e.message)
 
  68         } catch (t: Throwable) {
 
  69             throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, t.message, t)
 
  76     @PostMapping("/spy", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE], produces = ["text/vnd.yaml"])
 
  77     @PreAuthorize("hasRole('USER')")
 
  78     @Suppress("BlockingMethodInNonBlockingContext")
 
  80         @RequestPart("cba") cbaFile: FilePart,
 
  81         @RequestPart("uat", required = false) uatFile: FilePart?
 
  82     ): String = runBlocking {
 
  83         val tempFile = createTempFile()
 
  84         val tempCbaFile = createTempFile()
 
  85         setContextColor(COLOR_SERVICES)
 
  89                     uatFile.transferTo(tempFile).thenReturn(tempFile).awaitSingle()
 
  92                 else -> readZipEntryAsText(tempFile, UAT_SPECIFICATION_FILE)
 
  94             val uat = UatDefinition.load(mapper, uatSpec)
 
  95             cbaFile.transferTo(tempCbaFile).thenReturn(tempCbaFile).awaitSingle()
 
  96             val cbaBytes = tempCbaFile.readBytes()
 
  97             val updatedUat = uatExecutor.execute(uat, cbaBytes)
 
  98             return@runBlocking updatedUat.dump(
 
 102         } catch (t: Throwable) {
 
 103             throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, t.message, t)
 
 111     @Suppress("SameParameterValue")
 
 112     private fun readZipEntryAsText(file: File, entryName: String): String {
 
 113         return ZipFile(file).use { zipFile -> zipFile.readEntryAsText(entryName) }
 
 116     private fun ZipFile.readEntryAsText(entryName: String): String {
 
 117         val zipEntry = getEntry(entryName)
 
 118         return getInputStream(zipEntry).readBytes().toString(Charsets.UTF_8)
 
 123         // Fields that can be safely ignored from BPP response, and can be omitted on the UAT specification.
 
 124         private val FIELDS_TO_EXCLUDE = listOf("timestamp")