diff options
author | gummar <raj.gumma@est.tech> | 2020-02-18 18:54:44 +0000 |
---|---|---|
committer | KAPIL SINGAL <ks220y@att.com> | 2020-02-26 15:23:42 +0000 |
commit | 94ad509756f17e79c278e3cc2f87440009125cd1 (patch) | |
tree | ccd6a842eb0fdca66689b2569cd71cb78ec81cd2 /ms | |
parent | ac31d2159014a84de91b6c7baeb29adf90284c10 (diff) |
Merge SW Upgrade Blueprint into PNF_AAI and create one UAT BP for PNF
UAT: Add support to multiple responses for a single request
Set property IN_UAT=1 during UAT execution
so blueprints can tune their settings to values more
suitable for testing (like timeouts)
Add 'times' field to specify expected number of invocations
Add UAT blueprint script for PNF SW Upgrade UC
Add current thread check for Hazelcast distributed lock
Resolve URI before returning
Issue-ID: CCSDK-2091
Change-Id: Id256bad043488f88f1b60015ebf9ade4be607fa2
Signed-off-by: gummar <raj.gumma@est.tech>
Diffstat (limited to 'ms')
8 files changed, 162 insertions, 91 deletions
diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-local.yml b/ms/blueprintsprocessor/application/src/main/resources/application-local.yml index de2cf4e52..f2843322c 100644 --- a/ms/blueprintsprocessor/application/src/main/resources/application-local.yml +++ b/ms/blueprintsprocessor/application/src/main/resources/application-local.yml @@ -38,10 +38,10 @@ blueprintsprocessor: remoteScriptCommand: enabled: true restclient: - sdncodl: + sdnc: password: Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U type: basic-auth - url: http://localhost:8282/ + url: http://localhost:8282 username: admin restconfEnabled: true controllerblueprints: diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt index aebda8c07..4e7d4ce40 100644 --- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt +++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/UatServicesTest.kt @@ -30,6 +30,8 @@ import com.github.tomakehurst.wiremock.client.WireMock.equalToJson import com.github.tomakehurst.wiremock.client.WireMock.request import com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo import com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig +import com.github.tomakehurst.wiremock.http.HttpHeader +import com.github.tomakehurst.wiremock.http.HttpHeaders import org.apache.http.HttpStatus import org.apache.http.client.methods.HttpPost import org.apache.http.entity.ContentType @@ -55,8 +57,6 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.web.server.LocalServerPort import org.springframework.core.env.ConfigurableEnvironment import org.springframework.core.env.MapPropertySource -import org.springframework.http.HttpHeaders -import org.springframework.http.MediaType import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.support.TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME import org.yaml.snakeyaml.Yaml @@ -211,7 +211,6 @@ class UatServicesTest : BaseUatTest() { service.expectations.forEach { expectation -> val request = expectation.request - val response = expectation.response // WebTestClient always use absolute path, prefixing with "/" if necessary val urlPattern = urlEqualTo(request.path.prefixIfNot("/")) val mappingBuilder: MappingBuilder = request(request.method, urlPattern) @@ -222,15 +221,19 @@ class UatServicesTest : BaseUatTest() { mappingBuilder.withRequestBody(equalToJson(mapper.writeValueAsString(request.body), true, true)) } - val responseDefinitionBuilder: ResponseDefinitionBuilder = aResponse() - .withStatus(response.status) - if (response.body != null) { - responseDefinitionBuilder.withBody(mapper.writeValueAsBytes(response.body)) - .withHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + for (response in expectation.responses) { + val responseDefinitionBuilder: ResponseDefinitionBuilder = aResponse() + .withStatus(response.status) + if (response.body != null) { + responseDefinitionBuilder.withBody(mapper.writeValueAsBytes(response.body)) + .withHeaders(HttpHeaders( + response.headers.entries.map { e -> HttpHeader(e.key, e.value) })) + } + + // TODO: MockServer verification for multiple responses should be done using Wiremock scenarios + mappingBuilder.willReturn(responseDefinitionBuilder) } - mappingBuilder.willReturn(responseDefinitionBuilder) - mockServer.stubFor(mappingBuilder) } return mockServer diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt new file mode 100644 index 000000000..4a756411f --- /dev/null +++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/InvalidUatDefinition.kt @@ -0,0 +1,22 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Nordix Foundation. + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ +package org.onap.ccsdk.cds.blueprintsprocessor.uat.utils + +class InvalidUatDefinition(message: String) : RuntimeException(message) diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt index c45ac45c6..17b79f588 100644 --- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt +++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatDefinition.kt @@ -47,18 +47,30 @@ data class RequestDefinition( ) @JsonInclude(JsonInclude.Include.NON_EMPTY) -data class ResponseDefinition(val status: Int = 200, val body: JsonNode? = null) { +data class ResponseDefinition(val status: Int = 200, val body: JsonNode? = null, val headers: Map<String, String> = mapOf("Content-Type" to "application/json")) { companion object { - val DEFAULT_RESPONSE = ResponseDefinition() + val DEFAULT_RESPONSES = listOf(ResponseDefinition()) } } @JsonInclude(JsonInclude.Include.NON_EMPTY) -data class ExpectationDefinition( +class ExpectationDefinition( val request: RequestDefinition, - val response: ResponseDefinition = ResponseDefinition.DEFAULT_RESPONSE -) + response: ResponseDefinition?, + responses: List<ResponseDefinition>? = null, + val times: String = ">= 1" +) { + val responses: List<ResponseDefinition> = resolveOneOrMany(response, responses, ResponseDefinition.DEFAULT_RESPONSES) + + companion object { + fun <T> resolveOneOrMany(one: T?, many: List<T>?, defaultMany: List<T>): List<T> = when { + many != null -> many + one != null -> listOf(one) + else -> defaultMany + } + } +} @JsonInclude(JsonInclude.Include.NON_EMPTY) data class ServiceDefinition(val selector: String, val expectations: List<ExpectationDefinition>) @@ -97,6 +109,6 @@ data class UatDefinition( companion object { fun load(mapper: ObjectMapper, spec: String): UatDefinition = - mapper.convertValue(Yaml().load(spec), UatDefinition::class.java) + mapper.convertValue(Yaml().load(spec), UatDefinition::class.java) } } diff --git a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt index a904fa9b6..d120e71d6 100644 --- a/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt +++ b/ms/blueprintsprocessor/application/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/uat/utils/UatExecutor.kt @@ -24,9 +24,10 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.nhaarman.mockitokotlin2.any import com.nhaarman.mockitokotlin2.argThat import com.nhaarman.mockitokotlin2.atLeast -import com.nhaarman.mockitokotlin2.atLeastOnce +import com.nhaarman.mockitokotlin2.atMost import com.nhaarman.mockitokotlin2.eq import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.times import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions import com.nhaarman.mockitokotlin2.whenever @@ -44,6 +45,7 @@ import org.hamcrest.CoreMatchers.equalTo import org.hamcrest.CoreMatchers.notNullValue import org.hamcrest.MatcherAssert.assertThat import org.mockito.Answers +import org.mockito.verification.VerificationMode import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService.WebClientResponse @@ -77,7 +79,8 @@ class UatExecutor( companion object { private const val NOOP_PASSWORD_PREFIX = "{noop}" - + private const val PROPERTY_IN_UAT = "IN_UAT" + private val TIMES_SPEC_REGEX = "([<>]=?)?\\s*(\\d+)".toRegex() private val log: Logger = LoggerFactory.getLogger(UatExecutor::class.java) private val mockLoggingListener = MockInvocationLogger(markerOf(COLOR_MOCKITO)) } @@ -103,23 +106,24 @@ class UatExecutor( fun execute(uat: UatDefinition, cbaBytes: ByteArray): UatDefinition { val defaultHeaders = listOf(BasicHeader(HttpHeaders.AUTHORIZATION, clientAuthToken())) val httpClient = HttpClientBuilder.create() - .setDefaultHeaders(defaultHeaders) - .build() + .setDefaultHeaders(defaultHeaders) + .build() // Only if externalServices are defined val mockInterceptor = MockPreInterceptor() // Always defined and used, whatever the case val spyInterceptor = SpyPostInterceptor(mapper) restClientFactory.setInterceptors(mockInterceptor, spyInterceptor) try { - // Configure mocked external services and save their expected requests for further validation - val requestsPerClient = uat.externalServices.associateBy( - { service -> - createRestClientMock(service.expectations).also { restClient -> - // side-effect: register restClient to override real instance - mockInterceptor.registerMock(service.selector, restClient) - } - }, - { service -> service.expectations.map { it.request } } + markUatBegin() + // Configure mocked external services and save their expectations for further validation + val expectationsPerClient = uat.externalServices.associateBy( + { service -> + createRestClientMock(service.expectations).also { restClient -> + // side-effect: register restClient to override real instance + mockInterceptor.registerMock(service.selector, restClient) + } + }, + { service -> service.expectations } ) val newProcesses = httpClient.use { client -> @@ -130,26 +134,27 @@ class UatExecutor( log.info("Executing process '${process.name}'") val responseNormalizer = JsonNormalizer.getNormalizer(mapper, process.responseNormalizerSpec) val actualResponse = processBlueprint( - client, process.request, - process.expectedResponse, responseNormalizer + client, process.request, + process.expectedResponse, responseNormalizer ) ProcessDefinition( - process.name, - process.request, - actualResponse, - process.responseNormalizerSpec + process.name, + process.request, + actualResponse, + process.responseNormalizerSpec ) } } // Validate requests to external services - for ((mockClient, requests) in requestsPerClient) { - requests.forEach { request -> - verify(mockClient, atLeastOnce()).exchangeResource( - eq(request.method), - eq(request.path), - argThat { assertJsonEquals(request.body, this) }, - argThat(RequiredMapEntriesMatcher(request.headers)) + for ((mockClient, expectations) in expectationsPerClient) { + expectations.forEach { expectation -> + val request = expectation.request + verify(mockClient, evalVerificationMode(expectation.times)).exchangeResource( + eq(request.method), + eq(request.path), + argThat { assertJsonEquals(request.body, this) }, + argThat(RequiredMapEntriesMatcher(request.headers)) ) } // Don't mind the invocations to the overloaded exchangeResource(String, String, String) @@ -158,40 +163,51 @@ class UatExecutor( } val newExternalServices = spyInterceptor.getSpies() - .map(SpyService::asServiceDefinition) + .map(SpyService::asServiceDefinition) return UatDefinition(newProcesses, newExternalServices) } finally { restClientFactory.clearInterceptors() + markUatEnd() } } + private fun markUatBegin() { + System.setProperty(PROPERTY_IN_UAT, "1") + } + + private fun markUatEnd() { + System.clearProperty(PROPERTY_IN_UAT) + } + private fun createRestClientMock(restExpectations: List<ExpectationDefinition>): BlueprintWebClientService { val restClient = mock<BlueprintWebClientService>( - defaultAnswer = Answers.RETURNS_SMART_NULLS, - // our custom verboseLogging handler - invocationListeners = arrayOf(mockLoggingListener) + defaultAnswer = Answers.RETURNS_SMART_NULLS, + // our custom verboseLogging handler + invocationListeners = arrayOf(mockLoggingListener) ) // Delegates to overloaded exchangeResource(String, String, String, Map<String, String>) whenever(restClient.exchangeResource(any(), any(), any())) - .thenAnswer { invocation -> - val method = invocation.arguments[0] as String - val path = invocation.arguments[1] as String - val request = invocation.arguments[2] as String - restClient.exchangeResource(method, path, request, emptyMap()) - } + .thenAnswer { invocation -> + val method = invocation.arguments[0] as String + val path = invocation.arguments[1] as String + val request = invocation.arguments[2] as String + restClient.exchangeResource(method, path, request, emptyMap()) + } for (expectation in restExpectations) { - whenever( - restClient.exchangeResource( - eq(expectation.request.method), - eq(expectation.request.path), - any(), - any() - ) + var stubbing = whenever( + restClient.exchangeResource( + eq(expectation.request.method), + eq(expectation.request.path), + any(), + any() + ) ) - .thenReturn(WebClientResponse(expectation.response.status, expectation.response.body.toString())) + for (response in expectation.responses) { + stubbing = stubbing.thenReturn(WebClientResponse(response.status, response.body.toString())) + } } return restClient } @@ -199,9 +215,9 @@ class UatExecutor( @Throws(AssertionError::class) private fun uploadBlueprint(client: HttpClient, cbaBytes: ByteArray) { val multipartEntity = MultipartEntityBuilder.create() - .setMode(HttpMultipartMode.BROWSER_COMPATIBLE) - .addBinaryBody("file", cbaBytes, ContentType.DEFAULT_BINARY, "cba.zip") - .build() + .setMode(HttpMultipartMode.BROWSER_COMPATIBLE) + .addBinaryBody("file", cbaBytes, ContentType.DEFAULT_BINARY, "cba.zip") + .build() val request = HttpPost("$baseUrl/api/v1/blueprint-model/publish").apply { entity = multipartEntity } @@ -236,6 +252,19 @@ class UatExecutor( return mapper.readTree(actualResponse)!! } + private fun evalVerificationMode(times: String): VerificationMode { + val matchResult = TIMES_SPEC_REGEX.matchEntire(times) ?: throw InvalidUatDefinition( + "Time specification '$times' does not follow expected format $TIMES_SPEC_REGEX") + val counter = matchResult.groups[2]!!.value.toInt() + return when (matchResult.groups[1]?.value) { + ">=" -> atLeast(counter) + ">" -> atLeast(counter + 1) + "<=" -> atMost(counter) + "<" -> atMost(counter - 1) + else -> times(counter) + } + } + @Throws(AssertionError::class) private fun assertJsonEquals(expected: JsonNode?, actual: String): Boolean { // special case @@ -249,15 +278,15 @@ class UatExecutor( } private fun localServerPort(): Int = - (environment.getProperty("local.server.port") - ?: environment.getRequiredProperty("blueprint.httpPort")).toInt() + (environment.getProperty("local.server.port") + ?: environment.getRequiredProperty("blueprint.httpPort")).toInt() private fun clientAuthToken(): String { val username = environment.getRequiredProperty("security.user.name") val password = environment.getRequiredProperty("security.user.password") val plainPassword = when { password.startsWith(NOOP_PASSWORD_PREFIX) -> password.substring( - NOOP_PASSWORD_PREFIX.length) + NOOP_PASSWORD_PREFIX.length) else -> username } return "Basic " + Base64Utils.encodeToString("$username:$plainPassword".toByteArray()) @@ -271,7 +300,7 @@ class UatExecutor( } override fun getInstance(selector: String): BlueprintWebClientService? = - mocks[selector] + mocks[selector] fun registerMock(selector: String, client: BlueprintWebClientService) { mocks[selector] = client @@ -293,7 +322,7 @@ class UatExecutor( } fun getSpies(): List<SpyService> = - spies.values.toList() + spies.values.toList() } private class SpyService( @@ -301,14 +330,14 @@ class UatExecutor( val selector: String, private val realService: BlueprintWebClientService ) : - BlueprintWebClientService by realService { + BlueprintWebClientService by realService { private val expectations: MutableList<ExpectationDefinition> = mutableListOf() override fun exchangeResource(methodType: String, path: String, request: String): WebClientResponse<String> = - exchangeResource(methodType, path, request, - DEFAULT_HEADERS - ) + exchangeResource(methodType, path, request, + DEFAULT_HEADERS + ) override fun exchangeResource( methodType: String, @@ -317,7 +346,7 @@ class UatExecutor( headers: Map<String, String> ): WebClientResponse<String> { val requestDefinition = - RequestDefinition(methodType, path, headers, toJson(request)) + RequestDefinition(methodType, path, headers, toJson(request)) val realAnswer = realService.exchangeResource(methodType, path, request, headers) val responseBody = when { // TODO: confirm if we need to normalize the response here @@ -325,12 +354,12 @@ class UatExecutor( else -> null } val responseDefinition = - ResponseDefinition(realAnswer.status, responseBody) + ResponseDefinition(realAnswer.status, responseBody) expectations.add( - ExpectationDefinition( - requestDefinition, - responseDefinition - ) + ExpectationDefinition( + requestDefinition, + responseDefinition + ) ) return realAnswer } @@ -340,7 +369,7 @@ class UatExecutor( } fun asServiceDefinition() = - ServiceDefinition(selector, expectations) + ServiceDefinition(selector, expectations) private fun toJson(str: String): JsonNode? { return when { @@ -351,8 +380,8 @@ class UatExecutor( companion object { private val DEFAULT_HEADERS = mapOf( - HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, - HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE + HttpHeaders.CONTENT_TYPE to MediaType.APPLICATION_JSON_VALUE, + HttpHeaders.ACCEPT to MediaType.APPLICATION_JSON_VALUE ) } } diff --git a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt index fc6d5a910..408eaf45b 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt +++ b/ms/blueprintsprocessor/functions/restconf-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/restconf/executor/RestconfExecutorExtensions.kt @@ -45,12 +45,12 @@ suspend fun AbstractScriptComponentFunction.restconfMountDevice( headers: Map<String, String> = mutableMapOf("Content-Type" to "application/xml") ) { - val mountUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId" + val mountUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId" log.info("sending mount request, url: $mountUrl") webClientService.exchangeResource("PUT", mountUrl, payload as String, headers) /** Check device has mounted */ - val mountCheckUrl = "restconf/operational/network-topology:network-topology/topology/topology-netconf/node/$deviceId" + val mountCheckUrl = "/restconf/operational/network-topology:network-topology/topology/topology-netconf/node/$deviceId" val expectedResult = """"netconf-node-topology:connection-status":"connected"""" val mountCheckExecutionBlock: suspend (Int) -> String = { tryCount: Int -> @@ -80,7 +80,7 @@ suspend fun AbstractScriptComponentFunction.restconfApplyDeviceConfig( ): BlueprintWebClientService.WebClientResponse<String> { log.debug("headers: $additionalHeaders") log.info("configuring device: $deviceId, Configlet: $configletToApply") - val applyConfigUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" + + val applyConfigUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/" + "$deviceId/$configletResourcePath" return webClientService.exchangeResource("PATCH", applyConfigUrl, configletToApply as String, additionalHeaders) } @@ -92,7 +92,7 @@ suspend fun AbstractScriptComponentFunction.restconfDeviceConfig( ): BlueprintWebClientService.WebClientResponse<String> { - val configPathUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/" + + val configPathUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/" + "$deviceId/$configletResourcePath" log.debug("sending GET request, url: $configPathUrl") return webClientService.exchangeResource("GET", configPathUrl, "") @@ -106,7 +106,7 @@ suspend fun AbstractScriptComponentFunction.restconfUnMountDevice( deviceId: String, payload: String ) { - val unMountUrl = "restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId" + val unMountUrl = "/restconf/config/network-topology:network-topology/topology/topology-netconf/node/$deviceId" log.info("sending unMount request, url: $unMountUrl") webClientService.exchangeResource("DELETE", unMountUrl, "") } diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt index 6be3334bb..a58c077fa 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/cluster/HazlecastClusterService.kt @@ -243,8 +243,11 @@ open class ClusterLockImpl(private val hazelcast: HazelcastInstance, private val } override suspend fun unLock() { - distributedLock.unlock() - log.trace("Cluster unlock(${name()}) successfully..") + // Added condition to avoid failures like - "Current thread is not owner of the lock!" + if (distributedLock.isLockedByCurrentThread) { + distributedLock.unlock() + log.trace("Cluster unlock(${name()}) successfully..") + } } override fun isLocked(): Boolean { diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt index 540b3d9ad..bfc0a5cd4 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/rest/service/BasicAuthRestClientService.kt @@ -20,6 +20,7 @@ import org.apache.http.message.BasicHeader import org.onap.ccsdk.cds.blueprintsprocessor.rest.BasicAuthRestClientProperties import org.springframework.http.HttpHeaders import org.springframework.http.MediaType +import java.net.URI import java.nio.charset.Charset import java.util.Base64 @@ -43,7 +44,8 @@ class BasicAuthRestClientService( } override fun host(uri: String): String { - return restClientProperties.url + uri + val uri: URI = URI.create(restClientProperties.url + uri) + return uri.resolve(uri).toString() } override fun convertToBasicHeaders(headers: Map<String, String>): |