diff options
59 files changed, 811 insertions, 737 deletions
diff --git a/cps-application/src/main/resources/application.yml b/cps-application/src/main/resources/application.yml index f61a09ba17..dd4576ec02 100644 --- a/cps-application/src/main/resources/application.yml +++ b/cps-application/src/main/resources/application.yml @@ -188,22 +188,35 @@ logging: onap: cps: INFO ncmp: - dmi: + policy-executor: + enabled: true + server: + address: "http://localhost" + port: "8785" httpclient: - data-services: + all-services: + maximumInMemorySizeInMegabytes: 16 + maximumConnectionsTotal: 100 + pendingAcquireMaxCount: 50 connectionTimeoutInSeconds: 30 readTimeoutInSeconds: 30 writeTimeoutInSeconds: 30 + dmi: + httpclient: + data-services: + maximumInMemorySizeInMegabytes: 16 maximumConnectionsTotal: 100 pendingAcquireMaxCount: 50 - maximumInMemorySizeInMegabytes: 16 - model-services: connectionTimeoutInSeconds: 30 readTimeoutInSeconds: 30 writeTimeoutInSeconds: 30 + model-services: + maximumInMemorySizeInMegabytes: 16 maximumConnectionsTotal: 100 pendingAcquireMaxCount: 50 - maximumInMemorySizeInMegabytes: 16 + connectionTimeoutInSeconds: 30 + readTimeoutInSeconds: 30 + writeTimeoutInSeconds: 30 auth: username: ${DMI_USERNAME:cpsuser} password: ${DMI_PASSWORD:cpsr0cks!} @@ -244,4 +257,4 @@ otel: exporter: otlp: traces: - protocol: ${ONAP_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL:grpc}
\ No newline at end of file + protocol: ${ONAP_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL:grpc} diff --git a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java index 11adc84a1f..183698c4f5 100644 --- a/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java +++ b/cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java @@ -165,7 +165,8 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi { } @Override - public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId(final String cmHandle) { + public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId( + final String cmHandleReference) { return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java index af5f226a4f..6a2e9a1541 100755 --- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java +++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java @@ -148,7 +148,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { * Patch resource data. * * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running") - * @param cmHandle cm handle identifier + * @param cmHandleReference cm handle or alternate identifier * @param resourceIdentifier resource identifier * @param requestBody the request body * @param contentType content type of body @@ -158,7 +158,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { @Override public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName, - final String cmHandle, + final String cmHandleReference, final String resourceIdentifier, final Object requestBody, final String contentType, @@ -168,7 +168,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { final Object responseObject = networkCmProxyFacade .writeResourceDataPassThroughRunningForCmHandle( - cmHandle, resourceIdentifier, PATCH, + cmHandleReference, resourceIdentifier, PATCH, jsonObjectMapper.asJsonString(requestBody), contentType, authorization); return ResponseEntity.ok(responseObject); } @@ -177,7 +177,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { * Create resource data for given cm-handle. * * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running") - * @param cmHandle cm handle identifier + * @param cmHandleReference cm handle or alternate identifier * @param resourceIdentifier resource identifier * @param requestBody the request body * @param contentType content type of body @@ -186,14 +186,14 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { */ @Override public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName, - final String cmHandle, + final String cmHandleReference, final String resourceIdentifier, final Object requestBody, final String contentType, final String authorization) { validateDataStore(PASSTHROUGH_RUNNING, datastoreName); - networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandle, + networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference, resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization); return new ResponseEntity<>(HttpStatus.CREATED); } @@ -202,7 +202,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { * Update resource data for given cm-handle. * * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running") - * @param cmHandle cm handle identifier + * @param cmHandleReference cm handle or alternate identifier * @param resourceIdentifier resource identifier * @param requestBody the request body * @param contentType content type of the body @@ -212,14 +212,14 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { @Override public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName, - final String cmHandle, + final String cmHandleReference, final String resourceIdentifier, final Object requestBody, final String contentType, final String authorization) { validateDataStore(PASSTHROUGH_RUNNING, datastoreName); - networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandle, + networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference, resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization); return new ResponseEntity<>(HttpStatus.OK); } @@ -228,7 +228,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { * Delete resource data for a given cm-handle. * * @param datastoreName name of the datastore (currently only supports "ncmp-datastore:passthrough-running") - * @param cmHandle cm handle identifier + * @param cmHandleReference cm handle or alternate identifier * @param resourceIdentifier resource identifier * @param contentType content type of the body * @param authorization contents of Authorization header, or null if not present @@ -236,14 +236,14 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { */ @Override public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName, - final String cmHandle, + final String cmHandleReference, final String resourceIdentifier, final String contentType, final String authorization) { validateDataStore(PASSTHROUGH_RUNNING, datastoreName); - networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandle, + networkCmProxyFacade.writeResourceDataPassThroughRunningForCmHandle(cmHandleReference, resourceIdentifier, DELETE, NO_BODY, contentType, authorization); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @@ -317,13 +317,13 @@ public class NetworkCmProxyController implements NetworkCmProxyApi { /** * Get Cm Handle State by Cm Handle Id. * - * @param cmHandleId cm-handle identifier + * @param cmHandleReference cm-handle or alternate identifier * @return cm handle state */ @Override public ResponseEntity<RestOutputCmHandleCompositeState> getCmHandleStateByCmHandleId( - final String cmHandleId) { - final CompositeState cmHandleState = networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleId); + final String cmHandleReference) { + final CompositeState cmHandleState = networkCmProxyInventoryFacade.getCmHandleCompositeState(cmHandleReference); final RestOutputCmHandleCompositeState restOutputCmHandleCompositeState = new RestOutputCmHandleCompositeState(); restOutputCmHandleCompositeState.setState( diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy index 9f5331dbc3..92b47c6c8b 100644 --- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy +++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy @@ -32,7 +32,6 @@ import groovy.json.JsonSlurper import org.mapstruct.factory.Mappers import org.onap.cps.TestUtils import org.onap.cps.events.EventsPublisher -import org.onap.cps.ncmp.api.data.models.CmResourceAddress import org.onap.cps.ncmp.api.inventory.NetworkCmProxyInventoryFacade import org.onap.cps.ncmp.api.inventory.models.CompositeState import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle @@ -95,7 +94,7 @@ class NetworkCmProxyControllerSpec extends Specification { NetworkCmProxyInventoryFacade mockNetworkCmProxyInventoryFacade = Mock() @SpringBean - AlternateIdMatcher mockalternateIdMatcher = Mock() + AlternateIdMatcher mockAlternateIdMatcher = Mock() @SpringBean ObjectMapper objectMapper = new ObjectMapper() @@ -324,13 +323,13 @@ class NetworkCmProxyControllerSpec extends Specification { assertContainsPublicProperties(response) } - def 'Get Cm Handle composite state by Cm Handle id.'() { + def 'Get Cm Handle composite state by Cm Handle Reference.'() { given: 'a cm handle state endpoint' - def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/state" + def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle-reference/state" and: 'some cm handle composite state' def compositeState = compositeStateTestObject() and: 'the service method is invoked with the cm handle id returning the cm handle composite state' - 1 * mockNetworkCmProxyInventoryFacade.getCmHandleCompositeState('some-cm-handle') >> compositeState + 1 * mockNetworkCmProxyInventoryFacade.getCmHandleCompositeState('some-cm-handle-reference') >> compositeState when: 'the cm handle state api is invoked' def response = mvc.perform(get(cmHandlePropertiesEndpoint)).andReturn().response then: 'the correct response is returned' diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java index 794bc238f4..1acd937a31 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/NetworkCmProxyInventoryFacade.java @@ -36,7 +36,6 @@ import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistrationResponse; import org.onap.cps.ncmp.api.inventory.models.NcmpServiceCmHandle; -import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.onap.cps.ncmp.impl.inventory.CmHandleRegistrationService; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; @@ -44,12 +43,12 @@ import org.onap.cps.ncmp.impl.inventory.ParameterizedCmHandleQueryService; import org.onap.cps.ncmp.impl.inventory.models.CmHandleQueryConditions; import org.onap.cps.ncmp.impl.inventory.models.InventoryQueryConditions; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; -import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig; +import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager; +import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher; import org.onap.cps.ncmp.impl.utils.YangDataConverter; import org.onap.cps.spi.model.ModuleDefinition; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Slf4j @@ -62,9 +61,8 @@ public class NetworkCmProxyInventoryFacade { private final ParameterizedCmHandleQueryService parameterizedCmHandleQueryService; private final InventoryPersistence inventoryPersistence; private final JsonObjectMapper jsonObjectMapper; - - @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE) - private final Map<String, TrustLevel> trustLevelPerCmHandle; + private final TrustLevelManager trustLevelManager; + private final AlternateIdMatcher alternateIdMatcher; /** * Registration of Created, Removed, Updated or Upgraded CM Handles. @@ -72,7 +70,6 @@ public class NetworkCmProxyInventoryFacade { * @param dmiPluginRegistration Dmi Plugin Registration details * @return dmiPluginRegistrationResponse */ - public DmiPluginRegistrationResponse updateDmiRegistrationAndSyncModule( final DmiPluginRegistration dmiPluginRegistration) { return cmHandleRegistrationService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration); @@ -203,15 +200,17 @@ public class NetworkCmProxyInventoryFacade { /** * Get cm handle composite state for a given cm handle id. * - * @param cmHandleId cm handle identifier + * @param cmHandleReference cm handle or alternate identifier * @return cm handle state */ - public CompositeState getCmHandleCompositeState(final String cmHandleId) { + public CompositeState getCmHandleCompositeState(final String cmHandleReference) { + final String cmHandleId = alternateIdMatcher.getCmHandleId(cmHandleReference); return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState(); } private void applyCurrentTrustLevel(final NcmpServiceCmHandle ncmpServiceCmHandle) { - ncmpServiceCmHandle.setCurrentTrustLevel(trustLevelPerCmHandle.get(ncmpServiceCmHandle.getCmHandleId())); + ncmpServiceCmHandle.setCurrentTrustLevel(trustLevelManager + .getEffectiveTrustLevel(ncmpServiceCmHandle.getCmHandleId())); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/DmiHttpClientConfig.java index 583d4bb6ad..8eebb89a0a 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/HttpClientConfiguration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/DmiHttpClientConfig.java @@ -29,7 +29,7 @@ import org.springframework.context.annotation.Configuration; @Setter @Configuration @ConfigurationProperties(prefix = "ncmp.dmi.httpclient") -public class HttpClientConfiguration { +public class DmiHttpClientConfig { private final DataServices dataServices = new DataServices(); private final ModelServices modelServices = new ModelServices(); @@ -54,19 +54,4 @@ public class HttpClientConfiguration { private int maximumConnectionsTotal = 10; private int pendingAcquireMaxCount = 5; } - - /** - * Base configuration properties for all services. - */ - @Getter - @Setter - public static class ServiceConfig { - private String connectionProviderName = "cpsConnectionPool"; - private int maximumConnectionsTotal = 100; - private int pendingAcquireMaxCount = 50; - private Integer connectionTimeoutInSeconds = 30; - private long readTimeoutInSeconds = 30; - private long writeTimeoutInSeconds = 30; - private int maximumInMemorySizeInMegabytes = 1; - } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java new file mode 100644 index 0000000000..0903c671b5 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java @@ -0,0 +1,41 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Getter +@Setter +@Configuration +@ConfigurationProperties(prefix = "ncmp.policy-executor.httpclient") +public class PolicyExecutorHttpClientConfig { + + private final AllServices allServices = new AllServices(); + + @Getter + @Setter + public static class AllServices extends ServiceConfig { + private String connectionProviderName = "policyExecutorConfig"; + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java new file mode 100644 index 0000000000..f1fce0c7c6 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/ServiceConfig.java @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.config; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public abstract class ServiceConfig { + private String connectionProviderName = ""; + private int maximumInMemorySizeInMegabytes = 1; + private int maximumConnectionsTotal = 1; + private int pendingAcquireMaxCount = 1; + private Integer connectionTimeoutInSeconds = 1; + private long readTimeoutInSeconds = 1; + private long writeTimeoutInSeconds = 1; +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java index 90783a829a..6b813a6f69 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java @@ -41,15 +41,16 @@ import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException; import org.onap.cps.ncmp.impl.data.models.DmiDataOperation; import org.onap.cps.ncmp.impl.data.models.DmiDataOperationRequest; import org.onap.cps.ncmp.impl.data.models.DmiOperationCmHandle; +import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor; import org.onap.cps.ncmp.impl.data.utils.DmiDataOperationsHelper; import org.onap.cps.ncmp.impl.dmi.DmiProperties; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; -import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.models.DmiRequestBody; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; @@ -170,7 +171,10 @@ public class DmiDataOperations { final String requestData, final String dataType, final String authorization) { - final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); + final CmResourceAddress cmResourceAddress = + new CmResourceAddress(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleId, resourceId); + + final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmResourceAddress.getResolvedCmHandleId()); policyExecutor.checkPermission(yangModelCmHandle, operationType, authorization, resourceId, requestData); @@ -212,7 +216,7 @@ public class DmiDataOperations { final String optionsParamInQuery, final String topicParamInQuery) { final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(DATA); - return DmiServiceUrlTemplateBuilder.newInstance() + return RestServiceUrlTemplateBuilder.newInstance() .fixedPathSegment("ch") .variablePathSegment("cmHandleId", yangModelCmHandle.getId()) .fixedPathSegment("data") @@ -227,7 +231,7 @@ public class DmiDataOperations { private UrlTemplateParameters getUrlTemplateParameters(final String dmiServiceName, final String requestId, final String topicParamInQuery) { - return DmiServiceUrlTemplateBuilder.newInstance() + return RestServiceUrlTemplateBuilder.newInstance() .fixedPathSegment("data") .queryParameter("requestId", requestId) .queryParameter("topic", topicParamInQuery) diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java index b97088a5e0..5343a2e131 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/NetworkCmProxyFacade.java @@ -101,7 +101,7 @@ public class NetworkCmProxyFacade { /** * Write resource data for data store pass-through running using dmi for given cm-handle. * - * @param cmHandleId cm handle identifier + * @param cmHandleReference cm handle or alternate identifier * @param resourceIdentifier resource identifier * @param operationType required operation type * @param requestData request body to create resource @@ -109,13 +109,13 @@ public class NetworkCmProxyFacade { * @param authorization contents of Authorization header, or null if not present * @return {@code Object} return data */ - public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleId, + public Object writeResourceDataPassThroughRunningForCmHandle(final String cmHandleReference, final String resourceIdentifier, final OperationType operationType, final String requestData, final String dataType, final String authorization) { - return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier, + return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleReference, resourceIdentifier, operationType, requestData, dataType, authorization); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/PolicyExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java index 2b5eb9e792..8e7620ccea 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/PolicyExecutor.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.data; +package org.onap.cps.ncmp.impl.data.policyexecutor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java index 031cedc78b..8934c088a1 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImpl.java @@ -24,8 +24,8 @@ import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.datajobs.DataJobResultService; import org.onap.cps.ncmp.impl.dmi.DmiProperties; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; -import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.springframework.stereotype.Service; @Service @@ -41,7 +41,7 @@ public class DataJobResultServiceImpl implements DataJobResultService { final String dataProducerId, final String dataProducerJobId, final String destination) { - final UrlTemplateParameters urlTemplateParameters = DmiServiceUrlTemplateBuilder.newInstance() + final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance() .fixedPathSegment("cmwriteJob") .fixedPathSegment("dataProducer") .variablePathSegment("dataProducerId", dataProducerId) diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java index fb17f066ce..1cfb8a9dff 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImpl.java @@ -24,8 +24,8 @@ import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.datajobs.DataJobStatusService; import org.onap.cps.ncmp.impl.dmi.DmiProperties; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; -import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.springframework.stereotype.Service; /** @@ -54,7 +54,7 @@ public class DataJobStatusServiceImpl implements DataJobStatusService { private UrlTemplateParameters buildUrlParameters(final String dmiServiceName, final String dataProducerId, final String dataProducerJobId) { - return DmiServiceUrlTemplateBuilder.newInstance() + return RestServiceUrlTemplateBuilder.newInstance() .fixedPathSegment("cmwriteJob") .fixedPathSegment("dataProducer") .variablePathSegment("dataProducerId", dataProducerId) diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java index 0d14dace5e..a118d53e7e 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/DmiSubJobRequestHandler.java @@ -33,9 +33,9 @@ import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteRequest; import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse; import org.onap.cps.ncmp.impl.dmi.DmiProperties; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; -import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.models.RequiredDmiService; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; @@ -88,7 +88,7 @@ public class DmiSubJobRequestHandler { } private UrlTemplateParameters getUrlTemplateParameters(final String destination, final ProducerKey producerKey) { - return DmiServiceUrlTemplateBuilder.newInstance() + return RestServiceUrlTemplateBuilder.newInstance() .fixedPathSegment("cmwriteJob") .queryParameter("destination", destination) .createUrlTemplateParameters(producerKey.dmiServiceName(), dmiProperties.getDmiBasePath()); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java index c10132060d..a177272dff 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiRestClient.java @@ -34,6 +34,7 @@ import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.data.models.OperationType; import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException; import org.onap.cps.ncmp.impl.models.RequiredDmiService; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpHeaders; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java new file mode 100644 index 0000000000..4134a56ead --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfiguration.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.impl.dmi; + +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.config.DmiHttpClientConfig; +import org.onap.cps.ncmp.impl.utils.http.WebClientConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +@RequiredArgsConstructor +public class DmiWebClientsConfiguration extends WebClientConfiguration { + + private final DmiHttpClientConfig dmiHttpClientConfig; + + /** + * Configures and creates a web client bean for DMI data services. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for data services. + */ + @Bean + public WebClient dataServicesWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, dmiHttpClientConfig.getDataServices()); + } + + /** + * Configures and creates a web client bean for DMI model services. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for model services. + */ + @Bean + public WebClient modelServicesWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, dmiHttpClientConfig.getModelServices()); + } + + /** + * Configures and creates a web client bean for DMI health check services. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for health check services. + */ + @Bean + public WebClient healthChecksWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, dmiHttpClientConfig.getHealthCheckServices()); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java index d6bda3beee..d9f7e38993 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationService.java @@ -37,6 +37,7 @@ import com.hazelcast.map.IMap; import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -58,13 +59,11 @@ import org.onap.cps.ncmp.impl.inventory.models.CmHandleState; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.inventory.sync.ModuleOperationsUtils; import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandler; -import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelCacheConfig; import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager; import org.onap.cps.spi.exceptions.AlreadyDefinedException; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.spi.exceptions.DataNodeNotFoundException; import org.onap.cps.spi.exceptions.DataValidationException; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Slf4j @@ -79,11 +78,7 @@ public class CmHandleRegistrationService { private final CpsDataService cpsDataService; private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler; private final IMap<String, Object> moduleSyncStartedOnCmHandles; - - @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN) - private final Map<String, TrustLevel> trustLevelPerDmiPlugin; private final TrustLevelManager trustLevelManager; - private final AlternateIdChecker alternateIdChecker; /** @@ -98,7 +93,7 @@ public class CmHandleRegistrationService { dmiPluginRegistration.validateDmiPluginRegistration(); final DmiPluginRegistrationResponse dmiPluginRegistrationResponse = new DmiPluginRegistrationResponse(); - setTrustLevelPerDmiPlugin(dmiPluginRegistration); + trustLevelManager.registerDmiPlugin(dmiPluginRegistration); processRemovedCmHandles(dmiPluginRegistration, dmiPluginRegistrationResponse); @@ -153,7 +148,7 @@ public class CmHandleRegistrationService { final Set<String> notDeletedCmHandles = new HashSet<>(); for (final List<String> tobeRemovedCmHandleBatch : Lists.partition(tobeRemovedCmHandleIds, DELETE_BATCH_SIZE)) { try { - batchDeleteCmHandlesFromDbAndModuleSyncMap(tobeRemovedCmHandleBatch); + batchDeleteCmHandlesFromDbAndCaches(tobeRemovedCmHandleBatch); tobeRemovedCmHandleBatch.forEach(cmHandleId -> cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId))); @@ -215,8 +210,7 @@ public class CmHandleRegistrationService { final DmiPluginRegistrationResponse dmiPluginRegistrationResponse) { final List<String> cmHandleIds = dmiPluginRegistration.getUpgradedCmHandles().getCmHandles(); - final String upgradedModuleSetTag = - StringUtils.trimToEmpty(dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag()); + final String upgradedModuleSetTag = dmiPluginRegistration.getUpgradedCmHandles().getModuleSetTag(); final Map<YangModelCmHandle, CmHandleState> acceptedCmHandleStatePerCmHandle = new HashMap<>(cmHandleIds.size()); final List<CmHandleRegistrationResponse> cmHandleUpgradeResponses = new ArrayList<>(cmHandleIds.size()); @@ -260,7 +254,7 @@ public class CmHandleRegistrationService { ncmpServiceCmHandle.getRegistrationTrustLevel()); } } - trustLevelManager.handleInitialRegistrationOfTrustLevels(initialTrustLevelPerCmHandleId); + trustLevelManager.registerCmHandles(initialTrustLevelPerCmHandleId); } private static boolean moduleUpgradeCanBeSkipped(final YangModelCmHandle yangModelCmHandle, @@ -281,7 +275,7 @@ public class CmHandleRegistrationService { private CmHandleRegistrationResponse deleteCmHandleAndGetCmHandleRegistrationResponse(final String cmHandleId) { try { - deleteCmHandleFromDbAndModuleSyncMap(cmHandleId); + deleteCmHandleFromDbAndCaches(cmHandleId); return CmHandleRegistrationResponse.createSuccessResponse(cmHandleId); } catch (final DataNodeNotFoundException dataNodeNotFoundException) { log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", @@ -304,15 +298,17 @@ public class CmHandleRegistrationService { lcmEventsCmHandleStateHandler.updateCmHandleStateBatch(cmHandleStatePerCmHandle); } - private void deleteCmHandleFromDbAndModuleSyncMap(final String cmHandleId) { + private void deleteCmHandleFromDbAndCaches(final String cmHandleId) { inventoryPersistence.deleteSchemaSetWithCascade(cmHandleId); inventoryPersistence.deleteDataNode(NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='" + cmHandleId + "']"); + trustLevelManager.removeCmHandles(Collections.singleton(cmHandleId)); removeDeletedCmHandleFromModuleSyncMap(cmHandleId); } - private void batchDeleteCmHandlesFromDbAndModuleSyncMap(final Collection<String> cmHandleIds) { + private void batchDeleteCmHandlesFromDbAndCaches(final Collection<String> cmHandleIds) { inventoryPersistence.deleteSchemaSetsWithCascade(cmHandleIds); inventoryPersistence.deleteDataNodes(mapCmHandleIdsToXpaths(cmHandleIds)); + trustLevelManager.removeCmHandles(cmHandleIds); cmHandleIds.forEach(this::removeDeletedCmHandleFromModuleSyncMap); } @@ -346,14 +342,6 @@ public class CmHandleRegistrationService { return cmHandleStatePerCmHandle.keySet().stream().map(YangModelCmHandle::getId).toList(); } - private void setTrustLevelPerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) { - if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) { - trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiPlugin(), TrustLevel.COMPLETE); - } else { - trustLevelPerDmiPlugin.put(dmiPluginRegistration.getDmiDataPlugin(), TrustLevel.COMPLETE); - } - } - private Collection<String> checkAlternateIds( final List<NcmpServiceCmHandle> cmHandlesToBeCreated, final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java index 433c67f100..8ba70b3a31 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperations.java @@ -36,10 +36,10 @@ import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.inventory.models.YangResource; import org.onap.cps.ncmp.impl.dmi.DmiProperties; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; -import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; import org.onap.cps.ncmp.impl.models.DmiRequestBody; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; @@ -107,7 +107,7 @@ public class DmiModelOperations { final String jsonRequestBody, final String cmHandle, final String resourceName) { - final UrlTemplateParameters urlTemplateParameters = DmiServiceUrlTemplateBuilder.newInstance() + final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance() .fixedPathSegment("ch") .variablePathSegment("cmHandleId", cmHandle) .fixedPathSegment(resourceName) diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java index 617fe7f01d..efcbb78ace 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumer.java @@ -52,7 +52,7 @@ public class DeviceTrustLevelMessageConsumer { final DeviceTrustLevel deviceTrustLevel = CloudEventMapper.toTargetEvent(consumerRecord.value(), DeviceTrustLevel.class); final String trustLevelAsString = deviceTrustLevel.getData().getTrustLevel(); - trustLevelManager.handleUpdateOfDeviceTrustLevel(cmHandleId, TrustLevel.valueOf(trustLevelAsString)); + trustLevelManager.updateCmHandleTrustLevel(cmHandleId, TrustLevel.valueOf(trustLevelAsString)); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java index c81e9b7840..7581c4af7a 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDog.java @@ -26,9 +26,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.dmi.DmiRestClient; -import org.onap.cps.ncmp.impl.dmi.DmiServiceUrlTemplateBuilder; -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; +import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder; +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; @@ -67,13 +67,13 @@ public class DmiPluginTrustLevelWatchDog { } else { final Collection<String> cmHandleIds = cmHandleQueryService.getCmHandleIdsByDmiPluginIdentifier(dmiServiceName); - trustLevelManager.handleUpdateOfDmiTrustLevel(dmiServiceName, cmHandleIds, newDmiTrustLevel); + trustLevelManager.updateDmi(dmiServiceName, cmHandleIds, newDmiTrustLevel); } }); } private String getDmiHealthStatus(final String dmiServiceBaseUrl) { - final UrlTemplateParameters urlTemplateParameters = DmiServiceUrlTemplateBuilder.newInstance() + final UrlTemplateParameters urlTemplateParameters = RestServiceUrlTemplateBuilder.newInstance() .createUrlTemplateParametersForHealthCheck(dmiServiceBaseUrl); return dmiRestClient.getDmiHealthStatus(urlTemplateParameters).block(); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java index 44079c0bc9..f468127dbc 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManager.java @@ -24,6 +24,7 @@ import java.util.Collection; import java.util.Map; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration; import org.onap.cps.ncmp.api.inventory.models.TrustLevel; import org.onap.cps.ncmp.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle; @@ -49,11 +50,26 @@ public class TrustLevelManager { private static final String AVC_NO_OLD_VALUE = null; /** + * Add dmi plugins to the cache. + * + * @param dmiPluginRegistration a dmi plugin being registered + */ + public void registerDmiPlugin(final DmiPluginRegistration dmiPluginRegistration) { + final String dmiServiceName; + if (DmiPluginRegistration.isNullEmptyOrBlank(dmiPluginRegistration.getDmiDataPlugin())) { + dmiServiceName = dmiPluginRegistration.getDmiPlugin(); + } else { + dmiServiceName = dmiPluginRegistration.getDmiDataPlugin(); + } + trustLevelPerDmiPlugin.put(dmiServiceName, TrustLevel.COMPLETE); + } + + /** * Add cmHandles to the cache and publish notification for initial trust level of cmHandles if it is NONE. * * @param cmHandlesToBeCreated a list of cmHandles being created */ - public void handleInitialRegistrationOfTrustLevels(final Map<String, TrustLevel> cmHandlesToBeCreated) { + public void registerCmHandles(final Map<String, TrustLevel> cmHandlesToBeCreated) { for (final Map.Entry<String, TrustLevel> entry : cmHandlesToBeCreated.entrySet()) { final String cmHandleId = entry.getKey(); if (trustLevelPerCmHandle.containsKey(cmHandleId)) { @@ -82,15 +98,15 @@ public class TrustLevelManager { * @param affectedCmHandleIds cm handle ids belonging to dmi service name * @param newDmiTrustLevel new trust level of the dmi plugin */ - public void handleUpdateOfDmiTrustLevel(final String dmiServiceName, - final Collection<String> affectedCmHandleIds, - final TrustLevel newDmiTrustLevel) { + public void updateDmi(final String dmiServiceName, + final Collection<String> affectedCmHandleIds, + final TrustLevel newDmiTrustLevel) { final TrustLevel oldDmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName); trustLevelPerDmiPlugin.put(dmiServiceName, newDmiTrustLevel); for (final String affectedCmHandleId : affectedCmHandleIds) { - final TrustLevel deviceTrustLevel = trustLevelPerCmHandle.get(affectedCmHandleId); - final TrustLevel oldEffectiveTrustLevel = deviceTrustLevel.getEffectiveTrustLevel(oldDmiTrustLevel); - final TrustLevel newEffectiveTrustLevel = deviceTrustLevel.getEffectiveTrustLevel(newDmiTrustLevel); + final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandle.get(affectedCmHandleId); + final TrustLevel oldEffectiveTrustLevel = cmHandleTrustLevel.getEffectiveTrustLevel(oldDmiTrustLevel); + final TrustLevel newEffectiveTrustLevel = cmHandleTrustLevel.getEffectiveTrustLevel(newDmiTrustLevel); sendAvcNotificationIfRequired(affectedCmHandleId, oldEffectiveTrustLevel, newEffectiveTrustLevel); } } @@ -100,23 +116,56 @@ public class TrustLevelManager { * changed. * * @param cmHandleId cm handle id - * @param newDeviceTrustLevel new trust level of the device + * @param newCmHandleTrustLevel new trust level of the device */ - public void handleUpdateOfDeviceTrustLevel(final String cmHandleId, - final TrustLevel newDeviceTrustLevel) { - final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); - final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); + public void updateCmHandleTrustLevel(final String cmHandleId, + final TrustLevel newCmHandleTrustLevel) { + final String dmiServiceName = getDmiServiceName(cmHandleId); final TrustLevel dmiTrustLevel = trustLevelPerDmiPlugin.get(dmiServiceName); - final TrustLevel oldDeviceTrustLevel = trustLevelPerCmHandle.get(cmHandleId); + final TrustLevel oldCmHandleTrustLevel = trustLevelPerCmHandle.get(cmHandleId); - final TrustLevel oldEffectiveTrustLevel = oldDeviceTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); - final TrustLevel newEffectiveTrustLevel = newDeviceTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); + final TrustLevel oldEffectiveTrustLevel = oldCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); + final TrustLevel newEffectiveTrustLevel = newCmHandleTrustLevel.getEffectiveTrustLevel(dmiTrustLevel); - trustLevelPerCmHandle.put(cmHandleId, newDeviceTrustLevel); + trustLevelPerCmHandle.put(cmHandleId, newCmHandleTrustLevel); sendAvcNotificationIfRequired(cmHandleId, oldEffectiveTrustLevel, newEffectiveTrustLevel); } + /** + * Select effective trust level among device and dmi plugin. + * + * @param cmHandleId cm handle id + * @return TrustLevel effective trust level + */ + public TrustLevel getEffectiveTrustLevel(final String cmHandleId) { + final TrustLevel dmiTrustLevel = TrustLevel.COMPLETE; // TODO: CPS-2375 + final TrustLevel cmHandleTrustLevel = trustLevelPerCmHandle.get(cmHandleId); + return dmiTrustLevel.getEffectiveTrustLevel(cmHandleTrustLevel); + } + + /** + * Remove cm handle trust level from the cache and publish notification for trust level of cmHandles + * if it is COMPLETE. + * + * @param cmHandleIds cm handle ids to be removed from the cache + */ + public void removeCmHandles(final Collection<String> cmHandleIds) { + for (final String cmHandleId : cmHandleIds) { + if (trustLevelPerCmHandle.containsKey(cmHandleId)) { + final TrustLevel oldTrustLevel = trustLevelPerCmHandle.remove(cmHandleId); + sendAvcNotificationIfRequired(cmHandleId, oldTrustLevel, TrustLevel.NONE); + } else { + log.debug("Removed Cm handle: {} is not in trust level cache", cmHandleId); + } + } + } + + private String getDmiServiceName(final String cmHandleId) { + final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId); + return yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); + } + private void sendAvcNotificationIfRequired(final String notificationCandidateCmHandleId, final TrustLevel oldEffectiveTrustLevel, final TrustLevel newEffectiveTrustLevel) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java new file mode 100644 index 0000000000..333030ccd2 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfiguration.java @@ -0,0 +1,46 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.impl.policyexecutor; + +import lombok.RequiredArgsConstructor; +import org.onap.cps.ncmp.config.PolicyExecutorHttpClientConfig; +import org.onap.cps.ncmp.impl.utils.http.WebClientConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +@RequiredArgsConstructor +public class PolicyExecutorWebClientConfiguration extends WebClientConfiguration { + + private final PolicyExecutorHttpClientConfig policyExecutorHttpClientConfig; + + /** + * Configures and creates a web client bean for Policy Executor. + * + * @param webClientBuilder The builder instance to create the WebClient. + * @return a WebClient instance configured for Policy Executor. + */ + @Bean + public WebClient policyExecutorWebClient(final WebClient.Builder webClientBuilder) { + return configureWebClient(webClientBuilder, policyExecutorHttpClientConfig.getAllServices()); + } +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java index c408ff9b13..c526dfb297 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java @@ -59,7 +59,7 @@ public class AlternateIdMatcher { /** * Get cm handle Id from given cmHandleReference. * - * @param cmHandleReference alternate ID + * @param cmHandleReference cm handle or alternate identifier * @return cm handle id string */ public String getCmHandleId(final String cmHandleReference) { diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java index e7dbea83f2..fafb09007d 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilder.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.dmi; +package org.onap.cps.ncmp.impl.utils.http; import java.util.Collections; import java.util.HashMap; @@ -30,7 +30,7 @@ import org.apache.logging.log4j.util.Strings; import org.springframework.web.util.UriComponentsBuilder; @NoArgsConstructor -public class DmiServiceUrlTemplateBuilder { +public class RestServiceUrlTemplateBuilder { private final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance(); private static final String FIXED_PATH_SEGMENT = null; @@ -43,8 +43,8 @@ public class DmiServiceUrlTemplateBuilder { * * @return a new instance of DmiServiceUrlTemplateBuilder */ - public static DmiServiceUrlTemplateBuilder newInstance() { - return new DmiServiceUrlTemplateBuilder(); + public static RestServiceUrlTemplateBuilder newInstance() { + return new RestServiceUrlTemplateBuilder(); } /** @@ -53,7 +53,7 @@ public class DmiServiceUrlTemplateBuilder { * @param pathSegment the path segment * @return this builder instance */ - public DmiServiceUrlTemplateBuilder fixedPathSegment(final String pathSegment) { + public RestServiceUrlTemplateBuilder fixedPathSegment(final String pathSegment) { pathSegments.put(pathSegment, FIXED_PATH_SEGMENT); return this; } @@ -66,7 +66,7 @@ public class DmiServiceUrlTemplateBuilder { * @param value the value to be insert in teh URL for the given variable path segment * @return this builder instance */ - public DmiServiceUrlTemplateBuilder variablePathSegment(final String pathSegment, final String value) { + public RestServiceUrlTemplateBuilder variablePathSegment(final String pathSegment, final String value) { pathSegments.put(pathSegment, value); return this; } @@ -80,8 +80,8 @@ public class DmiServiceUrlTemplateBuilder { * * @return this builder instance */ - public DmiServiceUrlTemplateBuilder queryParameter(final String queryParameterName, - final String queryParameterValue) { + public RestServiceUrlTemplateBuilder queryParameter(final String queryParameterName, + final String queryParameterValue) { if (Strings.isNotBlank(queryParameterValue)) { queryParameters.put(queryParameterName, queryParameterValue); } @@ -91,12 +91,12 @@ public class DmiServiceUrlTemplateBuilder { /** * Constructs a URL template with variables based on the accumulated path segments and query parameters. * - * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com". - * @param dmiBasePath the base path of the DMI service + * @param serviceBaseUrl the base URL of the service, e.g., "http://dmi-service.com". + * @param basePath the base path of the service * @return a UrlTemplateParameters instance containing the complete URL template and URL variables */ - public UrlTemplateParameters createUrlTemplateParameters(final String dmiServiceBaseUrl, final String dmiBasePath) { - this.uriComponentsBuilder.pathSegment(dmiBasePath) + public UrlTemplateParameters createUrlTemplateParameters(final String serviceBaseUrl, final String basePath) { + this.uriComponentsBuilder.pathSegment(basePath) .pathSegment(VERSION_SEGMENT); final Map<String, String> urlTemplateVariables = new HashMap<>(); @@ -115,22 +115,21 @@ public class DmiServiceUrlTemplateBuilder { urlTemplateVariables.put(paramName, paramValue); }); - final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString(); + final String urlTemplate = serviceBaseUrl + this.uriComponentsBuilder.build().toUriString(); return new UrlTemplateParameters(urlTemplate, urlTemplateVariables); } /** * Constructs a URL for DMI health check based on the given base URL. * - * @param dmiServiceBaseUrl the base URL of the DMI service, e.g., "http://dmi-service.com". + * @param serviceBaseUrl the base URL of the service, e.g., "http://dmi-service.com". * @return a {@link UrlTemplateParameters} instance containing the complete URL template and empty URL variables, * suitable for DMI health check. */ - public UrlTemplateParameters createUrlTemplateParametersForHealthCheck(final String dmiServiceBaseUrl) { - this.uriComponentsBuilder.pathSegment("actuator") - .pathSegment("health"); + public UrlTemplateParameters createUrlTemplateParametersForHealthCheck(final String serviceBaseUrl) { + this.uriComponentsBuilder.pathSegment("actuator").pathSegment("health"); - final String urlTemplate = dmiServiceBaseUrl + this.uriComponentsBuilder.build().toUriString(); + final String urlTemplate = serviceBaseUrl + this.uriComponentsBuilder.build().toUriString(); return new UrlTemplateParameters(urlTemplate, Collections.emptyMap()); } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/UrlTemplateParameters.java index f51511116a..839af71823 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/UrlTemplateParameters.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/UrlTemplateParameters.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.dmi; +package org.onap.cps.ncmp.impl.utils.http; import java.util.Map; diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java index c176e40226..d8e8350345 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfiguration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/http/WebClientConfiguration.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.dmi; +package org.onap.cps.ncmp.impl.utils.http; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import io.netty.channel.ChannelOption; @@ -27,10 +27,7 @@ import io.netty.handler.timeout.WriteTimeoutHandler; import io.netty.resolver.DefaultAddressResolverGroup; import java.time.Duration; import java.util.concurrent.TimeUnit; -import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.config.HttpClientConfiguration; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; +import org.onap.cps.ncmp.config.ServiceConfig; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ReactorClientHttpConnector; @@ -39,58 +36,22 @@ import reactor.netty.http.client.HttpClient; import reactor.netty.resources.ConnectionProvider; /** - * Configures and creates WebClient beans for various DMI services including data, model, and health check services. + * Configures and creates WebClient beans for various rest services such as DMI and Policy Executor. * The configuration utilizes Netty-based HttpClient with custom connection settings, read and write timeouts, * and initializes WebClient with these settings to ensure optimal performance and resource management. */ -@Configuration -@RequiredArgsConstructor -public class DmiWebClientConfiguration { +public class WebClientConfiguration { - private final HttpClientConfiguration httpClientConfiguration; private static final Duration DEFAULT_RESPONSE_TIMEOUT = Duration.ofSeconds(30); - /** - * Configures and creates a web client bean for DMI data services. - * - * @param webClientBuilder The builder instance to create the WebClient. - * @return a WebClient instance configured for data services. - */ - @Bean - public WebClient dataServicesWebClient(final WebClient.Builder webClientBuilder) { - return configureWebClient(webClientBuilder, httpClientConfiguration.getDataServices()); - } - - /** - * Configures and creates a web client bean for DMI model services. - * - * @param webClientBuilder The builder instance to create the WebClient. - * @return a WebClient instance configured for model services. - */ - @Bean - public WebClient modelServicesWebClient(final WebClient.Builder webClientBuilder) { - return configureWebClient(webClientBuilder, httpClientConfiguration.getModelServices()); - } - - /** - * Configures and creates a web client bean for DMI health check services. - * - * @param webClientBuilder The builder instance to create the WebClient. - * @return a WebClient instance configured for health check services. - */ - @Bean - public WebClient healthChecksWebClient(final WebClient.Builder webClientBuilder) { - return configureWebClient(webClientBuilder, httpClientConfiguration.getHealthCheckServices()); - } - - private WebClient configureWebClient(final WebClient.Builder webClientBuilder, - final HttpClientConfiguration.ServiceConfig serviceConfig) { + protected WebClient configureWebClient(final WebClient.Builder webClientBuilder, + final ServiceConfig serviceConfig) { final ConnectionProvider connectionProvider = getConnectionProvider(serviceConfig); final HttpClient httpClient = createHttpClient(serviceConfig, connectionProvider); return buildAndGetWebClient(webClientBuilder, httpClient, serviceConfig.getMaximumInMemorySizeInMegabytes()); } - private static HttpClient createHttpClient(final HttpClientConfiguration.ServiceConfig serviceConfig, + private static HttpClient createHttpClient(final ServiceConfig serviceConfig, final ConnectionProvider connectionProvider) { return HttpClient.create(connectionProvider) .responseTimeout(DEFAULT_RESPONSE_TIMEOUT) @@ -103,7 +64,7 @@ public class DmiWebClientConfiguration { } @SuppressFBWarnings("BC_UNCONFIRMED_CAST_OF_RETURN_VALUE") - private static ConnectionProvider getConnectionProvider(final HttpClientConfiguration.ServiceConfig serviceConfig) { + private static ConnectionProvider getConnectionProvider(final ServiceConfig serviceConfig) { return ConnectionProvider.builder(serviceConfig.getConnectionProviderName()) .maxConnections(serviceConfig.getMaximumConnectionsTotal()) .pendingAcquireMaxCount(serviceConfig.getPendingAcquireMaxCount()) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/HttpClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy index 1d3b22fb73..e0ae204c8d 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/HttpClientConfigurationSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/DmiHttpClientConfigSpec.groovy @@ -28,46 +28,46 @@ import org.springframework.test.context.ContextConfiguration import spock.lang.Specification @SpringBootTest -@ContextConfiguration(classes = [HttpClientConfiguration]) -@EnableConfigurationProperties(HttpClientConfiguration) -class HttpClientConfigurationSpec extends Specification { +@ContextConfiguration(classes = [DmiHttpClientConfig]) +@EnableConfigurationProperties(DmiHttpClientConfig) +class DmiHttpClientConfigSpec extends Specification { @Autowired - HttpClientConfiguration httpClientConfiguration + DmiHttpClientConfig dmiHttpClientConfig def 'Test http client configuration properties of data with custom and default values'() { - expect: 'properties are populated correctly for data' - with(httpClientConfiguration.dataServices) { - assert connectionTimeoutInSeconds == 123 - assert readTimeoutInSeconds == 33 - assert writeTimeoutInSeconds == 30 - assert maximumConnectionsTotal == 100 - assert pendingAcquireMaxCount == 22 - assert maximumInMemorySizeInMegabytes == 7 + expect: 'properties are populated correctly for data services' + with(dmiHttpClientConfig.dataServices) { + assert maximumInMemorySizeInMegabytes == 1 + assert maximumConnectionsTotal == 2 + assert pendingAcquireMaxCount == 3 + assert connectionTimeoutInSeconds == 4 + assert readTimeoutInSeconds == 5 + assert writeTimeoutInSeconds == 6 } } def 'Test http client configuration properties of model with custom and default values'() { - expect: 'properties are populated correctly for model' - with(httpClientConfiguration.modelServices) { - assert connectionTimeoutInSeconds == 456 - assert readTimeoutInSeconds == 30 - assert writeTimeoutInSeconds == 30 - assert maximumConnectionsTotal == 111 - assert pendingAcquireMaxCount == 44 - assert maximumInMemorySizeInMegabytes == 8 + expect: 'properties are populated correctly for model services' + with(dmiHttpClientConfig.modelServices) { + assert maximumInMemorySizeInMegabytes == 11 + assert maximumConnectionsTotal == 12 + assert pendingAcquireMaxCount == 13 + assert connectionTimeoutInSeconds == 14 + assert readTimeoutInSeconds == 15 + assert writeTimeoutInSeconds == 16 } } def 'Test http client configuration properties of health with default values'() { - expect: 'properties are populated correctly for health' - with(httpClientConfiguration.healthCheckServices) { - assert connectionTimeoutInSeconds == 30 - assert readTimeoutInSeconds == 30 - assert writeTimeoutInSeconds == 30 - assert maximumConnectionsTotal == 10 - assert pendingAcquireMaxCount == 5 - assert maximumInMemorySizeInMegabytes == 1 + expect: 'properties are populated correctly for health check services' + with(dmiHttpClientConfig.healthCheckServices) { + assert maximumInMemorySizeInMegabytes == 21 + assert maximumConnectionsTotal == 22 + assert pendingAcquireMaxCount == 23 + assert connectionTimeoutInSeconds == 24 + assert readTimeoutInSeconds == 25 + assert writeTimeoutInSeconds == 26 } } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy new file mode 100644 index 0000000000..1946a452b1 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfigSpec.groovy @@ -0,0 +1,48 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.config + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration +import spock.lang.Specification + +@SpringBootTest +@ContextConfiguration(classes = [PolicyExecutorHttpClientConfig]) +@EnableConfigurationProperties +class PolicyExecutorHttpClientConfigSpec extends Specification { + + @Autowired + PolicyExecutorHttpClientConfig policyExecutorHttpClientConfig + + def 'Test http client configuration properties of data with custom and default values'() { + expect: 'properties are populated correctly for all services' + with(policyExecutorHttpClientConfig.allServices) { + assert maximumInMemorySizeInMegabytes == 31 + assert maximumConnectionsTotal == 32 + assert pendingAcquireMaxCount == 33 + assert connectionTimeoutInSeconds == 34 + assert readTimeoutInSeconds == 35 + assert writeTimeoutInSeconds == 36 + } + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy index 8b369bf549..fd76abb581 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy @@ -28,16 +28,16 @@ import org.onap.cps.ncmp.api.data.models.DataOperationRequest import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException import org.onap.cps.ncmp.config.CpsApplicationContext import org.onap.cps.ncmp.events.async1_0_0.DataOperationEvent +import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec import org.onap.cps.ncmp.impl.dmi.DmiProperties -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import org.onap.cps.ncmp.utils.TestUtils import org.onap.cps.utils.JsonObjectMapper import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootContextLoader import org.springframework.boot.test.context.SpringBootTest import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity @@ -49,6 +49,8 @@ import static org.onap.cps.ncmp.api.NcmpResponseStatus.UNKNOWN_ERROR import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_OPERATIONAL import static org.onap.cps.ncmp.api.data.models.DatastoreType.PASSTHROUGH_RUNNING import static org.onap.cps.ncmp.api.data.models.OperationType.CREATE +import static org.onap.cps.ncmp.api.data.models.OperationType.DELETE +import static org.onap.cps.ncmp.api.data.models.OperationType.PATCH import static org.onap.cps.ncmp.api.data.models.OperationType.READ import static org.onap.cps.ncmp.api.data.models.OperationType.UPDATE import static org.onap.cps.ncmp.impl.models.RequiredDmiService.DATA @@ -161,6 +163,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { def 'Write data for pass-through:running datastore in DMI.'() { given: 'a cm handle for #cmHandleId' mockYangModelCmHandleRetrieval([yangModelCmHandleProperty]) + alternateIdMatcher.getCmHandleId(cmHandleId) >> cmHandleId and: 'a positive response from DMI service when it is called with the expected parameters' def expectedUrlTemplateParameters = new UrlTemplateParameters('myServiceName/dmi/v1/ch/{cmHandleId}/data/ds/{datastore}?resourceIdentifier={resourceIdentifier}', ['resourceIdentifier': resourceIdentifier, 'datastore': 'ncmp-datastore:passthrough-running', 'cmHandleId': cmHandleId]) def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"},"moduleSetTag":""}' @@ -176,6 +179,8 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec { operation || expectedOperationInUrl CREATE || 'create' UPDATE || 'update' + DELETE || 'delete' + PATCH || 'patch' } def 'State Ready validation'() { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy index 654206776b..4b09afa2ae 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/PolicyExecutorSpec.groovy @@ -4,6 +4,7 @@ import ch.qos.logback.classic.Level import ch.qos.logback.classic.Logger import ch.qos.logback.classic.spi.ILoggingEvent import ch.qos.logback.core.read.ListAppender +import org.onap.cps.ncmp.impl.data.policyexecutor.PolicyExecutor import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy index 3af474040e..74bd0484df 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobResultServiceImplSpec.groovy @@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.datajobs import org.onap.cps.ncmp.impl.dmi.DmiProperties import org.onap.cps.ncmp.impl.dmi.DmiRestClient -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import reactor.core.publisher.Mono import spock.lang.Specification diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy index d231dfa755..be46d885e0 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/DataJobStatusServiceImplSpec.groovy @@ -22,7 +22,7 @@ package org.onap.cps.ncmp.impl.datajobs import org.onap.cps.ncmp.impl.dmi.DmiProperties import org.onap.cps.ncmp.impl.dmi.DmiRestClient -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import reactor.core.publisher.Mono import spock.lang.Specification diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy index affbf2aa4f..65fda8718c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiOperationsBaseSpec.groovy @@ -46,6 +46,7 @@ abstract class DmiOperationsBaseSpec extends Specification { def yangModelCmHandle = new YangModelCmHandle() def static dmiServiceName = 'myServiceName' def static cmHandleId = 'some-cm-handle' + def static alternateId = 'alt-id-' + cmHandleId def static resourceIdentifier = 'parent/child' def mockYangModelCmHandleRetrieval(dmiProperties) { @@ -68,6 +69,7 @@ abstract class DmiOperationsBaseSpec extends Specification { yangModelCmHandle.dmiServiceName = dmiServiceName yangModelCmHandle.dmiProperties = dmiProperties yangModelCmHandle.id = cmHandleId + yangModelCmHandle.alternateId = alternateId yangModelCmHandle.compositeState = new CompositeState() yangModelCmHandle.compositeState.cmHandleState = CmHandleState.READY yangModelCmHandle.moduleSetTag = moduleSetTag diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy index d92e69a136..4d47ef14a0 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiRestClientSpec.groovy @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.node.ObjectNode import org.onap.cps.ncmp.api.exceptions.DmiClientRequestException +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import org.onap.cps.ncmp.utils.TestUtils import org.onap.cps.utils.JsonObjectMapper import org.springframework.http.HttpHeaders diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfigurationSpec.groovy deleted file mode 100644 index fca47d8c24..0000000000 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientConfigurationSpec.groovy +++ /dev/null @@ -1,77 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2024 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.cps.ncmp.impl.dmi - - -import org.onap.cps.ncmp.config.HttpClientConfiguration -import org.springframework.boot.context.properties.EnableConfigurationProperties -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.test.context.ContextConfiguration -import org.springframework.test.context.TestPropertySource -import org.springframework.web.reactive.function.client.WebClient -import spock.lang.Specification - -@SpringBootTest -@ContextConfiguration(classes = [HttpClientConfiguration]) -@TestPropertySource(properties = ['ncmp.dmi.httpclient.data-services.connectionTimeoutInSeconds=1', 'ncmp.dmi.httpclient.model-services.maximumInMemorySizeInMegabytes=1']) -@EnableConfigurationProperties -class DmiWebClientConfigurationSpec extends Specification { - - def webClientBuilder = Mock(WebClient.Builder) { - defaultHeaders(_) >> it - clientConnector(_) >> it - codecs(_) >> it - build() >> Mock(WebClient) - } - - def httpClientConfiguration = Spy(HttpClientConfiguration.class) - - def objectUnderTest = new DmiWebClientConfiguration(httpClientConfiguration) - - def 'Web Client Configuration construction.'() { - expect: 'the system can create an instance' - new DmiWebClientConfiguration(httpClientConfiguration) != null - } - - def 'Creating a web client instance data service.'() { - given: 'Web client configuration is invoked' - def dataServicesWebClient = objectUnderTest.dataServicesWebClient(webClientBuilder) - expect: 'the system can create an instance for data service' - assert dataServicesWebClient != null - assert dataServicesWebClient instanceof WebClient - } - - def 'Creating a web client instance model service.'() { - given: 'Web client configuration invoked' - def modelServicesWebClient = objectUnderTest.modelServicesWebClient(webClientBuilder) - expect: 'the system can create an instance for model service' - assert modelServicesWebClient != null - assert modelServicesWebClient instanceof WebClient - } - - def 'Creating a web client instance health service.'() { - given: 'Web client configuration invoked' - def healthChecksWebClient = objectUnderTest.healthChecksWebClient(webClientBuilder) - expect: 'the system can create an instance for health service' - assert healthChecksWebClient != null - assert healthChecksWebClient instanceof WebClient - } -} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfigurationSpec.groovy new file mode 100644 index 0000000000..cb209beef0 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiWebClientsConfigurationSpec.groovy @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.impl.dmi + + +import org.onap.cps.ncmp.config.DmiHttpClientConfig +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.reactive.function.client.WebClient +import spock.lang.Specification + +@SpringBootTest +@ContextConfiguration(classes = [DmiHttpClientConfig]) +@EnableConfigurationProperties +class DmiWebClientsConfigurationSpec extends Specification { + + def webClientBuilder = Mock(WebClient.Builder) { + defaultHeaders(_) >> it + clientConnector(_) >> it + codecs(_) >> it + build() >> Mock(WebClient) + } + + def dmiHttpClientConfiguration = Spy(DmiHttpClientConfig.class) + + def objectUnderTest = new DmiWebClientsConfiguration(dmiHttpClientConfiguration) + + def 'Web client for data services.'() { + when: 'creating a web client for dmi data services' + def result = objectUnderTest.dataServicesWebClient(webClientBuilder) + then: 'a web client is created successfully' + assert result != null + assert result instanceof WebClient + } + + def 'Web client model services.'() { + when: 'creating a web client for dmi model services' + def result = objectUnderTest.modelServicesWebClient(webClientBuilder) + then: 'a web client is created successfully' + assert result != null + assert result instanceof WebClient + } + + def 'Web client health check services.'() { + when: 'creating a web client for dmi health check services' + def result = objectUnderTest.healthChecksWebClient(webClientBuilder) + then: 'a web client is created successfully' + assert result != null + assert result instanceof WebClient + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy index 0c702abea6..dcff2e9b89 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/CmHandleRegistrationServiceSpec.groovy @@ -59,13 +59,12 @@ class CmHandleRegistrationServiceSpec extends Specification { def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler) def mockCpsDataService = Mock(CpsDataService) def mockModuleSyncStartedOnCmHandles = Mock(IMap<String, Object>) - def trustLevelPerDmiPlugin = [:] def mockTrustLevelManager = Mock(TrustLevelManager) def mockAlternateIdChecker = Mock(AlternateIdChecker) def objectUnderTest = Spy(new CmHandleRegistrationService( mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockCpsDataService, mockLcmEventsCmHandleStateHandler, - mockModuleSyncStartedOnCmHandles, trustLevelPerDmiPlugin , mockTrustLevelManager, mockAlternateIdChecker)) + mockModuleSyncStartedOnCmHandles, mockTrustLevelManager, mockAlternateIdChecker)) def setup() { // always accept all cm handles @@ -143,9 +142,6 @@ class CmHandleRegistrationServiceSpec extends Specification { objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'create cm handles registration and sync modules is called with the correct plugin information' 1 * objectUnderTest.processCreatedCmHandles(dmiPluginRegistration, _) - and: 'dmi is added to the dmi trustLevel map' - assert trustLevelPerDmiPlugin.size() == 1 - assert trustLevelPerDmiPlugin.containsKey(expectedDmiPluginRegisteredName) where: scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin || expectedDmiPluginRegisteredName 'combined DMI plugin' | 'service1' | '' | '' || 'service1' @@ -212,7 +208,7 @@ class CmHandleRegistrationServiceSpec extends Specification { when: 'registration is updated' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) then: 'trustLevel is set for the created cm-handle' - 1 * mockTrustLevelManager.handleInitialRegistrationOfTrustLevels(expectedMapping) + 1 * mockTrustLevelManager.registerCmHandles(expectedMapping) where: scenario | registrationTrustLevel || expectedMapping 'with trusted cm handle' | TrustLevel.COMPLETE || [ 'ch-1' : TrustLevel.COMPLETE ] diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy index 716efd8fdb..1fed453fa5 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/NetworkCmProxyInventoryFacadeSpec.groovy @@ -35,6 +35,8 @@ import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.inventory.models.CmHandleState import org.onap.cps.ncmp.impl.inventory.models.LockReasonCategory import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle +import org.onap.cps.ncmp.impl.inventory.trustlevel.TrustLevelManager +import org.onap.cps.ncmp.impl.utils.AlternateIdMatcher import org.onap.cps.spi.model.ConditionProperties import org.onap.cps.utils.JsonObjectMapper import spock.lang.Specification @@ -46,10 +48,11 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { def mockParameterizedCmHandleQueryService = Mock(ParameterizedCmHandleQueryService) def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) def mockInventoryPersistence = Mock(InventoryPersistence) + def mockTrustLevelManager = Mock(TrustLevelManager) + def mockAlternateIdMatcher = Mock(AlternateIdMatcher) + def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper, mockTrustLevelManager, mockAlternateIdMatcher) def trustLevelPerCmHandle = [:] - def objectUnderTest = new NetworkCmProxyInventoryFacade(mockCmHandleRegistrationService, mockCmHandleQueryService, mockParameterizedCmHandleQueryService, mockInventoryPersistence, spiedJsonObjectMapper, trustLevelPerCmHandle) - def 'Update DMI Registration'() { given: 'an (updated) dmi plugin registration' def dmiPluginRegistration = Mock(DmiPluginRegistration) @@ -110,7 +113,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { publicProperties: publicProperties, compositeState: compositeState, moduleSetTag: moduleSetTag, alternateId: alternateId) 1 * mockInventoryPersistence.getYangModelCmHandle('ch-1') >> yangModelCmHandle and: 'a trust level for the cm handle in the cache' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + mockTrustLevelManager.getEffectiveTrustLevel(*_) >> TrustLevel.COMPLETE when: 'getting cm handle details for a given cm handle id from ncmp service' def result = objectUnderTest.getNcmpServiceCmHandle('ch-1') then: 'the result is a ncmpServiceCmHandle' @@ -144,7 +147,7 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { assert result == [ 'public prop' : 'some public prop' ] } - def 'Get cm handle composite state'() { + def 'Get cm handle composite state using #scenario'() { given: 'a yang modelled cm handle' def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED, lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.MODULE_SYNC_FAILED).details("lock details").build(), @@ -153,13 +156,21 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { dataStores: dataStores()) def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')] def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')] - def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState) + def cmHandleId = 'some-cm-handle' + def alternateId = 'some-alternate-id' + def yangModelCmHandle = new YangModelCmHandle(id:cmHandleId, alternateId: alternateId, dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState) + and: 'we have corresponding cm handle for the cm handle reference' + 1 * mockAlternateIdMatcher.getCmHandleId(cmHandleRef) >> cmHandleId and: 'the system returns this yang modelled cm handle' - 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle + 1 * mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle when: 'getting cm handle composite state for a given cm handle id from ncmp service' - def result = objectUnderTest.getCmHandleCompositeState('some-cm-handle') + def result = objectUnderTest.getCmHandleCompositeState(cmHandleRef) then: 'the result returns the correct data' assert result == compositeState + where: 'following cm handle reference is used' + scenario | cmHandleRef + 'Cm Handle Reference as cm handle-id' | 'some-cm-handle' + 'Cm Handle Reference as alternate-id' | 'some-alternate-id' } def 'Execute cm handle id search'() { @@ -204,16 +215,16 @@ class NetworkCmProxyInventoryFacadeSpec extends Specification { mockParameterizedCmHandleQueryService.queryCmHandles( spiedJsonObjectMapper.convertToValueType(cmHandleQueryApiParameters, CmHandleQueryServiceParameters.class)) >> [new NcmpServiceCmHandle(cmHandleId: 'ch-0'), new NcmpServiceCmHandle(cmHandleId: 'ch-1')] - and: ' a trust level for ch-1' - trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + and: 'a trust level for cm handles' + mockTrustLevelManager.getEffectiveTrustLevel(*_) >> TrustLevel.COMPLETE when: 'execute cm handle search is called' def result = objectUnderTest.executeCmHandleSearch(cmHandleQueryApiParameters) then: 'result consists of the two cm handles returned by the CPS Data Service' assert result.size() == 2 assert result[0].cmHandleId == 'ch-0' assert result[1].cmHandleId == 'ch-1' - and: 'only ch-1 has a trust level' - assert result[0].currentTrustLevel == null + and: 'cm handles have trust level' + assert result[0].currentTrustLevel == TrustLevel.COMPLETE assert result[1].currentTrustLevel == TrustLevel.COMPLETE } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy index 196a1cd360..c80aa7b242 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/DmiModelOperationsSpec.groovy @@ -25,7 +25,7 @@ import com.fasterxml.jackson.core.JsonProcessingException import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.impl.dmi.DmiOperationsBaseSpec import org.onap.cps.ncmp.impl.dmi.DmiProperties -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import org.onap.cps.spi.model.ModuleReference import org.onap.cps.utils.JsonObjectMapper import org.spockframework.spring.SpringBean diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy index 6db304acd1..c7d0616bb2 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DeviceTrustLevelMessageConsumerSpec.groovy @@ -49,7 +49,7 @@ class DeviceTrustLevelMessageConsumerSpec extends Specification { when: 'the event is consumed' objectUnderTest.deviceTrustLevelListener(consumerRecord) then: 'cm handles are stored with correct trust level' - 1 * mockTrustLevelManager.handleUpdateOfDeviceTrustLevel('"ch-1"', TrustLevel.COMPLETE) + 1 * mockTrustLevelManager.updateCmHandleTrustLevel('"ch-1"', TrustLevel.COMPLETE) } def createTrustLevelEvent(eventPayload) { diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy index 0a34d267c5..32f4503005 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/DmiPluginTrustLevelWatchDogSpec.groovy @@ -22,8 +22,8 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.dmi.DmiRestClient -import org.onap.cps.ncmp.impl.dmi.UrlTemplateParameters import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService +import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters import reactor.core.publisher.Mono import spock.lang.Specification @@ -46,7 +46,7 @@ class DmiPluginTrustLevelWatchDogSpec extends Specification { when: 'dmi watch dog method runs' objectUnderTest.checkDmiAvailability() then: 'the update delegated to manager' - numberOfCalls * mockTrustLevelManager.handleUpdateOfDmiTrustLevel('dmi-1', _, newDmiTrustLevel) + numberOfCalls * mockTrustLevelManager.updateDmi('dmi-1', _, newDmiTrustLevel) where: 'the following parameters are used' dmiHealhStatus | dmiOldTrustLevel | newDmiTrustLevel || numberOfCalls 'UP' | TrustLevel.COMPLETE | TrustLevel.COMPLETE || 0 diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy index b5bfbc165c..95d3db16cb 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/trustlevel/TrustLevelManagerSpec.groovy @@ -20,10 +20,12 @@ package org.onap.cps.ncmp.impl.inventory.trustlevel +import org.onap.cps.ncmp.api.inventory.models.DmiPluginRegistration import org.onap.cps.ncmp.api.inventory.models.TrustLevel import org.onap.cps.ncmp.impl.inventory.InventoryPersistence import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle import org.onap.cps.ncmp.utils.events.CmAvcEventPublisher +import spock.lang.Ignore import spock.lang.Specification class TrustLevelManagerSpec extends Specification { @@ -35,11 +37,20 @@ class TrustLevelManagerSpec extends Specification { def mockAttributeValueChangeEventPublisher = Mock(CmAvcEventPublisher) def objectUnderTest = new TrustLevelManager(trustLevelPerCmHandle, trustLevelPerDmiPlugin, mockInventoryPersistence, mockAttributeValueChangeEventPublisher) + def 'Initial dmi registration'() { + given: 'a dmi plugin' + def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'dmi-1') + when: 'method to register to the cache is called' + objectUnderTest.registerDmiPlugin(dmiPluginRegistration) + then: 'dmi plugin in the cache and trusted' + assert trustLevelPerDmiPlugin.get('dmi-1') == TrustLevel.COMPLETE + } + def 'Initial cm handle registration'() { given: 'two cm handles: one with no trust level and one trusted' def cmHandleModelsToBeCreated = ['ch-1': null, 'ch-2': TrustLevel.COMPLETE] - when: 'the initial registration handled' - objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated) + when: 'method to register to the cache is called' + objectUnderTest.registerCmHandles(cmHandleModelsToBeCreated) then: 'no notification sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) and: 'both cm handles are in the cache and are trusted' @@ -50,8 +61,8 @@ class TrustLevelManagerSpec extends Specification { def 'Initial cm handle registration with a cm handle that is not trusted'() { given: 'a not trusted cm handle' def cmHandleModelsToBeCreated = ['ch-2': TrustLevel.NONE] - when: 'the initial registration handled' - objectUnderTest.handleInitialRegistrationOfTrustLevels(cmHandleModelsToBeCreated) + when: 'method to register to the cache is called' + objectUnderTest.registerCmHandles(cmHandleModelsToBeCreated) then: 'notification is sent' 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) } @@ -62,7 +73,7 @@ class TrustLevelManagerSpec extends Specification { and: 'a trusted cm handle' trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) when: 'the update is handled' - objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.NONE) + objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.NONE) then: 'notification is sent' 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'COMPLETE', 'NONE') and: 'the dmi in the cache is not trusted' @@ -75,54 +86,89 @@ class TrustLevelManagerSpec extends Specification { and: 'a trusted cm handle' trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) when: 'the update is handled' - objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE) + objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.COMPLETE) then: 'no notification is sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) and: 'the dmi in the cache is trusted' assert trustLevelPerDmiPlugin.get('my-dmi') == TrustLevel.COMPLETE } - def 'Device trust level updated'() { + def 'CmHandle trust level updated'() { given: 'a non trusted cm handle' trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) and: 'a trusted dmi plugin' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'inventory persistence service returns yang model cm handle' mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi') - when: 'update of device to COMPLETE trust level handled' - objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.COMPLETE) + when: 'update of CmHandle to COMPLETE trust level handled' + objectUnderTest.updateCmHandleTrustLevel('ch-1', TrustLevel.COMPLETE) then: 'the cm handle in the cache is trusted' assert trustLevelPerCmHandle.get('ch-1', TrustLevel.COMPLETE) and: 'notification is sent' 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent('ch-1', 'trustLevel', 'NONE', 'COMPLETE') } - def 'Device trust level updated with same value'() { + def 'CmHandle trust level updated with same value'() { given: 'a non trusted cm handle' trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) and: 'a trusted dmi plugin' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.COMPLETE) and: 'inventory persistence service returns yang model cm handle' mockInventoryPersistence.getYangModelCmHandle('ch-1') >> new YangModelCmHandle(id: 'ch-1', dmiDataServiceName: 'my-dmi') - when: 'update of device trust to the same level (NONE)' - objectUnderTest.handleUpdateOfDeviceTrustLevel('ch-1', TrustLevel.NONE) + when: 'update of CmHandle trust to the same level (NONE)' + objectUnderTest.updateCmHandleTrustLevel('ch-1', TrustLevel.NONE) then: 'the cm handle in the cache is not trusted' assert trustLevelPerCmHandle.get('ch-1', TrustLevel.NONE) and: 'no notification is sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) } - def 'Dmi trust level restored to complete with non trusted device'() { + def 'Dmi trust level restored to complete with non trusted CmHandle'() { given: 'a non trusted dmi' trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) - and: 'a non trusted device' + and: 'a non trusted CmHandle' trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) when: 'restore the dmi trust level to COMPLETE' - objectUnderTest.handleUpdateOfDmiTrustLevel('my-dmi', ['ch-1'], TrustLevel.COMPLETE) + objectUnderTest.updateDmi('my-dmi', ['ch-1'], TrustLevel.COMPLETE) then: 'the cm handle in the cache is still NONE' assert trustLevelPerCmHandle.get('ch-1') == TrustLevel.NONE and: 'no notification is sent' 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) } + @Ignore + // TODO: CPS-2375 + def 'Select effective trust level among CmHandle and dmi plugin'() { + given: 'a non trusted dmi' + trustLevelPerDmiPlugin.put('my-dmi', TrustLevel.NONE) + and: 'a trusted CmHandle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + when: 'effective trust level selected' + def effectiveTrustLevel = objectUnderTest.getEffectiveTrustLevel('ch-1') + then: 'effective trust level is trusted' + assert effectiveTrustLevel == TrustLevel.NONE + } + + def 'CmHandle trust level (COMPLETE) removed'() { + given: 'a trusted cm handle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.COMPLETE) + when: 'the remove is handled' + objectUnderTest.removeCmHandles(['ch-1']) + then: 'cm handle removed from the cache' + assert trustLevelPerCmHandle.get('ch-1') == null + and: 'notification is sent' + 1 * mockAttributeValueChangeEventPublisher.publishAvcEvent(_,'trustLevel','COMPLETE','NONE') + } + + def 'CmHandle trust level (NONE) removed'() { + given: 'a non-trusted cm handle' + trustLevelPerCmHandle.put('ch-1', TrustLevel.NONE) + when: 'the remove is handled' + objectUnderTest.removeCmHandles(['ch-1']) + then: 'cm handle removed from the cache' + assert trustLevelPerCmHandle.get('ch-1') == null + and: 'no notification is sent' + 0 * mockAttributeValueChangeEventPublisher.publishAvcEvent(*_) + } + } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfigurationSpec.groovy new file mode 100644 index 0000000000..cf5e1a383c --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/policyexecutor/PolicyExecutorWebClientConfigurationSpec.groovy @@ -0,0 +1,53 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2024 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.cps.ncmp.impl.policyexecutor + +import org.onap.cps.ncmp.config.PolicyExecutorHttpClientConfig +import org.springframework.boot.context.properties.EnableConfigurationProperties +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.reactive.function.client.WebClient +import spock.lang.Specification + +@SpringBootTest +@ContextConfiguration(classes = [PolicyExecutorHttpClientConfig]) +@EnableConfigurationProperties +class PolicyExecutorWebClientConfigurationSpec extends Specification { + + def webClientBuilder = Mock(WebClient.Builder) { + defaultHeaders(_) >> it + clientConnector(_) >> it + codecs(_) >> it + build() >> Mock(WebClient) + } + + def httpClientConfiguration = Spy(PolicyExecutorHttpClientConfig.class) + + def objectUnderTest = new PolicyExecutorWebClientConfiguration(httpClientConfiguration) + + def 'Web client policy executor.'() { + when: 'create a web client for policy executor' + def result = objectUnderTest.policyExecutorWebClient(webClientBuilder) + then: 'a web client is created successfully' + assert result != null + assert result instanceof WebClient + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilderSpec.groovy index 9e1b37023b..9e051156f7 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/dmi/DmiServiceUrlTemplateBuilderSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/http/RestServiceUrlTemplateBuilderSpec.groovy @@ -18,14 +18,13 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.ncmp.impl.dmi - +package org.onap.cps.ncmp.impl.utils.http import spock.lang.Specification -class DmiServiceUrlTemplateBuilderSpec extends Specification { +class RestServiceUrlTemplateBuilderSpec extends Specification { - def objectUnderTest = new DmiServiceUrlTemplateBuilder() + def objectUnderTest = new RestServiceUrlTemplateBuilder() def 'Build URL template parameters with (variable) path segments and query parameters.'() { given: 'the URL details are given to the builder' @@ -35,9 +34,9 @@ class DmiServiceUrlTemplateBuilderSpec extends Specification { objectUnderTest.queryParameter('param1', 'abc') objectUnderTest.queryParameter('param2', 'value?with#special:characters') when: 'the URL template parameters are created' - def result = objectUnderTest.createUrlTemplateParameters('myDmiServer', 'myBasePath') + def result = objectUnderTest.createUrlTemplateParameters('myServer', 'myBasePath') then: 'the URL template contains variable names instead of value and un-encoded fixed segment' - assert result.urlTemplate == 'myDmiServer/myBasePath/v1/segment/{myVariableSegment}/segment?with:special&characters?param1={param1}¶m2={param2}' + assert result.urlTemplate == 'myServer/myBasePath/v1/segment/{myVariableSegment}/segment?with:special&characters?param1={param1}¶m2={param2}' and: 'URL variables contains name and un-encoded value pairs' assert result.urlVariables == ['myVariableSegment': 'someValue', 'param1': 'abc', 'param2': 'value?with#special:characters'] } @@ -46,7 +45,7 @@ class DmiServiceUrlTemplateBuilderSpec extends Specification { given: 'the query parameter is given to the builder' objectUnderTest.queryParameter('my¶m', 'special&characters=are?not\\encoded') when: 'the URL template parameters are created' - def result = objectUnderTest.createUrlTemplateParameters('myDmiServer', 'myBasePath') + def result = objectUnderTest.createUrlTemplateParameters('myServer', 'myBasePath') then: 'Special characters are not encoded' assert result.urlVariables == ['my¶m': 'special&characters=are?not\\encoded'] } @@ -55,7 +54,7 @@ class DmiServiceUrlTemplateBuilderSpec extends Specification { when: 'the query parameter is given to the builder' objectUnderTest.queryParameter('param', value) and: 'the URL template parameters are create' - def result = objectUnderTest.createUrlTemplateParameters('myDmiServer', 'myBasePath') + def result = objectUnderTest.createUrlTemplateParameters('myServer', 'myBasePath') then: 'no parameter gets added' assert result.urlVariables.isEmpty() where: 'the following parameter values are used' diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml index 759de834ab..72d074ab5f 100644 --- a/cps-ncmp-service/src/test/resources/application.yml +++ b/cps-ncmp-service/src/test/resources/application.yml @@ -47,15 +47,26 @@ ncmp: dmi: httpclient: data-services: - pendingAcquireMaxCount: 22 - connectionTimeoutInSeconds: 123 - maximumInMemorySizeInMegabytes: 7 - readTimeoutInSeconds: 33 + maximumInMemorySizeInMegabytes: 1 + maximumConnectionsTotal: 2 + pendingAcquireMaxCount: 3 + connectionTimeoutInSeconds: 4 + readTimeoutInSeconds: 5 + writeTimeoutInSeconds: 6 model-services: - pendingAcquireMaxCount: 44 - connectionTimeoutInSeconds: 456 - maximumInMemorySizeInMegabytes: 8 - maximumConnectionsTotal: 111 + maximumInMemorySizeInMegabytes: 11 + maximumConnectionsTotal: 12 + pendingAcquireMaxCount: 13 + connectionTimeoutInSeconds: 14 + readTimeoutInSeconds: 15 + writeTimeoutInSeconds: 16 + healthCheckServices: + maximumInMemorySizeInMegabytes: 21 + maximumConnectionsTotal: 22 + pendingAcquireMaxCount: 23 + connectionTimeoutInSeconds: 24 + readTimeoutInSeconds: 25 + writeTimeoutInSeconds: 26 auth: username: some-user password: some-password @@ -75,6 +86,14 @@ ncmp: server: address: "http://localhost" port: "8785" + httpclient: + all-services: + maximumInMemorySizeInMegabytes: 31 + maximumConnectionsTotal: 32 + pendingAcquireMaxCount: 33 + connectionTimeoutInSeconds: 34 + readTimeoutInSeconds: 35 + writeTimeoutInSeconds: 36 # Custom Hazelcast Config. hazelcast: diff --git a/cps-parent/pom.xml b/cps-parent/pom.xml index a4aeb5b5a5..430f4b5cd8 100644 --- a/cps-parent/pom.xml +++ b/cps-parent/pom.xml @@ -410,30 +410,6 @@ <artifactId>sonar-maven-plugin</artifactId> <version>3.9.1.2184</version> </plugin> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <version>1.6.0</version> - <executions> - <execution> - <id>generate-csv</id> - <phase>prepare-package</phase> - <goals> - <goal>exec</goal> - </goals> - </execution> - </executions> - <configuration> - <executable>${script.executor}</executable> - <workingDirectory>${parent.directory}/cps-ri/src/main/resources/</workingDirectory> - <arguments> - <argument>yangResourceCsvGenerator.py</argument> - <argument>dmi-registry@2021-12-13</argument> - <argument>dmi-registry@2022-02-10</argument> - <argument>dmi-registry@2022-05-10</argument> - </arguments> - </configuration> - </plugin> </plugins> </build> </project> diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md b/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md deleted file mode 100644 index 212acb9006..0000000000 --- a/cps-ri/src/main/resources/changelog/db/changes/data/dmi/generated-csv/README.md +++ /dev/null @@ -1,23 +0,0 @@ -<!-- - ============LICENSE_START======================================================= - Copyright (C) 2022 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========================================================= ---> - -##Placeholder folder for generated CSV files as part of yang models. - -Do not remove this folder
\ No newline at end of file diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang deleted file mode 100644 index ed3559bf61..0000000000 --- a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2021-12-13.yang +++ /dev/null @@ -1,63 +0,0 @@ -module dmi-registry { - - yang-version 1.1; - - namespace "org:onap:cps:ncmp"; - - prefix dmi-reg; - - contact "dylan.byrne@est.tech"; - - revision "2021-05-20" { - description - "Initial Version"; - } - - revision "2021-10-20" { - description - "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility"; - } - - revision "2021-12-13" { - description - "Added new list of public additonal properties for a Cm-Handle which are exposed to clients of the NCMP interface"; - } - - container dmi-registry { - list cm-handles { - key "id"; - leaf id { - type string; - } - leaf dmi-service-name { - type string; - } - leaf dmi-data-service-name { - type string; - } - leaf dmi-model-service-name { - type string; - } - - list additional-properties { - key "name"; - leaf name { - type string; - } - leaf value { - type string; - } - } - - list public-properties { - key "name"; - leaf name { - type string; - } - leaf value { - type string; - } - } - } - } -}
\ No newline at end of file diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang deleted file mode 100644 index 3c6d990c5d..0000000000 --- a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-02-10.yang +++ /dev/null @@ -1,81 +0,0 @@ -module dmi-registry { - - yang-version 1.1; - - namespace "org:onap:cps:ncmp"; - - prefix dmi-reg; - - contact "toine.siebelink@est.tech"; - - revision "2022-02-10" { - description - "Added State, LockReason, LockReasonDetails to aid with cmHandle sync and timestamp to aid with retry/timeout scenarios"; - } - - revision "2021-12-13" { - description - "Added new list of public additional properties for a Cm-Handle which are exposed to clients of the NCMP interface"; - } - - revision "2021-10-20" { - description - "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility"; - } - - revision "2021-05-20" { - description - "Initial Version"; - } - - container dmi-registry { - list cm-handles { - key "id"; - leaf id { - type string; - } - leaf dmi-service-name { - type string; - } - leaf dmi-data-service-name { - type string; - } - leaf dmi-model-service-name { - type string; - } - - list additional-properties { - key "name"; - leaf name { - type string; - } - leaf value { - type string; - } - } - - list public-properties { - key "name"; - leaf name { - type string; - } - leaf value { - type string; - } - } - - leaf state { - type string; - } - leaf lock-reason { - type string; - } - leaf lock-reason-details { - type string; - } - leaf last-update-time { - type string; - } - } - } -} diff --git a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang b/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang deleted file mode 100644 index 77517968c6..0000000000 --- a/cps-ri/src/main/resources/changelog/db/changes/data/yang-models/dmi-registry@2022-05-10.yang +++ /dev/null @@ -1,123 +0,0 @@ -module dmi-registry { - - yang-version 1.1; - - namespace "org:onap:cps:ncmp"; - - prefix dmi-reg; - - contact "toine.siebelink@est.tech"; - - revision "2022-05-10" { - description - "Added DataSyncEnabled, SyncState with State, LastSyncTime, DataStoreSyncState with Operational and Running syncstate"; - } - - revision "2022-02-10" { - description - "Added State, LockReason, LockReasonDetails to aid with cmHandle sync and timestamp to aid with retry/timeout scenarios"; - } - - revision "2021-12-13" { - description - "Added new list of public additional properties for a Cm-Handle which are exposed to clients of the NCMP interface"; - } - - revision "2021-10-20" { - description - "Added dmi-data-service-name & dmi-model-service-name to allow separate DMI instances for each responsibility"; - } - - revision "2021-05-20" { - description - "Initial Version"; - } - - grouping LockReason { - leaf reason { - type string; - } - leaf details { - type string; - } - } - - grouping SyncState { - leaf sync-state { - type string; - } - leaf last-sync-time { - type string; - } - } - - grouping Datastores { - container operational { - uses SyncState; - } - container running { - uses SyncState; - } - } - - container dmi-registry { - list cm-handles { - key "id"; - leaf id { - type string; - } - leaf dmi-service-name { - type string; - } - leaf dmi-data-service-name { - type string; - } - leaf dmi-model-service-name { - type string; - } - - list additional-properties { - key "name"; - leaf name { - type string; - } - leaf value { - type string; - } - } - - list public-properties { - key "name"; - leaf name { - type string; - } - leaf value { - type string; - } - } - - container state { - leaf cm-handle-state { - type string; - } - - container lock-reason { - uses LockReason; - } - - leaf last-update-time { - type string; - } - - leaf data-sync-enabled { - type boolean; - default "false"; - } - - container datastores { - uses Datastores; - } - } - } - } -}
\ No newline at end of file diff --git a/cps-ri/src/main/resources/yangResourceCsvGenerator.py b/cps-ri/src/main/resources/yangResourceCsvGenerator.py deleted file mode 100644 index 3a076d4378..0000000000 --- a/cps-ri/src/main/resources/yangResourceCsvGenerator.py +++ /dev/null @@ -1,66 +0,0 @@ -# ============LICENSE_START======================================================= -# Copyright (C) 2022 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========================================================= - - -import csv -import datetime -import hashlib -import sys -import re - -yang_source = '' -checksum = '' -regexForModuleName = '(?<=module)(.*)(?={)' -regexForRevision = '(?<=revision)(.*)(?={)' - -def main(): - for yang_source in sys.argv[1:]: - checksum = hashlib.sha256(str(yang_source).encode()).hexdigest() - - with open('changelog/db/changes/data/yang-models/' + yang_source + '.yang', 'r') as content: - dmiRegistry = content.read() - - try: - latestRevision = re.search(regexForRevision, dmiRegistry).group(0).replace('\"','').strip() - except: - print("ERROR IN in yangResourceCsvGenerator.py: Unable to find revision for " + yang_source + '.yang') - - try: - module_name = re.search(regexForModuleName, dmiRegistry).group(0).strip() - except: - print("ERROR IN in yangResourceCsvGenerator.py: Unable to find module name for " + yang_source + '.yang') - - #If true, file was created after module_name and revision columns were added to yang-resources table - writeWithModuleNameAndRevision = yang_source != 'dmi-registry@2021-12-13' - - try: - # open the file in the write mode - with open('changelog/db/changes/data/dmi/generated-csv/generated_yang_resource_' + yang_source + '.csv', 'w', newline='') \ - as file: - writer = csv.writer(file, delimiter='|') - if(writeWithModuleNameAndRevision): - writer.writerow(["name", "content", "checksum", "module_name", "revision"]) - writer.writerow([yang_source + '.yang', dmiRegistry, checksum, module_name, latestRevision]) - else: - writer.writerow(["name", "content", "checksum"]) - writer.writerow([yang_source + '.yang', dmiRegistry, checksum]) - except: - print("ERROR IN in yangResourceCsvGenerator.py: Unable to write to changelog/db/changes/data/dmi/generated-csv/generated_yang_resource_" + yang_source + ".csv") - - -main()
\ No newline at end of file diff --git a/csit/install-deps.sh b/csit/install-deps.sh new file mode 100755 index 0000000000..ef0b96a799 --- /dev/null +++ b/csit/install-deps.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright 2024 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. +# + +echo "---> install-deps.sh" +echo "Installing dependencies" + +# Create directory for downloaded binaries. +mkdir -p bin +touch bin/.gitignore + +# Add it to the PATH, so downloaded versions will be used. +export PATH="$(pwd)/bin:$PATH" + +# Download docker-compose. +if [ ! -x bin/docker-compose ]; then + echo " Downloading docker-compose" + curl -s -L https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 > bin/docker-compose + chmod +x bin/docker-compose +else + echo " docker-compose already installed" +fi +docker-compose version diff --git a/csit/plans/cps/setup.sh b/csit/plans/cps/setup.sh index 80829eba14..036f14b82f 100755 --- a/csit/plans/cps/setup.sh +++ b/csit/plans/cps/setup.sh @@ -1,7 +1,6 @@ #!/bin/bash # # Copyright 2016-2017 Huawei Technologies Co., Ltd. -# Modifications Copyright (C) 2022 Nordix Foundation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,7 +18,7 @@ # Modifications copyright (c) 2020-2021 Samsung Electronics Co., Ltd. # Modifications Copyright (C) 2021 Pantheon.tech # Modifications Copyright (C) 2021 Bell Canada. -# Modifications Copyright (C) 2021 Nordix Foundation. +# Modifications Copyright (C) 2021-2024 Nordix Foundation. # # Branched from ccsdk/distribution to this repository Feb 23, 2021 # @@ -59,10 +58,6 @@ export $(cut -d= -f1 $WORKSPACE/plans/cps/test.properties) ###################### setup cps-ncmp ############################ cd $CPS_HOME/docker-compose -curl -L https://github.com/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > docker-compose -chmod +x docker-compose -docker-compose version - # start CPS/NCMP, DMI Plugin, and PostgreSQL containers with docker compose docker-compose --profile dmi-service up -d @@ -82,4 +77,4 @@ check_health $DMI_HOST:$DMI_PORT 'dmi-plugin' ###################### ROBOT Configurations ########################## # Pass variables required for Robot test suites in ROBOT_VARIABLES -ROBOT_VARIABLES="-v CPS_CORE_HOST:$CPS_CORE_HOST -v CPS_CORE_PORT:$CPS_CORE_PORT -v DMI_HOST:$LOCAL_IP -v DMI_PORT:$DMI_PORT -v DMI_CSIT_STUB_HOST:$LOCAL_IP -v DMI_CSIT_STUB_PORT:$DMI_DEMO_STUB_PORT -v DMI_AUTH_ENABLED:$DMI_AUTH_ENABLED -v DATADIR_CPS_CORE:$WORKSPACE/data/cps-core -v DATADIR_NCMP:$WORKSPACE/data/ncmp -v DATADIR_SUBS_NOTIFICATION:$WORKSPACE/data/subscription-notification --exitonfailure"
\ No newline at end of file +ROBOT_VARIABLES="-v CPS_CORE_HOST:$CPS_CORE_HOST -v CPS_CORE_PORT:$CPS_CORE_PORT -v DMI_HOST:$LOCAL_IP -v DMI_PORT:$DMI_PORT -v DMI_CSIT_STUB_HOST:$LOCAL_IP -v DMI_CSIT_STUB_PORT:$DMI_DEMO_STUB_PORT -v DMI_AUTH_ENABLED:$DMI_AUTH_ENABLED -v DATADIR_CPS_CORE:$WORKSPACE/data/cps-core -v DATADIR_NCMP:$WORKSPACE/data/ncmp -v DATADIR_SUBS_NOTIFICATION:$WORKSPACE/data/subscription-notification --exitonfailure" diff --git a/csit/run-project-csit.sh b/csit/run-project-csit.sh index fcb3c925c1..f362cc7130 100755 --- a/csit/run-project-csit.sh +++ b/csit/run-project-csit.sh @@ -2,6 +2,7 @@ # # Copyright 2020-2021 © Samsung Electronics Co., Ltd. # Modifications Copyright (C) 2021 Pantheon.tech +# Modifications Copyright (C) 2024 Nordix Foundation. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,6 +29,8 @@ rm -rf ${WORKSPACE}/archives mkdir -p ${WORKSPACE}/archives cd ${WORKSPACE} +source install-deps.sh + # Execute all test-suites defined under plans subdirectory for dir in plans/*/ do diff --git a/csit/tests/cps-trust-level/cps-trust-level.robot b/csit/tests/cps-trust-level/cps-trust-level.robot index e4deeff32b..4db0115871 100644 --- a/csit/tests/cps-trust-level/cps-trust-level.robot +++ b/csit/tests/cps-trust-level/cps-trust-level.robot @@ -36,7 +36,7 @@ ${ncmpBasePath} /ncmp/v1 ${dmiUrl} http://${DMI_HOST}:${DMI_PORT} ${jsonCreateCmHandles} {"dmiPlugin":"${dmiUrl}","dmiDataPlugin":"","dmiModelPlugin":"","createdCmHandles":[{"trustLevel":"COMPLETE","cmHandle":"CH-1"},{"trustLevel":"COMPLETE","cmHandle":"CH-2"},{"cmHandle":"CH-3"},{"trustLevel":"NONE","cmHandle":"CH-4"}]} ${jsonTrustLevelPropertyQueryParameters} {"cmHandleQueryParameters": [{"conditionName": "cmHandleWithTrustLevel", "conditionParameters": [ {"trustLevel": "COMPLETE"} ] }]} -${jsonTrustLevelQueryResponse} {"data":{"attributeValueChange":[{"attributeName":"trustLevel","newAttributeValue":"NONE"}]}} +${jsonTrustLevelEventPayload} {"data":{"attributeValueChange":[{"attributeName":"trustLevel","oldAttributeValue":"COMPLETE","newAttributeValue":"NONE"}]}} *** Test Cases *** Register data node @@ -55,9 +55,9 @@ Verify notification Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_specversion" "1.0" Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_source" "NCMP" Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_type" "org.onap.cps.ncmp.events.avc.ncmp_to_client.AvcEvent" - Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_correlationid" "CH-4" + Compare Header Values ${header_key_value_pair[0]} ${header_key_value_pair[1]} "ce_correlationid" "CmHandleForDelete" END - Should Be Equal As Strings ${payload} ${jsonTrustLevelQueryResponse} + Should Be Equal As Strings ${payload} ${jsonTrustLevelEventPayload} [Teardown] Basic Teardown ${group_id} Retrieve CM Handle ids where query parameters Match (trust level query) diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy index 241d31a642..4d04eeeb81 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/DataJobResultServiceSpec.groovy @@ -39,7 +39,6 @@ class DataJobResultServiceSpec extends CpsIntegrationSpecBase { when: 'the data job status checked' def result = dataJobResultService.getDataJobResult(authorization, dmiServiceName, dataProducerId, dataProducerJobId, destination) then: 'the status is that defined in the mock service.' - assert result != null assert result == '{ "result": "some result"}' } } diff --git a/k6-tests/install-deps.sh b/k6-tests/install-deps.sh new file mode 100755 index 0000000000..bb5deb93dd --- /dev/null +++ b/k6-tests/install-deps.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# +# Copyright 2024 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. +# + +echo "---> install-deps.sh" +echo "Installing dependencies" + +# Create directory for downloaded binaries. +mkdir -p bin +touch bin/.gitignore + +# Add it to the PATH, so downloaded versions will be used. +export PATH="$(pwd)/bin:$PATH" + +# Download docker-compose. +if [ ! -x bin/docker-compose ]; then + echo " Downloading docker-compose" + curl -s -L https://github.com/docker/compose/releases/download/v2.29.2/docker-compose-linux-x86_64 > bin/docker-compose + chmod +x bin/docker-compose +else + echo " docker-compose already installed" +fi +docker-compose version + +# Download k6 with kafka extension. +if [ ! -x bin/k6 ]; then + echo " Downloading k6 with kafka extension" + curl -s -L https://github.com/mostafa/xk6-kafka/releases/download/v0.26.0/xk6-kafka_v0.26.0_linux_amd64.tar.gz | tar -xz + mv dist/xk6-kafka_v0.26.0_linux_amd64 bin/k6 && rmdir dist + chmod +x bin/k6 +else + echo " k6 already installed" +fi +k6 --version diff --git a/k6-tests/run-k6-tests.sh b/k6-tests/run-k6-tests.sh index 9b8747b1ff..b1ad38911a 100755 --- a/k6-tests/run-k6-tests.sh +++ b/k6-tests/run-k6-tests.sh @@ -31,6 +31,10 @@ trap on_exit EXIT pushd "$(dirname "$0")" || exit 1 +# Install needed dependencies. +source install-deps.sh + +# Run k6 test suite. ./setup.sh ./ncmp/run-all-tests.sh NCMP_RESULT=$? diff --git a/k6-tests/teardown.sh b/k6-tests/teardown.sh index 1b4d721a23..7693dc03a4 100755 --- a/k6-tests/teardown.sh +++ b/k6-tests/teardown.sh @@ -19,4 +19,10 @@ echo '================================== docker info ==========================' docker ps -a echo 'Stopping, Removing containers and volumes...' -docker-compose -f ../docker-compose/docker-compose.yml --profile dmi-stub down --volumes +docker_compose_cmd="docker-compose -f ../docker-compose/docker-compose.yml --profile dmi-stub down --volumes" +# Set an environment variable CLEAN_DOCKER_IMAGES=1 to also remove docker images when done (used on jenkins job) +if [ "${CLEAN_DOCKER_IMAGES:-0}" -eq 1 ]; then + $docker_compose_cmd --rmi all +else + $docker_compose_cmd +fi |