Merge "Remove Notification code for updated events"
authorToine Siebelink <toine.siebelink@est.tech>
Mon, 18 Dec 2023 15:16:26 +0000 (15:16 +0000)
committerGerrit Code Review <gerrit@onap.org>
Mon, 18 Dec 2023 15:16:26 +0000 (15:16 +0000)
cps-ncmp-service/pom.xml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java [new file with mode: 0644]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
cps-ncmp-service/src/main/resources/models/dmi-registry@2023-11-27.yang [moved from integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2022-05-10.yang with 74% similarity]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy [new file with mode: 0644]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
integration-test/src/test/groovy/org/onap/cps/integration/performance/base/NcmpPerfTestBase.groovy
integration-test/src/test/resources/data/ncmp-registry/dmi-registry@2023-11-27.yang [moved from cps-ncmp-service/src/main/resources/models/dmi-registry@2023-08-23.yang with 94% similarity]

index f448c8f..e9faf43 100644 (file)
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents.client5</groupId>
+            <artifactId>httpclient5</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.cloudevents</groupId>
             <artifactId>cloudevents-json-jackson</artifactId>
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/HttpClientConfiguration.java
new file mode 100644 (file)
index 0000000..aaa4f1e
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.api.impl.config;
+
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.convert.DurationUnit;
+
+@Getter
+@Setter
+@ConfigurationProperties(prefix = "httpclient5", ignoreUnknownFields = true)
+public class HttpClientConfiguration {
+
+    /**
+     * The maximum time to establish a connection.
+     */
+    @DurationUnit(ChronoUnit.SECONDS)
+    private Duration connectionTimeoutInSeconds = Duration.ofSeconds(180);
+
+    /**
+     * The maximum number of open connections per route.
+     */
+    private int maximumConnectionsPerRoute = 50;
+
+    /**
+     * The maximum total number of open connections.
+     */
+    private int maximumConnectionsTotal = maximumConnectionsPerRoute * 2;
+
+    /**
+     * The duration after which idle connections are evicted.
+     */
+    @DurationUnit(ChronoUnit.SECONDS)
+    private Duration idleConnectionEvictionThresholdInSeconds = Duration.ofSeconds(5);
+
+}
index ffecf9c..4460094 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 package org.onap.cps.ncmp.api.impl.config;
 
-import java.time.Duration;
 import java.util.Arrays;
 import lombok.AccessLevel;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import org.apache.hc.client5.http.config.ConnectionConfig;
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
+import org.apache.hc.client5.http.impl.classic.HttpClients;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
+import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
+import org.apache.hc.core5.util.TimeValue;
+import org.apache.hc.core5.util.Timeout;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.client.RestTemplateBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Scope;
 import org.springframework.http.MediaType;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 import org.springframework.stereotype.Component;
 import org.springframework.web.client.RestTemplate;
 
 @Configuration
+@EnableConfigurationProperties(HttpClientConfiguration.class)
 @RequiredArgsConstructor(access = AccessLevel.PROTECTED)
 public class NcmpConfiguration {
 
-    private static final Duration CONNECTION_TIMEOUT_MILLISECONDS = Duration.ofMillis(180000);
-    private static final Duration READ_TIMEOUT_MILLISECONDS = Duration.ofMillis(180000);
-
     @Getter
     @Component
     public static class DmiProperties {
@@ -60,13 +67,38 @@ public class NcmpConfiguration {
      * Rest template bean.
      *
      * @param restTemplateBuilder the rest template builder
+     * @param httpClientConfiguration the http client configuration
      * @return rest template instance
      */
     @Bean
     @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
-    public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder) {
-        final RestTemplate restTemplate = restTemplateBuilder.setConnectTimeout(CONNECTION_TIMEOUT_MILLISECONDS)
-                .setReadTimeout(READ_TIMEOUT_MILLISECONDS).build();
+    public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder, 
+                                            final HttpClientConfiguration httpClientConfiguration) {
+        
+        final ConnectionConfig connectionConfig = ConnectionConfig.copy(ConnectionConfig.DEFAULT)
+                .setConnectTimeout(Timeout.of(httpClientConfiguration.getConnectionTimeoutInSeconds()))
+                .build();
+        
+        final PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
+                .setDefaultConnectionConfig(connectionConfig)
+                .setMaxConnTotal(httpClientConfiguration.getMaximumConnectionsTotal())
+                .setMaxConnPerRoute(httpClientConfiguration.getMaximumConnectionsPerRoute())
+                .build();
+        
+        final CloseableHttpClient httpClient = HttpClients.custom()
+                .setConnectionManager(connectionManager)
+                .evictExpiredConnections()
+                .evictIdleConnections(
+                        TimeValue.of(httpClientConfiguration.getIdleConnectionEvictionThresholdInSeconds()))
+                .build();
+        
+        final ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
+        
+        final RestTemplate restTemplate = restTemplateBuilder
+                .requestFactory(() -> requestFactory)
+                .setConnectTimeout(httpClientConfiguration.getConnectionTimeoutInSeconds())
+                .build();
+        
         setRestTemplateMessageConverters(restTemplate);
         return restTemplate;
     }
index b805cdc..a27eb6f 100644 (file)
@@ -33,8 +33,8 @@ import org.springframework.stereotype.Service;
 @Service
 public class InventoryModelLoader extends AbstractModelLoader {
 
-    private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2023-08-23.yang";
-    private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2023-08-23";
+    private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2023-11-27.yang";
+    private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2023-11-27";
 
     public InventoryModelLoader(final CpsAdminService cpsAdminService,
                                 final CpsModuleService cpsModuleService,
@@ -8,19 +8,29 @@ module dmi-registry {
 
   contact "toine.siebelink@est.tech";
 
+  revision "2023-11-27" {
+    description
+    "Added alternate-id";
+  }
+
+  revision "2023-08-23" {
+    description
+    "Added module-set-tag";
+  }
+
   revision "2022-05-10" {
     description
-    "Added DataSyncEnabled, SyncState with State, LastSyncTime, DataStoreSyncState with Operational and Running syncstate";
+    "Added data-sync-enabled, sync-state with state, last-sync-time, data-store-sync-state 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";
+    "Added state, lock-reason, lock-reason-details 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";
+    "Added new list of public-properties and additional-properties for a Cm-Handle which are exposed to clients of the NCMP interface";
   }
 
   revision "2021-10-20" {
@@ -75,6 +85,12 @@ module dmi-registry {
       leaf dmi-model-service-name {
         type string;
       }
+      leaf module-set-tag {
+        type string;
+      }
+      leaf alternate-id {
+        type string;
+      }
 
       list additional-properties {
         key "name";
@@ -120,4 +136,5 @@ module dmi-registry {
       }
     }
   }
-}
\ No newline at end of file
+}
+
index 51b00d1..013341f 100644 (file)
@@ -212,7 +212,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
             1 * mockLcmEventsCmHandleStateHandler.initiateStateAdvised(_) >> {
                 args ->
                     {
-                        def cmHandleStatePerCmHandle = (args[0] as Map)
+                        def cmHandleStatePerCmHandle = (args[0] as List)
                         cmHandleStatePerCmHandle.each {
                             assert (it.id == 'cmhandle' && it.dmiServiceName == 'my-server')
                         }
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/HttpClientConfigurationSpec.groovy
new file mode 100644 (file)
index 0000000..941c8b8
--- /dev/null
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 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.api.impl.config
+
+import java.time.Duration
+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 org.springframework.test.context.TestPropertySource
+import org.springframework.test.context.support.AnnotationConfigContextLoader
+import spock.lang.Specification
+
+@SpringBootTest
+@ContextConfiguration(classes = [HttpClientConfiguration])
+@EnableConfigurationProperties(HttpClientConfiguration.class)
+@TestPropertySource(properties = ["httpclient5.connectionTimeoutInSeconds=1", "httpclient5.maximumConnectionsTotal=200"])
+class HttpClientConfigurationSpec extends Specification {
+
+    @Autowired
+    private HttpClientConfiguration httpClientConfiguration
+
+    def 'Test HttpClientConfiguration properties with custom and default values'() {
+        expect: 'custom property values'
+            httpClientConfiguration.getConnectionTimeoutInSeconds() == Duration.ofSeconds(1)
+            httpClientConfiguration.getMaximumConnectionsTotal() == 200
+        and: 'default property values'
+            httpClientConfiguration.getMaximumConnectionsPerRoute() == 50
+            httpClientConfiguration.getIdleConnectionEvictionThresholdInSeconds() == Duration.ofSeconds(5)
+    }
+}
index e1aba79..a4df9b3 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  */
 package org.onap.cps.ncmp.api.impl.config
 
+import org.apache.hc.client5.http.impl.classic.CloseableHttpClient
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.boot.web.client.RestTemplateBuilder
 import org.springframework.http.MediaType
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory
 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
 import org.springframework.test.context.ContextConfiguration
 import org.springframework.web.client.RestTemplate
 import spock.lang.Specification
 
 @SpringBootTest
-@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties])
+@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, HttpClientConfiguration])
 class NcmpConfigurationSpec extends Specification{
 
     @Autowired
     NcmpConfiguration.DmiProperties dmiProperties
-
+    
+    @Autowired
+    HttpClientConfiguration httpClientConfiguration
+    
     def mockRestTemplateBuilder = new RestTemplateBuilder()
 
     def 'NcmpConfiguration Construction.'() {
@@ -48,11 +53,14 @@ class NcmpConfigurationSpec extends Specification{
             dmiProperties.authPassword == 'some-password'
     }
 
-    def 'Rest Template creation.'() {
+    def 'Rest Template creation with CloseableHttpClient and MappingJackson2HttpMessageConverter.'() {
         when: 'a rest template is created'
-            def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder)
+            def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder, httpClientConfiguration)
         then: 'the rest template is returned'
             assert result instanceof RestTemplate
+        and: 'the rest template is created with httpclient5'
+            assert result.getRequestFactory() instanceof HttpComponentsClientHttpRequestFactory
+            assert ((HttpComponentsClientHttpRequestFactory) result.getRequestFactory()).getHttpClient() instanceof CloseableHttpClient;
         and: 'a jackson media converter has been added'
             def lastMessageConverter = result.getMessageConverters().get(result.getMessageConverters().size()-1)
             lastMessageConverter instanceof MappingJackson2HttpMessageConverter
index 43e0f69..4eb2ca3 100644 (file)
@@ -49,7 +49,7 @@ class InventoryModelLoaderSpec extends Specification {
     def loggingListAppender
 
     void setup() {
-        expectedYangResourceToContentMap = objectUnderTest.createYangResourcesToContentMap('dmi-registry@2023-08-23.yang')
+        expectedYangResourceToContentMap = objectUnderTest.createYangResourcesToContentMap('dmi-registry@2023-11-27.yang')
         logger.setLevel(Level.DEBUG)
         loggingListAppender = new ListAppender()
         logger.addAppender(loggingListAppender)
@@ -68,9 +68,9 @@ class InventoryModelLoaderSpec extends Specification {
         when: 'the application is ready'
             objectUnderTest.onApplicationEvent(Mock(ApplicationReadyEvent))
         then: 'the module service is used to create the new schema set from the correct resource'
-            1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'dmi-registry-2023-08-23', expectedYangResourceToContentMap)
+            1 * mockCpsModuleService.createSchemaSet(NCMP_DATASPACE_NAME, 'dmi-registry-2023-11-27', expectedYangResourceToContentMap)
         and: 'the admin service is used to update the anchor'
-            1 * mockCpsAdminService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2023-08-23')
+            1 * mockCpsAdminService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2023-11-27')
         and: 'No schema sets are being removed by the module service (yet)'
             0 * mockCpsModuleService.deleteSchemaSet(NCMP_DATASPACE_NAME, _, _)
     }
index bef4224..12b04be 100644 (file)
@@ -72,7 +72,7 @@ class NcmpPerfTestBase extends PerfTestBase {
     }
 
     def createRegistrySchemaSet() {
-        def modelAsString = readResourceDataFile('ncmp-registry/dmi-registry@2022-05-10.yang')
+        def modelAsString = readResourceDataFile('ncmp-registry/dmi-registry@2023-11-27.yang')
         cpsModuleService.createSchemaSet(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_SCHEMA_SET, [registry: modelAsString])
     }
 
@@ -8,6 +8,11 @@ module dmi-registry {
 
   contact "toine.siebelink@est.tech";
 
+  revision "2023-11-27" {
+    description
+    "Added alternateId";
+  }
+
   revision "2023-08-23" {
     description
     "Added ModuleSetTag";
@@ -83,6 +88,9 @@ module dmi-registry {
       leaf module-set-tag {
         type string;
       }
+      leaf alternate-id {
+        type string;
+      }
 
       list additional-properties {
         key "name";
@@ -129,3 +137,4 @@ module dmi-registry {
     }
   }
 }
+