Merge "Log all incoming HTTP requests to NCMP with Authorization Header"
authorToine Siebelink <toine.siebelink@est.tech>
Wed, 6 Mar 2024 10:53:26 +0000 (10:53 +0000)
committerGerrit Code Review <gerrit@onap.org>
Wed, 6 Mar 2024 10:53:26 +0000 (10:53 +0000)
77 files changed:
checkstyle/pom.xml
cps-application/pom.xml
cps-application/src/main/java/org/onap/cps/config/WebSecurityConfig.java [deleted file]
cps-application/src/main/resources/application.yml
cps-application/src/test/groovy/org/onap/cps/rest/controller/ControllerSecuritySpec.groovy
cps-bom/pom.xml
cps-dependencies/pom.xml
cps-events/pom.xml
cps-ncmp-events/pom.xml
cps-ncmp-rest-stub/cps-ncmp-rest-stub-app/pom.xml
cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/pom.xml
cps-ncmp-rest-stub/cps-ncmp-rest-stub-service/src/main/java/org/onap/cps/ncmp/rest/stub/controller/NetworkCmProxyStubController.java
cps-ncmp-rest-stub/pom.xml
cps-ncmp-rest/docs/openapi/components.yaml
cps-ncmp-rest/docs/openapi/ncmp-inventory.yml
cps-ncmp-rest/docs/openapi/ncmp.yml
cps-ncmp-rest/lombok.config
cps-ncmp-rest/pom.xml
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpCachedResourceRequestHandler.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandler.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/handlers/NcmpPassthroughResourceRequestHandler.java
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/handlers/NcmpDatastoreRequestHandlerSpec.groovy
cps-ncmp-service/lombok.config
cps-ncmp-service/pom.xml
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/NetworkCmProxyDataService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/client/DmiRestClient.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/embeddedcache/TrustLevelCacheConfig.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/inventory/CmHandleQueriesImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/TrustLevelManager.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/trustlevel/dmiavailability/DmiPluginWatchDog.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/AlternateIdChecker.java
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/NetworkCmProxyDataServiceImplSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/utils/AlternateIdCheckerSpec.groovy
cps-parent/pom.xml
cps-path-parser/pom.xml
cps-rest/docs/openapi/cpsAdmin.yml
cps-rest/docs/openapi/cpsAdminV1Deprecated.yml
cps-rest/docs/openapi/cpsAdminV2.yml
cps-rest/docs/openapi/cpsData.yml
cps-rest/docs/openapi/cpsDataV1Deprecated.yml
cps-rest/docs/openapi/cpsDataV2.yml
cps-rest/docs/openapi/cpsQueryV1Deprecated.yml
cps-rest/docs/openapi/cpsQueryV2.yml
cps-rest/pom.xml
cps-ri/pom.xml
cps-ri/src/main/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceImpl.java
cps-service/pom.xml
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-app/pom.xml
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/pom.xml
dmi-plugin-demo-and-csit-stub/dmi-plugin-demo-and-csit-stub-service/src/main/java/org/onap/cps/ncmp/dmi/rest/stub/controller/DmiRestStubController.java
dmi-plugin-demo-and-csit-stub/pom.xml
docs/api/swagger/cps/openapi.yaml
docs/api/swagger/ncmp/openapi-inventory.yaml
docs/api/swagger/ncmp/openapi.yaml
docs/release-notes.rst
integration-test/pom.xml
integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpBearerTokenPassthroughSpec.groovy [new file with mode: 0644]
integration-test/src/test/resources/application.yml
jacoco-report/pom.xml
pom.xml
postman-collections/CPS-CORE.postman_collection.json
releases/3.4.6-container.yaml [new file with mode: 0644]
releases/3.4.6.yaml [new file with mode: 0644]
spotbugs/pom.xml
version.properties

index 2676dcb..83f1120 100644 (file)
@@ -26,7 +26,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>checkstyle</artifactId>
-    <version>3.4.6-SNAPSHOT</version>
+    <version>3.4.7-SNAPSHOT</version>
 
     <profiles>
         <profile>
index 871b929..ac75c0b 100644 (file)
@@ -28,7 +28,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
@@ -37,7 +37,7 @@
     <properties>
         <app>org.onap.cps.Application</app>
         <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
-        <minimum-coverage>0.86</minimum-coverage>
+        <minimum-coverage>0.68</minimum-coverage>
         <base.image>${docker.pull.registry}/onap/integration-java17:12.0.0</base.image>
         <image.tag>${project.version}-${maven.build.timestamp}</image.tag>
     </properties>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-jetty</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-security</artifactId>
-        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-actuator</artifactId>
             <groupId>org.springdoc</groupId>
             <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.micrometer</groupId>
             <artifactId>micrometer-registry-prometheus</artifactId>
diff --git a/cps-application/src/main/java/org/onap/cps/config/WebSecurityConfig.java b/cps-application/src/main/java/org/onap/cps/config/WebSecurityConfig.java
deleted file mode 100644 (file)
index 0b6d0db..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- *  ============LICENSE_START=======================================================
- *  Copyright (c) 2021 Bell Canada.
- *  Modification Copyright (C) 2021 Pantheon.tech
- *  Modification 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.config;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.core.userdetails.User;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.provisioning.InMemoryUserDetailsManager;
-import org.springframework.security.web.SecurityFilterChain;
-
-/**
- * Configuration class to implement application security.
- * It enforces Basic Authentication access control.
- */
-@Configuration
-@EnableWebSecurity
-public class WebSecurityConfig {
-    private static final String USER_ROLE = "USER";
-    private final String username;
-    private final String password;
-    private final String[] permitUris;
-
-    /**
-     * Constructor. Accepts parameters from configuration.
-     *
-     * @param permitUris comma-separated list of uri patterns for endpoints permitted
-     * @param username   username
-     * @param password   password
-     */
-    public WebSecurityConfig(
-            @Autowired @Value("${security.permit-uri}") final String permitUris,
-            @Autowired @Value("${security.auth.username}") final String username,
-            @Autowired @Value("${security.auth.password}") final String password
-    ) {
-        super();
-        this.permitUris = permitUris.isEmpty() ? new String[] {"/v3/api-docs"} : permitUris.split("\\s{0,9},\\s{0,9}");
-        this.username = username;
-        this.password = password;
-    }
-
-    /**
-     * Return the configuration for secure access to the modules REST end points.
-     *
-     * @param http the HTTP security settings.
-     * @return the HTTP security settings.
-     */
-    @Bean
-    // The team decided to disable default CSRF Spring protection and not implement CSRF tokens validation.
-    // CPS is a stateless REST API that is not as vulnerable to CSRF attacks as web applications running in
-    // web browsers are. CPS  does not manage sessions, each request requires the authentication token in the header.
-    // See https://docs.spring.io/spring-security/site/docs/5.3.8.RELEASE/reference/html5/#csrf
-    @SuppressWarnings("squid:S4502")
-    public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception {
-        http
-                .httpBasic(httpBasicCustomizer -> {})
-                .authorizeHttpRequests(authorizeHttpRequestsCustomizer -> {
-                    authorizeHttpRequestsCustomizer.requestMatchers(permitUris).permitAll();
-                    authorizeHttpRequestsCustomizer.anyRequest().authenticated();
-                })
-                .csrf(AbstractHttpConfigurer::disable);
-        return http.build();
-    }
-
-    /**
-     * In memory user authentication details.
-     *
-     * @return in memory authentication
-     */
-    @Bean
-    public InMemoryUserDetailsManager userDetailsService() {
-        final UserDetails user = User.builder()
-                .username(username)
-                .password("{noop}" + password)
-                .roles(USER_ROLE)
-                .build();
-        return new InMemoryUserDetailsManager(user);
-    }
-}
index 207341c..9f03fc2 100644 (file)
@@ -64,7 +64,7 @@ spring:
 
     liquibase:
         change-log: classpath:changelog/changelog-master.yaml
-        label-filter: ${LIQUIBASE_LABELS}
+        labels: ${LIQUIBASE_LABELS}
 
     servlet:
         multipart:
index ccadc57..b86f824 100755 (executable)
 
 package org.onap.cps.rest.controller
 
-import org.onap.cps.config.WebSecurityConfig
-import org.springframework.context.annotation.Import
-
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
 
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
 import org.springframework.http.HttpStatus
 import org.springframework.test.web.servlet.MockMvc
+import spock.lang.Ignore
 import spock.lang.Specification
 
 @WebMvcTest(TestController)
-@Import(WebSecurityConfig)
 class ControllerSecuritySpec extends Specification {
 
     @Autowired
@@ -49,6 +46,7 @@ class ControllerSecuritySpec extends Specification {
             assert response.status == HttpStatus.OK.value()
     }
 
+    @Ignore // CPS-2126
     def 'Get request without authentication is not authorized'() {
         when: 'request is sent without authentication'
             def response = mvc.perform(get(testEndpoint)).andReturn().response
@@ -56,6 +54,7 @@ class ControllerSecuritySpec extends Specification {
             assert response.status == HttpStatus.UNAUTHORIZED.value()
     }
 
+    @Ignore // CPS-2126
     def 'Get request with invalid authentication is not authorized'() {
         when: 'request is sent with invalid authentication'
             def response = mvc.perform(
index fb6bdbd..3e88be7 100644 (file)
@@ -25,7 +25,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-bom</artifactId>
-    <version>3.4.6-SNAPSHOT</version>
+    <version>3.4.7-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <description>This artifact contains dependencyManagement declarations of all published CPS components.</description>
index e1e7caa..69ea859 100644 (file)
@@ -27,7 +27,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-dependencies</artifactId>
-    <version>3.4.6-SNAPSHOT</version>
+    <version>3.4.7-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <name>${project.groupId}:${project.artifactId}</name>
@@ -85,7 +85,7 @@
             <dependency>
                 <groupId>org.springframework.boot</groupId>
                 <artifactId>spring-boot-dependencies</artifactId>
-                <version>3.2.2</version>
+                <version>3.1.2</version>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
+            <dependency>
+                <groupId>org.springframework</groupId>
+                <artifactId>spring-test</artifactId>
+                <version>6.0.11</version>
+            </dependency>
             <dependency>
                 <groupId>io.springfox</groupId>
                 <artifactId>springfox-boot-starter</artifactId>
             </dependency>
             <dependency>
                 <groupId>io.hypersistence</groupId>
-                <artifactId>hypersistence-utils-hibernate-63</artifactId>
-                <version>3.7.3</version>
+                <artifactId>hypersistence-utils-hibernate-60</artifactId>
+                <version>3.5.0</version>
             </dependency>
             <dependency>
                 <groupId>io.micrometer</groupId>
                 <artifactId>groovy</artifactId>
                 <version>${groovy.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-server</artifactId>
+                <version>${jetty-version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.eclipse.jetty</groupId>
+                <artifactId>jetty-http</artifactId>
+                <version>${jetty-version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.codehaus.janino</groupId>
                 <artifactId>janino</artifactId>
                 <artifactId>annotations</artifactId>
                 <version>22.0.0</version>
             </dependency>
+            <dependency>
+                <groupId>org.junit.jupiter</groupId>
+                <artifactId>junit-jupiter-api</artifactId>
+                <version>5.10.0</version>
+            </dependency>
             <dependency>
                 <groupId>org.liquibase</groupId>
                 <artifactId>liquibase-core</artifactId>
index ec62b62..fd75c2c 100644 (file)
@@ -24,7 +24,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index a6b80e5..89785ca 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index e100399..9d30692 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-ncmp-rest-stub</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
     </parent>
 
     <artifactId>cps-ncmp-rest-stub-app</artifactId>
index 480c28e..350bb00 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-ncmp-rest-stub</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
     </parent>
     <artifactId>cps-ncmp-rest-stub-service</artifactId>
 
             <groupId>org.onap.cps</groupId>
             <artifactId>cps-ncmp-rest</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+        </dependency>
         <!-- T E S T - D E P E N D E N C I E S -->
         <dependency>
             <groupId>org.spockframework</groupId>
index 0e4f7f9..08a492e 100644 (file)
@@ -69,7 +69,8 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
                                                              final String resourceIdentifier,
                                                              final String optionsParamInQuery,
                                                              final String topicParamInQuery,
-                                                             final Boolean includeDescendants) {
+                                                             final Boolean includeDescendants,
+                                                             final String authorization) {
         if (DatastoreType.PASSTHROUGH_OPERATIONAL == DatastoreType.fromDatastoreName(datastoreName)) {
             final ResponseEntity<Map<String, Object>> asyncResponse = populateAsyncResponse(topicParamInQuery);
             final Map<String, Object> asyncResponseData = asyncResponse.getBody();
@@ -142,16 +143,18 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
 
     @Override
     public ResponseEntity<Void> createResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
-                                                                     @NotNull @Valid final String resourceIdentifier, 
-                                                                     @Valid final Object body, 
-                                                                     final String contentType) {
+                                                                     @NotNull @Valid final String resourceIdentifier,
+                                                                     @Valid final Object body,
+                                                                     final String contentType,
+                                                                     final String authorization) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
-    
+
     @Override
     public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
                                                                      @NotNull @Valid final String resourceIdentifier,
-                                                                     final String contentType) {
+                                                                     final String contentType,
+                                                                     final String authorization) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
@@ -180,18 +183,20 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
 
     @Override
     public ResponseEntity<Object> executeDataOperationForCmHandles(final String topicParamInQuery,
-                                                                   final DataOperationRequest dataOperationRequest) {
+                                                                   final DataOperationRequest dataOperationRequest,
+                                                                   final String authorization) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
 
     @Override
     public ResponseEntity<Object> patchResourceDataRunningForCmHandle(final String datastoreName, final String cmHandle,
-                                                                      @NotNull @Valid final String resourceIdentifier, 
-                                                                      @Valid final Object body, 
-                                                                      final String contentType) {
+                                                                      @NotNull @Valid final String resourceIdentifier,
+                                                                      @Valid final Object body,
+                                                                      final String contentType,
+                                                                      final String authorization) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
     }
-    
+
     @Override
     public ResponseEntity<Object> queryResourceDataForCmHandle(final String datastoreName, final String cmHandle,
                                                                @Valid final String cpsPath, @Valid final String options,
@@ -220,11 +225,12 @@ public class NetworkCmProxyStubController implements NetworkCmProxyApi {
     }
 
     @Override
-    public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName, 
-                                                                       final String cmHandle, 
-                                                                       @NotNull @Valid final String resourceIdentifier, 
+    public ResponseEntity<Object> updateResourceDataRunningForCmHandle(final String datastoreName,
+                                                                       final String cmHandle,
+                                                                       @NotNull @Valid final String resourceIdentifier,
                                                                        @Valid final Object body,
-                                                                       final String contentType) {
+                                                                       final String contentType,
+                                                                       final String authorization) {
         return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
 
     }
index ee76f0a..3df8fa9 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 6b53292..cd77eff 100644 (file)
@@ -629,6 +629,13 @@ components:
         type: string
         default: application/json
         example: application/yang-data+json
+    authorizationParamInHeader:
+      name: Authorization
+      in: header
+      required: false
+      description: Authorization parameter for request.
+      schema:
+        type: string
     datastoreName:
       name: datastore-name
       in: path
index 16083bd..ea020f9 100755 (executable)
@@ -35,8 +35,6 @@ updateDmiRegistration:
         $ref: 'components.yaml#/components/responses/NoContent'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -116,8 +114,6 @@ getAllCmHandleIdsForRegisteredDmi:
               type: array
               items:
                 type: string
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -145,8 +141,6 @@ searchCmHandleIds:
               type: array
               items:
                 type: string
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
index 2f90155..0cb1cdf 100755 (executable)
@@ -32,6 +32,7 @@ resourceDataForCmHandle:
       - $ref: 'components.yaml#/components/parameters/optionsParamInQuery'
       - $ref: 'components.yaml#/components/parameters/topicParamInQuery'
       - $ref: 'components.yaml#/components/parameters/includeDescendantsOptionInQuery'
+      - $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
     responses:
       200:
         description: OK
@@ -44,8 +45,6 @@ resourceDataForCmHandle:
                 $ref: 'components.yaml#/components/examples/dataSampleResponse'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -64,6 +63,7 @@ resourceDataForCmHandle:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
       - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/contentParamInHeader'
+      - $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
     requestBody:
       required: true
       content:
@@ -84,8 +84,6 @@ resourceDataForCmHandle:
         $ref: 'components.yaml#/components/responses/Created'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -104,6 +102,7 @@ resourceDataForCmHandle:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
       - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/contentParamInHeader'
+      - $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
     requestBody:
       required: true
       content:
@@ -124,8 +123,6 @@ resourceDataForCmHandle:
         $ref: 'components.yaml#/components/responses/Ok'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -144,6 +141,7 @@ resourceDataForCmHandle:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
       - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/contentParamInHeader'
+      - $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
     requestBody:
       required: true
       content:
@@ -158,8 +156,6 @@ resourceDataForCmHandle:
         $ref: 'components.yaml#/components/responses/Ok'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -178,13 +174,12 @@ resourceDataForCmHandle:
       - $ref: 'components.yaml#/components/parameters/cmHandleInPath'
       - $ref: 'components.yaml#/components/parameters/resourceIdentifierInQuery'
       - $ref: 'components.yaml#/components/parameters/contentParamInHeader'
+      - $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
     responses:
       204:
         $ref: 'components.yaml#/components/responses/NoContent'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       404:
@@ -203,6 +198,7 @@ dataOperationForCmHandle:
     operationId: executeDataOperationForCmHandles
     parameters:
       - $ref: 'components.yaml#/components/parameters/requiredTopicParamInQuery'
+      - $ref: 'components.yaml#/components/parameters/authorizationParamInHeader'
     requestBody:
       required: true
       content:
@@ -218,8 +214,6 @@ dataOperationForCmHandle:
               type: object
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -253,8 +247,6 @@ queryResourceDataForCmHandle:
                 $ref: 'components.yaml#/components/examples/dataSampleResponse'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -282,8 +274,6 @@ fetchModuleReferencesByCmHandle:
                 $ref: 'components.yaml#/components/schemas/RestModuleReference'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -309,8 +299,6 @@ getModuleDefinitions:
               type: array
               items:
                 $ref: 'components.yaml#/components/schemas/RestModuleDefinition'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -351,8 +339,6 @@ searchCmHandles:
                 $ref: 'components.yaml#/components/schemas/RestOutputCmHandle'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
@@ -376,8 +362,6 @@ retrieveCmHandleDetailsById:
               $ref: 'components.yaml#/components/schemas/RestOutputCmHandle'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       404:
         $ref: 'components.yaml#/components/responses/NotFound'
       500:
@@ -401,8 +385,6 @@ getCmHandlePropertiesById:
               $ref: 'components.yaml#/components/schemas/RestOutputCmHandlePublicProperties'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       404:
         $ref: 'components.yaml#/components/responses/NotFound'
       500:
@@ -426,8 +408,6 @@ getCmHandleStateById:
               $ref: 'components.yaml#/components/schemas/RestOutputCmHandleCompositeState'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       404:
         $ref: 'components.yaml#/components/responses/NotFound'
       500:
@@ -468,8 +448,6 @@ searchCmHandleIds:
                 type: string
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       404:
@@ -492,11 +470,9 @@ setDataSyncEnabledFlag:
         $ref: 'components.yaml#/components/responses/Ok'
       400:
         $ref: 'components.yaml#/components/responses/BadRequest'
-      401:
-        $ref: 'components.yaml#/components/responses/Unauthorized'
       403:
         $ref: 'components.yaml#/components/responses/Forbidden'
       500:
         $ref: 'components.yaml#/components/responses/InternalServerError'
       502:
-        $ref: 'components.yaml#/components/responses/BadGateway'
\ No newline at end of file
+        $ref: 'components.yaml#/components/responses/BadGateway'
index e4122df..0418974 100644 (file)
@@ -17,5 +17,4 @@
 #  ============LICENSE_END=========================================================
 
 config.stopBubbling = true
-lombok.addLombokGeneratedAnnotation = true
-lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
index fc3bd8c..7e03120 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 73bd8d7..b567ba2 100755 (executable)
@@ -39,7 +39,6 @@ import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
 import org.onap.cps.ncmp.api.impl.exception.InvalidDatastoreException;
 import org.onap.cps.ncmp.api.impl.inventory.CompositeState;
 import org.onap.cps.ncmp.api.impl.operations.DatastoreType;
@@ -63,7 +62,6 @@ import org.onap.cps.ncmp.rest.model.RestOutputCmHandlePublicProperties;
 import org.onap.cps.ncmp.rest.util.DeprecationHelper;
 import org.onap.cps.spi.model.ModuleDefinition;
 import org.onap.cps.utils.JsonObjectMapper;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.util.StringUtils;
@@ -85,7 +83,6 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
     private final NcmpCachedResourceRequestHandler ncmpCachedResourceRequestHandler;
     private final NcmpPassthroughResourceRequestHandler ncmpPassthroughResourceRequestHandler;
     private final DataOperationRequestMapper dataOperationRequestMapper;
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerCmHandle;
 
     /**
@@ -97,6 +94,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * @param optionsParamInQuery  options query parameter
      * @param topicParamInQuery    topic query parameter
      * @param includeDescendants   whether to include descendants or not
+     * @param authorization        contents of Authorization header, or null if not present
      * @return {@code ResponseEntity} response from dmi plugin
      */
     @Override
@@ -106,18 +104,19 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                              final String resourceIdentifier,
                                                              final String optionsParamInQuery,
                                                              final String topicParamInQuery,
-                                                             final Boolean includeDescendants) {
+                                                             final Boolean includeDescendants,
+                                                             final String authorization) {
         final NcmpDatastoreRequestHandler ncmpDatastoreRequestHandler = getNcmpDatastoreRequestHandler(datastoreName);
         return ncmpDatastoreRequestHandler.executeRequest(datastoreName, cmHandle, resourceIdentifier,
-                optionsParamInQuery, topicParamInQuery, includeDescendants);
+                optionsParamInQuery, topicParamInQuery, includeDescendants, authorization);
     }
 
     @Override
     public ResponseEntity<Object> executeDataOperationForCmHandles(final String topicParamInQuery,
-                                                                  final DataOperationRequest
-                                                                          dataOperationRequest) {
+                                                                   final DataOperationRequest dataOperationRequest,
+                                                                   final String authorization) {
         return ncmpPassthroughResourceRequestHandler.executeRequest(topicParamInQuery,
-                dataOperationRequestMapper.toDataOperationRequest(dataOperationRequest));
+                dataOperationRequestMapper.toDataOperationRequest(dataOperationRequest), authorization);
     }
 
     /**
@@ -151,6 +150,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * @param resourceIdentifier resource identifier
      * @param requestBody        the request body
      * @param contentType        content type of body
+     * @param authorization      contents of Authorization header, or null if not present
      * @return {@code ResponseEntity} response from dmi plugin
      */
 
@@ -159,14 +159,15 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                                       final String cmHandle,
                                                                       final String resourceIdentifier,
                                                                       final Object requestBody,
-                                                                      final String contentType) {
+                                                                      final String contentType,
+                                                                      final String authorization) {
 
         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
 
         final Object responseObject = networkCmProxyDataService
                 .writeResourceDataPassThroughRunningForCmHandle(
                         cmHandle, resourceIdentifier, PATCH,
-                        jsonObjectMapper.asJsonString(requestBody), contentType);
+                        jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
         return ResponseEntity.ok(responseObject);
     }
 
@@ -178,6 +179,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * @param resourceIdentifier resource identifier
      * @param requestBody        the request body
      * @param contentType        content type of body
+     * @param authorization      contents of Authorization header, or null if not present
      * @return {@code ResponseEntity} response from dmi plugin
      */
     @Override
@@ -185,12 +187,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                                      final String cmHandle,
                                                                      final String resourceIdentifier,
                                                                      final Object requestBody,
-                                                                     final String contentType) {
-
+                                                                     final String contentType,
+                                                                     final String authorization) {
         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
 
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-                resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType);
+                resourceIdentifier, CREATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
         return new ResponseEntity<>(HttpStatus.CREATED);
     }
 
@@ -202,6 +204,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * @param resourceIdentifier resource identifier
      * @param requestBody        the request body
      * @param contentType        content type of the body
+     * @param authorization      contents of Authorization header, or null if not present
      * @return response entity
      */
 
@@ -210,11 +213,12 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
                                                                        final String cmHandle,
                                                                        final String resourceIdentifier,
                                                                        final Object requestBody,
-                                                                       final String contentType) {
+                                                                       final String contentType,
+                                                                       final String authorization) {
         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
 
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-                resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType);
+                resourceIdentifier, UPDATE, jsonObjectMapper.asJsonString(requestBody), contentType, authorization);
         return new ResponseEntity<>(HttpStatus.OK);
     }
 
@@ -225,18 +229,20 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
      * @param cmHandle           cm handle identifier
      * @param resourceIdentifier resource identifier
      * @param contentType        content type of the body
+     * @param authorization      contents of Authorization header, or null if not present
      * @return response entity no content if request is successful
      */
     @Override
     public ResponseEntity<Void> deleteResourceDataRunningForCmHandle(final String datastoreName,
                                                                      final String cmHandle,
                                                                      final String resourceIdentifier,
-                                                                     final String contentType) {
+                                                                     final String contentType,
+                                                                     final String authorization) {
 
         validateDataStore(PASSTHROUGH_RUNNING, datastoreName);
 
         networkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle(cmHandle,
-                resourceIdentifier, DELETE, NO_BODY, contentType);
+                resourceIdentifier, DELETE, NO_BODY, contentType, authorization);
         return new ResponseEntity<>(HttpStatus.NO_CONTENT);
     }
 
index 85a1eae..430c099 100644 (file)
@@ -74,7 +74,8 @@ public class NcmpCachedResourceRequestHandler extends NcmpDatastoreRequestHandle
                                                   final String optionsParamInQuery,
                                                   final String topicParamInQuery,
                                                   final String requestId,
-                                                  final boolean includeDescendants) {
+                                                  final boolean includeDescendants,
+                                                  final String authorization) {
 
         final FetchDescendantsOption fetchDescendantsOption = getFetchDescendantsOption(includeDescendants);
 
index d40ab9b..8b08090 100644 (file)
@@ -56,6 +56,7 @@ public abstract class NcmpDatastoreRequestHandler {
      * @param optionsParamInQuery the options param in query
      * @param topicParamInQuery   the topic param in query
      * @param includeDescendants  whether include descendants
+     * @param authorization       contents of Authorization header, or null if not present
      * @return the response entity
      */
     public ResponseEntity<Object> executeRequest(final String datastoreName,
@@ -63,12 +64,13 @@ public abstract class NcmpDatastoreRequestHandler {
                                                  final String resourceIdentifier,
                                                  final String optionsParamInQuery,
                                                  final String topicParamInQuery,
-                                                 final boolean includeDescendants) {
+                                                 final boolean includeDescendants,
+                                                 final String authorization) {
 
         final boolean asyncResponseRequested = topicParamInQuery != null;
         if (asyncResponseRequested && notificationFeatureEnabled) {
             return executeAsyncTaskAndGetResponseEntity(datastoreName, cmHandleId, resourceIdentifier,
-                optionsParamInQuery, topicParamInQuery, includeDescendants);
+                optionsParamInQuery, topicParamInQuery, includeDescendants, authorization);
         }
 
         if (asyncResponseRequested) {
@@ -76,7 +78,7 @@ public abstract class NcmpDatastoreRequestHandler {
                     + "will use synchronous operation.");
         }
         final Supplier<Object> taskSupplier = getTaskSupplierForGetRequest(datastoreName, cmHandleId,
-                resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID, includeDescendants);
+                resourceIdentifier, optionsParamInQuery, NO_TOPIC, NO_REQUEST_ID, includeDescendants, authorization);
         return executeTaskSync(taskSupplier);
     }
 
@@ -99,10 +101,12 @@ public abstract class NcmpDatastoreRequestHandler {
                                                                         final String resourceIdentifier,
                                                                         final String optionsParamInQuery,
                                                                         final String topicParamInQuery,
-                                                                        final boolean includeDescendants) {
+                                                                        final boolean includeDescendants,
+                                                                        final String authorization) {
         final String requestId = UUID.randomUUID().toString();
         final Supplier<Object> taskSupplier = getTaskSupplierForGetRequest(datastoreName, cmHandleId,
-                resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId, includeDescendants);
+                resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId, includeDescendants,
+                authorization);
         return executeTaskAsync(topicParamInQuery, requestId, taskSupplier);
     }
 
@@ -112,6 +116,7 @@ public abstract class NcmpDatastoreRequestHandler {
                                                   final String optionsParamInQuery,
                                                   final String topicParamInQuery,
                                                   final String requestId,
-                                                  final boolean includeDescendant);
+                                                  final boolean includeDescendant,
+                                                  final String authorization);
 
 }
index 8a32575..430b749 100644 (file)
@@ -61,17 +61,19 @@ public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestH
      *
      * @param topicParamInQuery        the topic param in query
      * @param dataOperationRequest     data operation request details for resource data
+     * @param authorization            contents of Authorization header, or null if not present
      * @return the response entity
      */
     public ResponseEntity<Object> executeRequest(final String topicParamInQuery,
-                                                 final DataOperationRequest
-                                                     dataOperationRequest) {
+                                                 final DataOperationRequest dataOperationRequest,
+                                                 final String authorization) {
         validateDataOperationRequest(topicParamInQuery, dataOperationRequest);
         if (!notificationFeatureEnabled) {
             return ResponseEntity.ok(Map.of("status",
                 "Asynchronous request is unavailable as notification feature is currently disabled."));
         }
-        return getRequestIdAndSendDataOperationRequestToDmiService(topicParamInQuery, dataOperationRequest);
+        return getRequestIdAndSendDataOperationRequestToDmiService(topicParamInQuery, dataOperationRequest,
+                authorization);
     }
 
     @Override
@@ -81,18 +83,21 @@ public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestH
                                                             final String optionsParamInQuery,
                                                             final String topicParamInQuery,
                                                             final String requestId,
-                                                            final boolean includeDescendants) {
+                                                            final boolean includeDescendants,
+                                                            final String authorization) {
 
         return () -> networkCmProxyDataService.getResourceDataForCmHandle(
-            datastoreName, cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId);
+            datastoreName, cmHandleId, resourceIdentifier, optionsParamInQuery, topicParamInQuery, requestId,
+            authorization);
     }
 
-    private ResponseEntity<Object> getRequestIdAndSendDataOperationRequestToDmiService(final String topicParamInQuery,
-                                                                                       final DataOperationRequest
-                                                                                           dataOperationRequest) {
+    private ResponseEntity<Object> getRequestIdAndSendDataOperationRequestToDmiService(
+            final String topicParamInQuery,
+            final DataOperationRequest dataOperationRequest,
+            final String authorization) {
         final String requestId = UUID.randomUUID().toString();
         cpsNcmpTaskExecutor.executeTask(
-            getTaskSupplierForDataOperationRequest(topicParamInQuery, dataOperationRequest, requestId),
+            getTaskSupplierForDataOperationRequest(topicParamInQuery, dataOperationRequest, requestId, authorization),
             timeOutInMilliSeconds);
         return ResponseEntity.ok(Map.of("requestId", requestId));
     }
@@ -114,11 +119,13 @@ public class NcmpPassthroughResourceRequestHandler extends NcmpDatastoreRequestH
 
     private Supplier<Object> getTaskSupplierForDataOperationRequest(final String topicParamInQuery,
                                                                     final DataOperationRequest dataOperationRequest,
-                                                                    final String requestId) {
+                                                                    final String requestId,
+                                                                    final String authorization) {
         return () -> {
             networkCmProxyDataService.executeDataOperationForCmHandles(topicParamInQuery,
                 dataOperationRequest,
-                requestId);
+                requestId,
+                authorization);
             return noReturn;
         };
     }
index 983f243..dba2b30 100644 (file)
@@ -135,6 +135,7 @@ class NetworkCmProxyControllerSpec extends Specification {
     @Shared
     def NO_TOPIC = null
     def NO_REQUEST_ID = null
+    def NO_AUTH_HEADER = null
     def TIMOUT_FOR_TEST = 1234
 
     def logger = Spy(ListAppender<ILoggingEvent>)
@@ -162,7 +163,7 @@ class NetworkCmProxyControllerSpec extends Specification {
             ).andReturn().response
         then: 'the NCMP data service is called with getResourceDataOperationalForCmHandle'
             1 * mockNetworkCmProxyDataService.getResourceDataForCmHandle(PASSTHROUGH_OPERATIONAL.datastoreName, 'testCmHandle',
-                    'parent/child','(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID)
+                    'parent/child','(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
         and: 'response status is Ok'
             response.status == HttpStatus.OK.value()
     }
@@ -279,7 +280,7 @@ class NetworkCmProxyControllerSpec extends Specification {
                     "?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
         and: 'ncmp service returns json object'
             mockNetworkCmProxyDataService.getResourceDataForCmHandle(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle',
-                    resourceIdentifier,'(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID) >> '{valid-json}'
+                    resourceIdentifier,'(a=1,b=2)', NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) >> '{valid-json}'
         when: 'get data resource request is performed'
             def response = mvc.perform(
                     get(getUrl)
@@ -310,7 +311,7 @@ class NetworkCmProxyControllerSpec extends Specification {
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', UPDATE, requestBody, 'application/json;charset=UTF-8')
+                    'parent/child', UPDATE, requestBody, 'application/json;charset=UTF-8', NO_AUTH_HEADER)
         and: 'the response status is OK'
             response.status == HttpStatus.OK.value()
     }
@@ -326,7 +327,7 @@ class NetworkCmProxyControllerSpec extends Specification {
             ).andReturn().response
         then: 'ncmp service method to create resource called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', CREATE, requestBody, 'application/json;charset=UTF-8')
+                    'parent/child', CREATE, requestBody, 'application/json;charset=UTF-8', NO_AUTH_HEADER)
         and: 'resource is created'
             response.status == HttpStatus.CREATED.value()
     }
@@ -492,7 +493,7 @@ class NetworkCmProxyControllerSpec extends Specification {
             ).andReturn().response
         then: 'ncmp service method to update resource is called'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8')
+                    'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8', NO_AUTH_HEADER)
         and: 'the response status is OK'
             response.status == HttpStatus.OK.value()
     }
@@ -507,7 +508,7 @@ class NetworkCmProxyControllerSpec extends Specification {
                             .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andReturn().response
         then: 'the ncmp service method to delete resource is called (with null as body)'
             1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
-                    'parent/child', DELETE, null, 'application/json;charset=UTF-8')
+                    'parent/child', DELETE, null, 'application/json;charset=UTF-8', NO_AUTH_HEADER)
         and: 'the response is No Content'
             response.status == HttpStatus.NO_CONTENT.value()
     }
index 4edbf35..ddeac51 100644 (file)
@@ -37,6 +37,8 @@ class NcmpDatastoreRequestHandlerSpec extends Specification {
 
     def objectUnderTest = new NcmpPassthroughResourceRequestHandler(spiedCpsNcmpTaskExecutor, mockNetworkCmProxyDataService)
 
+    def NO_AUTH_HEADER = null
+
     def setup() {
         objectUnderTest.timeOutInMilliSeconds = 100
     }
@@ -47,11 +49,11 @@ class NcmpDatastoreRequestHandlerSpec extends Specification {
         and: 'a flag to track the network service call'
             def networkServiceMethodCalled = false
         and: 'the (mocked) service will use the flag to indicate if it is called'
-            mockNetworkCmProxyDataService.getResourceDataForCmHandle('ds', 'ch1', 'resource1', 'options', _, _) >> {
+            mockNetworkCmProxyDataService.getResourceDataForCmHandle('ds', 'ch1', 'resource1', 'options', _, _, NO_AUTH_HEADER) >> {
                 networkServiceMethodCalled = true
             }
         when: 'get request is executed with topic = #topic'
-            objectUnderTest.executeRequest('ds', 'ch1', 'resource1', 'options', topic, false)
+            objectUnderTest.executeRequest('ds', 'ch1', 'resource1', 'options', topic, false, NO_AUTH_HEADER)
         then: 'the task is executed in an async fashion or not'
             expectedCalls * spiedCpsNcmpTaskExecutor.executeTask(*_)
         and: 'the service request is invoked'
@@ -72,7 +74,7 @@ class NcmpDatastoreRequestHandlerSpec extends Specification {
         and: 'notification feature is turned on/off'
             objectUnderTest.notificationFeatureEnabled = notificationFeatureEnabled
         when: 'data operation request is executed'
-            objectUnderTest.executeRequest('someTopic', new DataOperationRequest())
+            objectUnderTest.executeRequest('someTopic', new DataOperationRequest(), NO_AUTH_HEADER)
         then: 'the task is executed in an async fashion or not'
             expectedCalls * spiedCpsNcmpTaskExecutor.executeTask(*_)
         where: 'the following parameters are used'
@@ -90,11 +92,11 @@ class NcmpDatastoreRequestHandlerSpec extends Specification {
         and: ' a flag to track the network service call'
             def networkServiceMethodCalled = false
         and: 'the (mocked) service will use the flag to indicate it is called'
-            mockNetworkCmProxyDataService.executeDataOperationForCmHandles('myTopic', dataOperationRequest, _) >> {
+            mockNetworkCmProxyDataService.executeDataOperationForCmHandles('myTopic', dataOperationRequest, _, NO_AUTH_HEADER) >> {
                 networkServiceMethodCalled = true
             }
         when: 'data operation request is executed'
-            objectUnderTest.executeRequest('myTopic', dataOperationRequest)
+            objectUnderTest.executeRequest('myTopic', dataOperationRequest, NO_AUTH_HEADER)
         then: 'the task is executed in an async fashion'
             1 * spiedCpsNcmpTaskExecutor.executeTask(*_)
         and: 'the network service is invoked'
@@ -112,7 +114,7 @@ class NcmpDatastoreRequestHandlerSpec extends Specification {
             def dataOperationDefinition = new DataOperationDefinition(operation: 'read', datastore: datastore)
         when: 'data operation request is executed'
             def dataOperationRequest = new DataOperationRequest(dataOperationDefinitions: [dataOperationDefinition])
-            objectUnderTest.executeRequest('myTopic', dataOperationRequest)
+            objectUnderTest.executeRequest('myTopic', dataOperationRequest, NO_AUTH_HEADER)
         then: 'the correct error is thrown'
             def thrown = thrown(InvalidDatastoreException)
             assert thrown.message.contains(expectedErrorMessage)
@@ -128,7 +130,7 @@ class NcmpDatastoreRequestHandlerSpec extends Specification {
         and: 'a data operation definition with operation: #operation'
             def dataOperationDefinition = new DataOperationDefinition(operation: operation, datastore: 'ncmp-datastore:passthrough-running')
         when: 'bulk request is executed'
-            objectUnderTest.executeRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]))
+            objectUnderTest.executeRequest('someTopic', new DataOperationRequest(dataOperationDefinitions:[dataOperationDefinition]), NO_AUTH_HEADER)
         then: 'the expected type of exception is thrown'
             thrown(expectedException)
         where: 'the following operations are used'
index 6776ef0..359519c 100644 (file)
@@ -17,5 +17,4 @@
 #  ============LICENSE_END=========================================================
 
 config.stopBubbling = true
-lombok.addLombokGeneratedAnnotation = true
-lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier
+lombok.addLombokGeneratedAnnotation = true
\ No newline at end of file
index bdc2304..4feb676 100644 (file)
@@ -27,7 +27,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index 0c84748..4230140 100644 (file)
@@ -59,6 +59,7 @@ public interface NetworkCmProxyDataService {
      * @param optionsParamInQuery options query
      * @param topicParamInQuery   topic name for (triggering) async responses
      * @param requestId           unique requestId for async request
+     * @param authorization       contents of Authorization header, or null if not present
      * @return {@code Object} resource data
      */
     Object getResourceDataForCmHandle(String datastoreName,
@@ -66,7 +67,8 @@ public interface NetworkCmProxyDataService {
                                       String resourceIdentifier,
                                       String optionsParamInQuery,
                                       String topicParamInQuery,
-                                      String requestId);
+                                      String requestId,
+                                      String authorization);
 
     /**
      * Get resource data for operational.
@@ -87,10 +89,13 @@ public interface NetworkCmProxyDataService {
      *
      * @param topicParamInQuery        topic name for (triggering) async responses
      * @param dataOperationRequest     contains a list of operation definitions(multiple operations)
+     * @param requestId                request ID
+     * @param authorization            contents of Authorization header, or null if not present
      */
     void executeDataOperationForCmHandles(String topicParamInQuery,
                                           DataOperationRequest dataOperationRequest,
-                                          String requestId);
+                                          String requestId,
+                                          String authorization);
 
 
     /**
@@ -101,13 +106,15 @@ public interface NetworkCmProxyDataService {
      * @param operationType      required operation type
      * @param requestBody        request body to create resource
      * @param contentType        content type in body
+     * @param authorization       contents of Authorization header, or null if not present
      * @return {@code Object} return data
      */
     Object writeResourceDataPassThroughRunningForCmHandle(String cmHandleId,
                                                         String resourceIdentifier,
                                                         OperationType operationType,
                                                         String requestBody,
-                                                        String contentType);
+                                                        String contentType,
+                                                        String authorization);
 
     /**
      * Retrieve module references for the given cm handle.
index ab83486..4c905bf 100755 (executable)
@@ -51,7 +51,6 @@ import org.apache.commons.lang3.StringUtils;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
 import org.onap.cps.ncmp.api.impl.events.lcm.LcmEventsCmHandleStateHandler;
 import org.onap.cps.ncmp.api.impl.inventory.CmHandleQueries;
 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState;
@@ -85,7 +84,6 @@ import org.onap.cps.spi.exceptions.DataValidationException;
 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.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
@@ -104,7 +102,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
     private final LcmEventsCmHandleStateHandler lcmEventsCmHandleStateHandler;
     private final CpsDataService cpsDataService;
     private final IMap<String, Object> moduleSyncStartedOnCmHandles;
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
     private final TrustLevelManager trustLevelManager;
     private final AlternateIdChecker alternateIdChecker;
@@ -135,12 +132,14 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                              final String resourceIdentifier,
                                              final String optionsParamInQuery,
                                              final String topicParamInQuery,
-                                             final String requestId) {
+                                             final String requestId,
+                                             final String authorization) {
         final ResponseEntity<?> responseEntity = dmiDataOperations.getResourceDataFromDmi(datastoreName, cmHandleId,
             resourceIdentifier,
             optionsParamInQuery,
             topicParamInQuery,
-            requestId);
+            requestId,
+            authorization);
         return responseEntity.getBody();
     }
 
@@ -155,10 +154,11 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
 
     @Override
     public void executeDataOperationForCmHandles(final String topicParamInQuery,
-                                                 final DataOperationRequest
-                                                     dataOperationRequest,
-                                                 final String requestId) {
-        dmiDataOperations.requestResourceDataFromDmi(topicParamInQuery, dataOperationRequest, requestId);
+                                                 final DataOperationRequest dataOperationRequest,
+                                                 final String requestId,
+                                                 final String authorization) {
+        dmiDataOperations.requestResourceDataFromDmi(topicParamInQuery, dataOperationRequest, requestId,
+                authorization);
     }
 
     @Override
@@ -166,9 +166,10 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
                                                                  final String resourceIdentifier,
                                                                  final OperationType operationType,
                                                                  final String requestData,
-                                                                 final String dataType) {
+                                                                 final String dataType,
+                                                                 final String authorization) {
         return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier,
-            operationType, requestData, dataType);
+            operationType, requestData, dataType, authorization);
     }
 
     @Override
@@ -423,7 +424,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
         final List<NcmpServiceCmHandle> cmHandlesToBeCreated,
         final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses) {
         final Collection<String> rejectedCmHandleIds = alternateIdChecker
-            .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated);
+            .getIdsOfCmHandlesWithRejectedAlternateId(cmHandlesToBeCreated, AlternateIdChecker.Operation.CREATE);
         cmHandleRegistrationResponses.addAll(CmHandleRegistrationResponse.createFailureResponses(
             rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED));
         return rejectedCmHandleIds;
index f5d22af..3d15291 100644 (file)
@@ -22,6 +22,7 @@
 
 package org.onap.cps.ncmp.api.impl;
 
+import static org.onap.cps.ncmp.api.NcmpResponseStatus.ALTERNATE_ID_ALREADY_ASSOCIATED;
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLES_NOT_FOUND;
 import static org.onap.cps.ncmp.api.NcmpResponseStatus.CM_HANDLE_INVALID_ID;
 import static org.onap.cps.ncmp.api.impl.NetworkCmProxyDataServicePropertyHandler.PropertyType.DMI_PROPERTY;
@@ -46,8 +47,6 @@ import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.api.CpsDataService;
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
 import org.onap.cps.ncmp.api.impl.utils.AlternateIdChecker;
-import org.onap.cps.ncmp.api.impl.utils.YangDataConverter;
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse;
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException;
@@ -70,67 +69,76 @@ public class NetworkCmProxyDataServicePropertyHandler {
     private final AlternateIdChecker alternateIdChecker;
 
     /**
-     * Iterates over incoming ncmpServiceCmHandles and update the dataNodes based on the updated attributes.
+     * Iterates over incoming updatedNcmpServiceCmHandles and update the dataNodes based on the updated attributes.
      * The attributes which are not passed will remain as is.
      *
-     * @param ncmpServiceCmHandles collection of ncmpServiceCmHandles
+     * @param updatedNcmpServiceCmHandles collection of CmHandles
      */
     public List<CmHandleRegistrationResponse> updateCmHandleProperties(
-        final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) {
-        final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses
-            = new ArrayList<>(ncmpServiceCmHandles.size());
-        for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
-            final String cmHandleId = ncmpServiceCmHandle.getCmHandleId();
-            try {
-                final DataNode existingCmHandleDataNode = inventoryPersistence
-                    .getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next();
-                updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle);
-                processUpdates(existingCmHandleDataNode, ncmpServiceCmHandle);
-                cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId));
-            } catch (final DataNodeNotFoundException e) {
-                log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandleId, e.getMessage());
-                cmHandleRegistrationResponses.add(
-                    CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND));
-            } catch (final DataValidationException e) {
-                log.error("Unable to update cm handle : {}, caused by : {}", cmHandleId, e.getMessage());
-                cmHandleRegistrationResponses.add(
-                    CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID));
-            } catch (final Exception exception) {
-                log.error("Unable to update cmHandle : {} , caused by : {}", cmHandleId, exception.getMessage());
-                cmHandleRegistrationResponses.add(
-                    CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception));
+            final Collection<NcmpServiceCmHandle> updatedNcmpServiceCmHandles) {
+        final Collection<String> rejectedCmHandleIds = alternateIdChecker
+            .getIdsOfCmHandlesWithRejectedAlternateId(updatedNcmpServiceCmHandles, AlternateIdChecker.Operation.UPDATE);
+        final List<CmHandleRegistrationResponse> failureResponses =
+            CmHandleRegistrationResponse.createFailureResponses(rejectedCmHandleIds, ALTERNATE_ID_ALREADY_ASSOCIATED);
+        final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>(failureResponses);
+        for (final NcmpServiceCmHandle updatedNcmpServiceCmHandle : updatedNcmpServiceCmHandles) {
+            final String cmHandleId = updatedNcmpServiceCmHandle.getCmHandleId();
+            if (!rejectedCmHandleIds.contains(cmHandleId)) {
+                try {
+                    final DataNode existingCmHandleDataNode = inventoryPersistence
+                            .getCmHandleDataNodeByCmHandleId(cmHandleId).iterator().next();
+                    processUpdates(existingCmHandleDataNode, updatedNcmpServiceCmHandle);
+                    cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId));
+                } catch (final DataNodeNotFoundException e) {
+                    log.error("Unable to find dataNode for cmHandleId : {} , caused by : {}", cmHandleId,
+                            e.getMessage());
+                    cmHandleRegistrationResponses.add(
+                            CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLES_NOT_FOUND));
+                } catch (final DataValidationException e) {
+                    log.error("Unable to update cm handle : {}, caused by : {}", cmHandleId, e.getMessage());
+                    cmHandleRegistrationResponses.add(
+                            CmHandleRegistrationResponse.createFailureResponse(cmHandleId, CM_HANDLE_INVALID_ID));
+                } catch (final Exception exception) {
+                    log.error("Unable to update cmHandle : {} , caused by : {}", cmHandleId, exception.getMessage());
+                    cmHandleRegistrationResponses.add(
+                            CmHandleRegistrationResponse.createFailureResponse(cmHandleId, exception));
+                }
             }
         }
         return cmHandleRegistrationResponses;
     }
 
-    private void updateAlternateId(final DataNode existingCmHandleDataNode,
-                                   final NcmpServiceCmHandle ncmpServiceCmHandle) {
-        final YangModelCmHandle yangModelCmHandle =
-            YangDataConverter.convertCmHandleToYangModel(existingCmHandleDataNode);
-        final String currentAlternateId = yangModelCmHandle.getAlternateId();
-        final String newAlternateId = ncmpServiceCmHandle.getAlternateId();
-        if (alternateIdChecker.canApplyAlternateId(ncmpServiceCmHandle.getCmHandleId(),
-            currentAlternateId, newAlternateId)) {
-            setAndUpdateAlternateId(yangModelCmHandle, newAlternateId);
+    private void processUpdates(final DataNode existingCmHandleDataNode,
+                                final NcmpServiceCmHandle updatedNcmpServiceCmHandle) {
+        updateAlternateId(updatedNcmpServiceCmHandle);
+        if (!updatedNcmpServiceCmHandle.getPublicProperties().isEmpty()) {
+            updateProperties(existingCmHandleDataNode, PUBLIC_PROPERTY,
+                updatedNcmpServiceCmHandle.getPublicProperties());
+        }
+        if (!updatedNcmpServiceCmHandle.getDmiProperties().isEmpty()) {
+            updateProperties(existingCmHandleDataNode, DMI_PROPERTY, updatedNcmpServiceCmHandle.getDmiProperties());
         }
     }
 
-    private void processUpdates(final DataNode existingCmHandleDataNode, final NcmpServiceCmHandle incomingCmHandle) {
-        if (!incomingCmHandle.getPublicProperties().isEmpty()) {
-            updateProperties(existingCmHandleDataNode, PUBLIC_PROPERTY, incomingCmHandle.getPublicProperties());
-        }
-        if (!incomingCmHandle.getDmiProperties().isEmpty()) {
-            updateProperties(existingCmHandleDataNode, DMI_PROPERTY, incomingCmHandle.getDmiProperties());
-        }
+    private void updateAlternateId(final NcmpServiceCmHandle updatedNcmpServiceCmHandle) {
+        final String updatedAlternateId = updatedNcmpServiceCmHandle.getAlternateId();
+        final String cmHandleId = updatedNcmpServiceCmHandle.getCmHandleId();
+        final Map<String, String> cmHandleProperties = new HashMap<>(2);
+        cmHandleProperties.put("id", cmHandleId);
+        cmHandleProperties.put("alternate-id", updatedAlternateId);
+        final Map<String, Map<String, String>> dmiRegistryProperties = new HashMap<>(1);
+        dmiRegistryProperties.put("cm-handles", cmHandleProperties);
+        cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
+                jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
+        log.debug("Updating alternateId for cmHandle {} with value : {})", cmHandleId, updatedAlternateId);
     }
 
     private void updateProperties(final DataNode existingCmHandleDataNode, final PropertyType propertyType,
-            final Map<String, String> incomingProperties) {
+                                  final Map<String, String> updatedProperties) {
         final Collection<DataNode> replacementPropertyDataNodes =
-                getReplacementDataNodes(existingCmHandleDataNode, propertyType, incomingProperties);
+                getReplacementDataNodes(existingCmHandleDataNode, propertyType, updatedProperties);
         replacementPropertyDataNodes.addAll(
-                getUnchangedPropertyDataNodes(existingCmHandleDataNode, propertyType, incomingProperties));
+                getUnchangedPropertyDataNodes(existingCmHandleDataNode, propertyType, updatedProperties));
         if (replacementPropertyDataNodes.isEmpty()) {
             removeAllProperties(existingCmHandleDataNode, propertyType);
         } else {
@@ -149,13 +157,14 @@ public class NetworkCmProxyDataServicePropertyHandler {
     }
 
     private Collection<DataNode> getUnchangedPropertyDataNodes(final DataNode existingCmHandleDataNode,
-            final PropertyType propertyType, final Map<String, String> incomingProperties) {
+                                                               final PropertyType propertyType,
+                                                               final Map<String, String> updatedProperties) {
         final Collection<DataNode> unchangedPropertyDataNodes = new HashSet<>();
         for (final DataNode existingPropertyDataNode : existingCmHandleDataNode.getChildDataNodes()) {
             final Matcher matcher = propertyType.propertyXpathPattern.matcher(existingPropertyDataNode.getXpath());
             if (matcher.find()) {
                 final String keyName = matcher.group(2);
-                if (!incomingProperties.containsKey(keyName)) {
+                if (!updatedProperties.containsKey(keyName)) {
                     unchangedPropertyDataNodes.add(existingPropertyDataNode);
                 }
             }
@@ -164,9 +173,10 @@ public class NetworkCmProxyDataServicePropertyHandler {
     }
 
     private Collection<DataNode> getReplacementDataNodes(final DataNode existingCmHandleDataNode,
-            final PropertyType propertyType, final Map<String, String> incomingProperties) {
+                                                         final PropertyType propertyType,
+                                                         final Map<String, String> updatedProperties) {
         final Collection<DataNode> replacementPropertyDataNodes = new HashSet<>();
-        incomingProperties.forEach((updatedAttributeKey, updatedAttributeValue) -> {
+        updatedProperties.forEach((updatedAttributeKey, updatedAttributeValue) -> {
             final String propertyXpath = getAttributeXpath(existingCmHandleDataNode, propertyType, updatedAttributeKey);
             if (updatedAttributeValue != null) {
                 log.info("Creating a new DataNode with xpath {} , key : {} and value : {}", propertyXpath,
@@ -179,7 +189,7 @@ public class NetworkCmProxyDataServicePropertyHandler {
     }
 
     private String getAttributeXpath(final DataNode cmHandle, final PropertyType propertyType,
-            final String attributeKey) {
+                                     final String attributeKey) {
         return cmHandle.getXpath() + "/" + propertyType.xpathPrefix + String.format("[@name='%s']", attributeKey);
     }
 
@@ -192,17 +202,6 @@ public class NetworkCmProxyDataServicePropertyHandler {
         return new DataNodeBuilder().withXpath(xpath).withLeaves(ImmutableMap.copyOf(updatedLeaves)).build();
     }
 
-    private void setAndUpdateAlternateId(final YangModelCmHandle upgradedCmHandle, final String alternateId) {
-        final Map<String, Map<String, String>> dmiRegistryProperties = new HashMap<>(1);
-        final Map<String, String> cmHandleProperties = new HashMap<>(2);
-        cmHandleProperties.put("id", upgradedCmHandle.getId());
-        cmHandleProperties.put("alternate-id", alternateId);
-        dmiRegistryProperties.put("cm-handles", cmHandleProperties);
-        cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
-                jsonObjectMapper.asJsonString(dmiRegistryProperties), OffsetDateTime.now());
-        log.info("Updating alternateId for cmHandle {} with value : {})", upgradedCmHandle.getId(), alternateId);
-    }
-
     enum PropertyType {
         DMI_PROPERTY("additional-properties"), PUBLIC_PROPERTY("public-properties");
 
index 5b93eb4..798a280 100644 (file)
@@ -22,6 +22,7 @@
 package org.onap.cps.ncmp.api.impl.client;
 
 import com.fasterxml.jackson.databind.JsonNode;
+import java.util.Locale;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration.DmiProperties;
@@ -51,12 +52,15 @@ public class DmiRestClient {
      * @param dmiResourceUrl          dmi resource url
      * @param requestBodyAsJsonString json data body
      * @param operationType           the type of operation being executed (for error reporting only)
+     * @param authorization           contents of Authorization header, or null if not present
      * @return response entity of type String
      */
     public ResponseEntity<Object> postOperationWithJsonData(final String dmiResourceUrl,
                                                             final String requestBodyAsJsonString,
-                                                            final OperationType operationType) {
-        final var httpEntity = new HttpEntity<>(requestBodyAsJsonString, configureHttpHeaders(new HttpHeaders()));
+                                                            final OperationType operationType,
+                                                            final String authorization) {
+        final var httpEntity = new HttpEntity<>(requestBodyAsJsonString, configureHttpHeaders(new HttpHeaders(),
+                authorization));
         try {
             return restTemplate.postForEntity(dmiResourceUrl, httpEntity, Object.class);
         } catch (final HttpStatusCodeException httpStatusCodeException) {
@@ -73,7 +77,7 @@ public class DmiRestClient {
      * @return      plugin health status ("UP" is all OK, "" (not-specified) in case of any exception)
      */
     public String getDmiHealthStatus(final String dmiPluginBaseUrl) {
-        final HttpEntity<Object> httpHeaders = new HttpEntity<>(configureHttpHeaders(new HttpHeaders()));
+        final HttpEntity<Object> httpHeaders = new HttpEntity<>(configureHttpHeaders(new HttpHeaders(), null));
         try {
             final JsonNode responseHealthStatus =
                 restTemplate.getForObject(dmiPluginBaseUrl + HEALTH_CHECK_URL_EXTENSION,
@@ -86,9 +90,11 @@ public class DmiRestClient {
         }
     }
 
-    private HttpHeaders configureHttpHeaders(final HttpHeaders httpHeaders) {
+    private HttpHeaders configureHttpHeaders(final HttpHeaders httpHeaders, final String authorization) {
         if (dmiProperties.isDmiBasicAuthEnabled()) {
             httpHeaders.setBasicAuth(dmiProperties.getAuthUsername(), dmiProperties.getAuthPassword());
+        } else if (authorization != null && authorization.toLowerCase(Locale.getDefault()).startsWith("bearer ")) {
+            httpHeaders.add(HttpHeaders.AUTHORIZATION, authorization);
         }
         httpHeaders.setContentType(MediaType.APPLICATION_JSON);
         return httpHeaders;
index f12cc9c..171db52 100644 (file)
@@ -30,10 +30,6 @@ import org.springframework.context.annotation.Configuration;
 @Configuration
 public class TrustLevelCacheConfig extends HazelcastCacheConfig {
 
-    public static final String TRUST_LEVEL_PER_DMI_PLUGIN_BEAN_NAME = "trustLevelPerDmiPlugin";
-
-    public static final String TRUST_LEVEL_PER_CM_HANDLE_BEAN_NAME = "trustLevelPerCmHandle";
-
     private static final MapConfig trustLevelPerCmHandleCacheConfig =
             createMapConfig("trustLevelPerCmHandleCacheConfig");
 
@@ -45,7 +41,7 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig {
      *
      * @return configured map of cm handle name as keys to trust-level for values.
      */
-    @Bean(TRUST_LEVEL_PER_CM_HANDLE_BEAN_NAME)
+    @Bean
     public Map<String, TrustLevel> trustLevelPerCmHandle() {
         return createHazelcastInstance("hazelcastInstanceTrustLevelPerCmHandleMap",
                 trustLevelPerCmHandleCacheConfig).getMap("trustLevelPerCmHandle");
@@ -56,7 +52,7 @@ public class TrustLevelCacheConfig extends HazelcastCacheConfig {
      *
      * @return configured map of dmi-plugin name as keys to trust-level for values.
      */
-    @Bean(TRUST_LEVEL_PER_DMI_PLUGIN_BEAN_NAME)
+    @Bean
     public Map<String, TrustLevel> trustLevelPerDmiPlugin() {
         return createHazelcastInstance("hazelcastInstanceTrustLevelPerDmiPluginMap",
                 trustLevelPerDmiPluginCacheConfig).getMap("trustLevelPerDmiPlugin");
index a43da29..2d7ad69 100644 (file)
@@ -34,14 +34,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import lombok.RequiredArgsConstructor;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
 import org.onap.cps.ncmp.api.impl.inventory.enums.PropertyType;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
 import org.onap.cps.spi.CpsDataPersistenceService;
 import org.onap.cps.spi.FetchDescendantsOption;
 import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.utils.CpsValidator;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Component;
 
 @RequiredArgsConstructor
@@ -51,11 +49,7 @@ public class CmHandleQueriesImpl implements CmHandleQueries {
     private static final String DESCENDANT_PATH = "//";
     private static final String ANCESTOR_CM_HANDLES = "/ancestor::cm-handles";
     private final CpsDataPersistenceService cpsDataPersistenceService;
-
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
-
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerCmHandle;
     private final CpsValidator cpsValidator;
 
index fa18767..a77e78a 100644 (file)
@@ -79,6 +79,7 @@ public class DmiDataOperations extends DmiOperations {
      * @param optionsParamInQuery options query
      * @param topicParamInQuery   topic name for (triggering) async responses
      * @param requestId           requestId for async responses
+     * @param authorization       contents of Authorization header, or null if not present
      * @return {@code ResponseEntity} response entity
      */
     @Timed(value = "cps.ncmp.dmi.get",
@@ -89,7 +90,8 @@ public class DmiDataOperations extends DmiOperations {
                                                          final String resourceId,
                                                          final String optionsParamInQuery,
                                                          final String topicParamInQuery,
-                                                         final String requestId) {
+                                                         final String requestId,
+                                                         final String authorization) {
         final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
         final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
         validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
@@ -97,7 +99,7 @@ public class DmiDataOperations extends DmiOperations {
                 yangModelCmHandle);
         final String dmiResourceDataUrl = getDmiRequestUrl(dataStoreName, cmHandleId, resourceId, optionsParamInQuery,
                 topicParamInQuery, yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
-        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ);
+        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, authorization);
     }
 
     /**
@@ -120,7 +122,7 @@ public class DmiDataOperations extends DmiOperations {
                 yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
         final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
         validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
-        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ);
+        return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, null);
     }
 
     /**
@@ -130,10 +132,12 @@ public class DmiDataOperations extends DmiOperations {
      * @param topicParamInQuery        topic name for (triggering) async responses
      * @param dataOperationRequest     data operation request to execute operations
      * @param requestId                requestId for as a response
+     * @param authorization            contents of Authorization header, or null if not present
      */
     public void requestResourceDataFromDmi(final String topicParamInQuery,
                                            final DataOperationRequest dataOperationRequest,
-                                           final String requestId)  {
+                                           final String requestId,
+                                           final String authorization)  {
 
         final Set<String> cmHandlesIds
                 = getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest);
@@ -145,7 +149,8 @@ public class DmiDataOperations extends DmiOperations {
                 = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(topicParamInQuery,
                 requestId, dataOperationRequest, yangModelCmHandles);
 
-        buildDataOperationRequestUrlAndSendToDmiService(topicParamInQuery, requestId, operationsOutPerDmiServiceName);
+        buildDataOperationRequestUrlAndSendToDmiService(topicParamInQuery, requestId, operationsOutPerDmiServiceName,
+                authorization);
     }
 
     /**
@@ -157,13 +162,15 @@ public class DmiDataOperations extends DmiOperations {
      * @param operationType operation enum
      * @param requestData   the request data
      * @param dataType      data type
+     * @param authorization contents of Authorization header, or null if not present
      * @return {@code ResponseEntity} response entity
      */
     public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleId,
                                                                              final String resourceId,
                                                                              final OperationType operationType,
                                                                              final String requestData,
-                                                                             final String dataType) {
+                                                                             final String dataType,
+                                                                             final String authorization) {
         final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId);
         final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType,
                 yangModelCmHandle);
@@ -172,7 +179,7 @@ public class DmiDataOperations extends DmiOperations {
                 yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA));
         final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
         validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
-        return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType);
+        return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType, authorization);
     }
 
     private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
@@ -234,23 +241,26 @@ public class DmiDataOperations extends DmiOperations {
     private void buildDataOperationRequestUrlAndSendToDmiService(final String topicParamInQuery,
                                                                  final String requestId,
                                                                  final Map<String, List<DmiDataOperation>>
-                                                                groupsOutPerDmiServiceName) {
+                                                                groupsOutPerDmiServiceName,
+                                                                 final String authorization) {
 
         groupsOutPerDmiServiceName.forEach((dmiServiceName, dmiDataOperationRequestBodies) -> {
             final String dmiDataOperationResourceUrl =
                     getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId);
-            sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies);
+            sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies,
+                    authorization);
         });
     }
 
     private void sendDataOperationRequestToDmiService(final String dataOperationResourceUrl,
-                                                      final List<DmiDataOperation> dmiDataOperationRequestBodies) {
+                                                      final List<DmiDataOperation> dmiDataOperationRequestBodies,
+                                                      final String authorization) {
         final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder()
                 .operations(dmiDataOperationRequestBodies).build();
         final String dmiDataOperationRequestAsJsonString =
                 jsonObjectMapper.asJsonString(dmiDataOperationRequest);
         TaskExecutor.executeTask(() -> dmiRestClient.postOperationWithJsonData(dataOperationResourceUrl,
-                                dmiDataOperationRequestAsJsonString, READ),
+                                dmiDataOperationRequestAsJsonString, READ, authorization),
                         DEFAULT_ASYNC_TASK_EXECUTOR_TIMEOUT_IN_MILLISECONDS)
                 .whenCompleteAsync((response, throwable) -> handleTaskCompletionException(throwable,
                         dataOperationResourceUrl, dmiDataOperationRequestBodies));
index dbe386d..f99fe86 100644 (file)
@@ -112,7 +112,7 @@ public class DmiModelOperations extends DmiOperations {
                                                                   final String resourceName) {
         final String dmiResourceDataUrl = getDmiResourceUrl(dmiServiceName, cmHandle, resourceName);
         return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody,
-                OperationType.READ);
+                OperationType.READ, null);
     }
 
     private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences,
index 4c606a9..82c7204 100644 (file)
@@ -24,12 +24,10 @@ import java.util.Collection;
 import java.util.Map;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
 import org.onap.cps.ncmp.api.impl.events.avc.ncmptoclient.AvcEventPublisher;
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence;
 import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.stereotype.Service;
 
 @Slf4j
@@ -37,12 +35,8 @@ import org.springframework.stereotype.Service;
 @RequiredArgsConstructor
 public class TrustLevelManager {
 
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_CM_HANDLE_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerCmHandle;
-
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
-
     private final InventoryPersistence inventoryPersistence;
     private final AvcEventPublisher avcEventPublisher;
     private static final String AVC_CHANGED_ATTRIBUTE_NAME = "trustLevel";
index 78eaf3e..72dc295 100644 (file)
@@ -26,10 +26,8 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.cps.ncmp.api.NetworkCmProxyDataService;
 import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
-import org.onap.cps.ncmp.api.impl.config.embeddedcache.TrustLevelCacheConfig;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevel;
 import org.onap.cps.ncmp.api.impl.trustlevel.TrustLevelManager;
-import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 
@@ -40,10 +38,7 @@ public class DmiPluginWatchDog {
 
     private final DmiRestClient dmiRestClient;
     private final NetworkCmProxyDataService networkCmProxyDataService;
-
     private final TrustLevelManager trustLevelManager;
-
-    @Qualifier(TrustLevelCacheConfig.TRUST_LEVEL_PER_DMI_PLUGIN_BEAN_NAME)
     private final Map<String, TrustLevel> trustLevelPerDmiPlugin;
 
     /**
index 4ac6537..f14439f 100644 (file)
@@ -38,6 +38,10 @@ import org.springframework.stereotype.Service;
 @RequiredArgsConstructor
 public class AlternateIdChecker {
 
+    public enum Operation {
+        CREATE, UPDATE
+    }
+
     private final InventoryPersistence inventoryPersistence;
 
     private static final String NO_CURRENT_ALTERNATE_ID = "";
@@ -96,15 +100,16 @@ public class AlternateIdChecker {
     }
 
     /**
-     * Check all alternate ids of a batch of NEW cm handles.
+     * Check all alternate ids of a batch of cm handles.
      * Includes cross-checks in the batch itself for duplicates. Only the first entry encountered wil be accepted.
-     * This method can only be used for NEW cm handle registrations NOT for updating existing ones
      *
      * @param newNcmpServiceCmHandles the proposed new cm handles
+     * @param operation type of operation being executed
      * @return collection of cm handles ids which are acceptable
      */
     public Collection<String> getIdsOfCmHandlesWithRejectedAlternateId(
-                                    final Collection<NcmpServiceCmHandle> newNcmpServiceCmHandles) {
+                                    final Collection<NcmpServiceCmHandle> newNcmpServiceCmHandles,
+                                    final Operation operation) {
         final Set<String> acceptedAlternateIds = new HashSet<>(newNcmpServiceCmHandles.size());
         final Collection<String> rejectedCmHandleIds = new ArrayList<>();
         for (final NcmpServiceCmHandle ncmpServiceCmHandle : newNcmpServiceCmHandles) {
@@ -119,7 +124,11 @@ public class AlternateIdChecker {
                     log.warn("Alternate id update ignored, cannot update cm handle {}, alternate id is already "
                         + "assigned to a different cm handle (in this batch)", cmHandleId);
                 } else {
-                    isAcceptable = canApplyAlternateId(cmHandleId, NO_CURRENT_ALTERNATE_ID, proposedAlternateId);
+                    if (Operation.CREATE.equals(operation)) {
+                        isAcceptable = canApplyAlternateId(cmHandleId, NO_CURRENT_ALTERNATE_ID, proposedAlternateId);
+                    } else {
+                        isAcceptable = canApplyAlternateId(cmHandleId, proposedAlternateId);
+                    }
                 }
             }
             if (isAcceptable) {
index cb7e1ef..fbfbac5 100644 (file)
@@ -78,7 +78,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
 
     def setup() {
         // always accept all cm handles
-        mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(_) >> []
+        mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(*_) >> []
 
         // always can find all cm handles in DB
         mockInventoryPersistence.getYangModelCmHandles(_) >> { args -> args[0].collect { new YangModelCmHandle(id:it) } }
@@ -418,14 +418,4 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
         'an unexpected exception'    | 'cmhandle'             | new RuntimeException('Failed')            || UNKNOWN_ERROR        | 'Failed'
     }
 
-    def 'Adding data to alternate id caches.'() {
-        given: 'a registration with three CM Handles to be created'
-            def ncmpServiceCmHandles = [new NcmpServiceCmHandle(cmHandleId: 'cmhandle1', alternateId: 'my-alternate-id-1')]
-            def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server', createdCmHandles: ncmpServiceCmHandles)
-        when: 'the DMI plugin registration happens'
-            objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
-        then: 'the new alternate id is added to the cache'
-            1 * mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(ncmpServiceCmHandles) >> ['cmhandle1']
-    }
-
 }
index 9b4fe14..74016e4 100644 (file)
@@ -86,6 +86,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
 
     def NO_TOPIC = null
     def NO_REQUEST_ID = null
+    def NO_AUTH_HEADER = null
     def OPTIONS_PARAM = '(a=1,b=2)'
     def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'test-cm-handle-id')
 
@@ -113,10 +114,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         when: 'write resource data is called'
             objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
                 'testResourceId', CREATE,
-                '{some-json}', 'application/json')
+                '{some-json}', 'application/json', null)
         then: 'DMI called with correct data'
             1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId',
-                    CREATE, '{some-json}', 'application/json')
+                    CREATE, '{some-json}', 'application/json', null)
                 >> { new ResponseEntity<>(HttpStatus.CREATED) }
     }
 
@@ -124,10 +125,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         given: 'cpsDataService returns valid data node'
             mockDataNode()
         and: 'get resource data from DMI is called'
-            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_OPERATIONAL.datastoreName,'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID) >>
+            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_OPERATIONAL.datastoreName,'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) >>
                     new ResponseEntity<>('dmi-response', HttpStatus.OK)
         when: 'get resource data operational for cm-handle is called'
-            def response = objectUnderTest.getResourceDataForCmHandle(PASSTHROUGH_OPERATIONAL.datastoreName, 'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID)
+            def response = objectUnderTest.getResourceDataForCmHandle(PASSTHROUGH_OPERATIONAL.datastoreName, 'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
         then: 'DMI returns a json response'
             assert response == 'dmi-response'
     }
@@ -136,10 +137,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         given: 'cpsDataService returns valid data node'
             mockDataNode()
         and: 'DMI returns valid response and data'
-            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID) >>
+            mockDmiDataOperations.getResourceDataFromDmi(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER) >>
                     new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
         when: 'get resource data is called'
-            def response = objectUnderTest.getResourceDataForCmHandle(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID)
+            def response = objectUnderTest.getResourceDataForCmHandle(PASSTHROUGH_RUNNING.datastoreName, 'testCmHandle', 'testResourceId', OPTIONS_PARAM, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
         then: 'get resource data returns expected response'
             assert response == '{dmi-response}'
     }
@@ -157,9 +158,9 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         given: 'cpsDataService returns valid data node'
             def dataOperationRequest = getDataOperationRequest(datastoreName)
         when: 'request resource data for data operation is called'
-            objectUnderTest.executeDataOperationForCmHandles('some topic', dataOperationRequest, 'requestId')
+            objectUnderTest.executeDataOperationForCmHandles('some topic', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
         then: 'request resource data for data operation returns expected response'
-            1 * mockDmiDataOperations.requestResourceDataFromDmi('some topic', dataOperationRequest, 'requestId')
+            1 * mockDmiDataOperations.requestResourceDataFromDmi('some topic', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
         where: 'the following data stores are used'
             datastoreName << [PASSTHROUGH_RUNNING.datastoreName, PASSTHROUGH_OPERATIONAL.datastoreName]
     }
@@ -259,10 +260,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
         when: 'get resource data is called'
             objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
                 'testResourceId', UPDATE,
-                '{some-json}', 'application/json')
+                '{some-json}', 'application/json', NO_AUTH_HEADER)
         then: 'DMI called with correct data'
             1 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle', 'testResourceId',
-                    UPDATE, '{some-json}', 'application/json')
+                    UPDATE, '{some-json}', 'application/json', NO_AUTH_HEADER)
                 >> { new ResponseEntity<>(HttpStatus.OK) }
     }
 
@@ -273,7 +274,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
             dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
             mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle]
         and: 'no rejected cm handles because of alternate ids'
-            mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(_) >> []
+            mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(*_) >> []
         when: 'parse and create cm handle in dmi registration then sync module'
             mockDmiPluginRegistration.createdCmHandles = ['test-cm-handle-id']
             objectUnderTest.processCreatedCmHandles(mockDmiPluginRegistration, new DmiPluginRegistrationResponse())
index e00a426..cbed417 100644 (file)
@@ -49,6 +49,12 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
     def mockAlternateIdChecker = Mock(AlternateIdChecker)
 
     def objectUnderTest = new NetworkCmProxyDataServicePropertyHandler(mockInventoryPersistence, mockCpsDataService, jsonObjectMapper, mockAlternateIdChecker)
+
+    def setup() {
+        // Always accept all alternate IDs
+        mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(*_) >> []
+    }
+
     def static cmHandleId = 'myHandle1'
     def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}']"
 
@@ -66,7 +72,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
         when: 'update data node leaves is called with the update request'
             objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
         then: 'the replace list method is called with correct params'
-            1 * mockInventoryPersistence.replaceListContent(cmHandleXpath,_) >> { args ->
+            1 * mockInventoryPersistence.replaceListContent(cmHandleXpath, _) >> { args ->
                 {
                     assert args[1].leaves.size() == expectedPropertiesAfterUpdate.size()
                     assert args[1].leaves.containsAll(convertToProperties(expectedPropertiesAfterUpdate))
@@ -142,10 +148,10 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
                 assert it.errorText == expectedErrorText
             }
         where:
-        scenario                   | cmHandleId               | exception                                                                                           || expectedError        | expectedErrorText
-        'Cm Handle does not exist' | 'cmHandleId'             | new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR)                        || CM_HANDLES_NOT_FOUND | 'cm handle id(s) not found'
-        'Unknown'                  | 'cmHandleId'             | new RuntimeException('Failed')                                                                      || UNKNOWN_ERROR        | 'Failed'
-        'Invalid cm handle id'     | 'cmHandleId with spaces' | new DataValidationException('Name Validation Error.', cmHandleId + 'contains an invalid character') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
+            scenario                   | cmHandleId               | exception                                                                                           || expectedError        | expectedErrorText
+            'Cm Handle does not exist' | 'cmHandleId'             | new DataNodeNotFoundException(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR)                        || CM_HANDLES_NOT_FOUND | 'cm handle id(s) not found'
+            'Unknown'                  | 'cmHandleId'             | new RuntimeException('Failed')                                                                      || UNKNOWN_ERROR        | 'Failed'
+            'Invalid cm handle id'     | 'cmHandleId with spaces' | new DataValidationException('Name Validation Error.', cmHandleId + 'contains an invalid character') || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
     }
 
     def 'Multiple update operations in a single request'() {
@@ -177,42 +183,44 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
                 assert it.errorText == 'cm handle id(s) not found'
             }
         then: 'the replace list method is called twice'
-            2 * mockInventoryPersistence.replaceListContent(cmHandleXpath,_)
+            2 * mockInventoryPersistence.replaceListContent(cmHandleXpath, _)
     }
 
-    def 'Update CM Handle Alternate ID with #scenario'() {
-        given: 'an existing cm handle'
-            DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': cmHandleId])
-        and: 'an update request with an alternate id'
-            def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1')
-        when: 'update alternate id method is called with the update request'
-            objectUnderTest.updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle)
-        then: 'the update node leaves method is invoked as many times as expected'
-            callsToDataService * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _) >>
+    def 'Update alternate id of existing CM Handle.'() {
+        given: 'cm handles request'
+            def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1')]
+        and: 'a data node found'
+            def dataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': cmHandleId, 'alternate-id': 'alt-1'])
+            mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(cmHandleId) >> [dataNode]
+        when: 'cm handle properties is updated'
+            def response = objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
+        then: 'the update is delegated to cps data service with correct parameters'
+            1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', _, _) >>
                     { args ->
                         assert args[3].contains('alt-1')
                     }
-            mockAlternateIdChecker.canApplyAlternateId(cmHandleId, '','alt-1') >> isNewMapping
-        where: 'following updates are attempted'
-            scenario                | isNewMapping || callsToDataService
-            'new alternate id   '   | true         || 1
-            'existing alternate id' | false        || 0
+        and: 'one successful registration response'
+            response.size() == 1
+        and: 'the response shows success for the given cm handle id'
+                assert response[0].status == Status.SUCCESS
+                assert response[0].cmHandle == cmHandleId
     }
 
-    def 'Alternate ID removed from cache when persisting fails.'() {
-        given: 'an existing data node and an update request with an alternate id'
-            def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1')
-            DataNode existingCmHandleDataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': cmHandleId, 'alternate-id': null])
-        and: 'an applicable alternate id for the cm handle'
-            mockAlternateIdChecker.canApplyAlternateId(cmHandleId, '','alt-1') >> true
-        and: 'but an exception occurs while saving'
-            def originalException = new NullPointerException('some exception')
-            mockCpsDataService.updateNodeLeaves(*_) >> { throw originalException }
-        when: 'updating of alternate id called'
-            objectUnderTest.updateAlternateId(existingCmHandleDataNode, ncmpServiceCmHandle)
-        then: 'the original exception is thrown up'
-            def thrownException = thrown(NullPointerException)
-            assert thrownException == originalException
+    def 'Update with rejected alternate id.'() {
+        given: 'cm handles request'
+            def updatedNcmpServiceCmHandles = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, alternateId: 'alt-1')]
+        and: 'a data node found'
+            def dataNode = new DataNode(xpath: cmHandleXpath, leaves: ['id': cmHandleId, 'alternate-id': 'alt-1'])
+            mockInventoryPersistence.getCmHandleDataNodeByCmHandleId(cmHandleId) >> [dataNode]
+        when: 'attempt to update the cm handle'
+            def response = objectUnderTest.updateCmHandleProperties(updatedNcmpServiceCmHandles)
+        then: 'the update is NOT delegated to cps data service'
+            0 * mockCpsDataService.updateNodeLeaves(*_)
+        and:  'the alternate id checker rejects the given cm handle (override default setup behavior)'
+            mockAlternateIdChecker.getIdsOfCmHandlesWithRejectedAlternateId(*_) >> [cmHandleId]
+        and: 'the response shows a failure for the given cm handle id'
+            assert response[0].status == Status.FAILURE
+            assert response[0].cmHandle == cmHandleId
     }
 
     def convertToProperties(expectedPropertiesAfterUpdateAsMap) {
index 0176de7..c8e34b1 100644 (file)
@@ -48,6 +48,10 @@ import static org.onap.cps.ncmp.api.impl.operations.OperationType.CREATE
 @ContextConfiguration(classes = [DmiProperties, DmiRestClient, ObjectMapper])
 class DmiRestClientSpec extends Specification {
 
+    static final NO_AUTH_HEADER = null
+    static final BASIC_AUTH_HEADER = 'Basic c29tZS11c2VyOnNvbWUtcGFzc3dvcmQ='
+    static final BEARER_AUTH_HEADER = 'Bearer my-bearer-token'
+
     @SpringBean
     RestTemplate mockRestTemplate = Mock(RestTemplate)
 
@@ -66,7 +70,7 @@ class DmiRestClientSpec extends Specification {
         given: 'the rest template returns a valid response entity for the expected parameters'
             mockRestTemplate.postForEntity('my url', _ as HttpEntity, Object.class) >> responseFromRestTemplate
         when: 'POST operation is invoked'
-            def result = objectUnderTest.postOperationWithJsonData('my url', 'some json', READ)
+            def result = objectUnderTest.postOperationWithJsonData('my url', 'some json', READ, null)
         then: 'the output of the method is equal to the output from the test template'
             result == responseFromRestTemplate
     }
@@ -77,7 +81,7 @@ class DmiRestClientSpec extends Specification {
             def httpServerErrorException = new HttpServerErrorException(HttpStatus.FORBIDDEN, 'status text', serverResponse, null)
             mockRestTemplate.postForEntity(*_) >> { throw httpServerErrorException }
         when: 'POST operation is invoked'
-            def result = objectUnderTest.postOperationWithJsonData('some url', 'some json', operation)
+            def result = objectUnderTest.postOperationWithJsonData('some url', 'some json', operation, null)
         then: 'a Http Client Exception is thrown'
             def thrown = thrown(HttpClientRequestException)
         and: 'the exception has the relevant details from the error response'
@@ -113,15 +117,20 @@ class DmiRestClientSpec extends Specification {
             'exception' | {throw new Exception()}
     }
 
-    def 'Basic auth header #scenario'() {
+    def 'DMI auth header #scenario'() {
         when: 'Specific dmi properties are provided'
             dmiProperties.dmiBasicAuthEnabled = authEnabled
         then: 'http headers to conditionally have Authorization header'
-            assert (objectUnderTest.configureHttpHeaders(new HttpHeaders()).get('Authorization') != null) == isPresentInHttpHeader
+            def authHeaderValues = objectUnderTest.configureHttpHeaders(new HttpHeaders(), ncmpAuthHeader).getOrEmpty('Authorization')
+            def outputAuthHeader = (authHeaderValues == null ? null : authHeaderValues[0])
+            assert outputAuthHeader == expectedAuthHeader
         where: 'the following configurations are used'
-            scenario        | authEnabled || isPresentInHttpHeader
-            'auth enabled'  | true        || true
-            'auth disabled' | false       || false
+            scenario                                          | authEnabled | ncmpAuthHeader     || expectedAuthHeader
+            'DMI basic auth enabled, no NCMP bearer token'    | true        | NO_AUTH_HEADER     || BASIC_AUTH_HEADER
+            'DMI basic auth enabled, with NCMP bearer token'  | true        | BEARER_AUTH_HEADER || BASIC_AUTH_HEADER
+            'DMI basic auth disabled, no NCMP bearer token'   | false       | NO_AUTH_HEADER     || NO_AUTH_HEADER
+            'DMI basic auth disabled, with NCMP bearer token' | false       | BEARER_AUTH_HEADER || BEARER_AUTH_HEADER
+            'DMI basic auth disabled, with NCMP basic auth'   | false       | BASIC_AUTH_HEADER  || NO_AUTH_HEADER
     }
 
 }
index 2229b32..7d8ac74 100644 (file)
@@ -59,6 +59,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
     def dmiServiceBaseUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/data/ds/ncmp-datastore:"
     def NO_TOPIC = null
     def NO_REQUEST_ID = null
+    def NO_AUTH_HEADER = null
     @Shared
     def OPTIONS_PARAM = '(a=1,b=2)'
 
@@ -77,11 +78,11 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with the expected parameters'
             def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
             def expectedUrl = dmiServiceBaseUrl + "${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}"
-            mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ) >> responseFromDmi
+            mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ, NO_AUTH_HEADER) >> responseFromDmi
             dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
         when: 'get resource data is invoked'
             def result = objectUnderTest.getResourceDataFromDmi(dataStore.datastoreName, cmHandleId, resourceIdentifier,
-                    options, NO_TOPIC, NO_REQUEST_ID)
+                    options, NO_TOPIC, NO_REQUEST_ID, NO_AUTH_HEADER)
         then: 'the result is the response from the DMI service'
             assert result == responseFromDmi
         where: 'the following parameters are used'
@@ -104,16 +105,16 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
             def responseFromDmi = new ResponseEntity<Object>(HttpStatus.ACCEPTED)
             def expectedDmiBatchResourceDataUrl = "ncmp/v1/data/topic=my-topic-name"
             def expectedBatchRequestAsJson = '{"operations":[{"operation":"read","operationId":"operational-14","datastore":"ncmp-datastore:passthrough-operational","options":"some option","resourceIdentifier":"some resource identifier","cmHandles":[{"id":"some-cm-handle","cmHandleProperties":{"prop1":"val1"}}]}]}'
-            mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName) >> responseFromDmi
+            mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, _, READ.operationName, NO_AUTH_HEADER) >> responseFromDmi
             dmiServiceUrlBuilder.getDataOperationRequestUrl(_, _) >> expectedDmiBatchResourceDataUrl
         and: ' a flag to track the post operation call'
             def postOperationWithJsonDataMethodCalled = false
         and: 'the (mocked) dmi rest client will use the flag to indicate it is called and capture the request body'
-            mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, expectedBatchRequestAsJson, READ) >> {
+            mockDmiRestClient.postOperationWithJsonData(expectedDmiBatchResourceDataUrl, expectedBatchRequestAsJson, READ, null) >> {
                 postOperationWithJsonDataMethodCalled = true
             }
         when: 'get resource data for group of cm handles are invoked'
-            objectUnderTest.requestResourceDataFromDmi('my-topic-name', dataOperationRequest, 'requestId')
+            objectUnderTest.requestResourceDataFromDmi('my-topic-name', dataOperationRequest, 'requestId', NO_AUTH_HEADER)
         then: 'validate the post operation was called and ncmp generated dmi request body json args'
             new PollingConditions().within(1) {
                 assert postOperationWithJsonDataMethodCalled == true
@@ -148,7 +149,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with the expected parameters'
             def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
             def expectedUrl = dmiServiceBaseUrl + "passthrough-operational?resourceIdentifier=/"
-            mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}', READ) >> responseFromDmi
+            mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"operation":"read","cmHandleProperties":{"prop1":"val1"}}', READ, null) >> responseFromDmi
             dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
         when: 'get resource data is invoked'
             def result = objectUnderTest.getResourceDataFromDmi( PASSTHROUGH_OPERATIONAL.datastoreName, cmHandleId, NO_REQUEST_ID)
@@ -164,9 +165,9 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
             def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"}}'
             def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
             dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
-            mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, operation) >> responseFromDmi
+            mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, operation, NO_AUTH_HEADER) >> responseFromDmi
         when: 'write resource method is invoked'
-            def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId, 'parent/child', operation, 'requestData', 'some data type')
+            def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId, 'parent/child', operation, 'requestData', 'some data type', NO_AUTH_HEADER)
         then: 'the result is the response from the DMI service'
             assert result == responseFromDmi
         where: 'the following operation is performed'
index a105f84..ae17c56 100644 (file)
@@ -51,6 +51,8 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
     @SpringBean
     JsonObjectMapper spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
 
+    def NO_AUTH_HEADER = null
+
     def 'Retrieving module references.'() {
         given: 'a cm handle'
             mockYangModelCmHandleRetrieval([])
@@ -58,7 +60,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
             def moduleReferencesAsLisOfMaps = [[moduleName: 'mod1', revision: 'A'], [moduleName: 'mod2', revision: 'X']]
             def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules"
             def responseFromDmi = new ResponseEntity([schemas: moduleReferencesAsLisOfMaps], HttpStatus.OK)
-            mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{}}', READ)
+            mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{}}', READ, NO_AUTH_HEADER)
                     >> responseFromDmi
         when: 'get module references is called'
             def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
@@ -91,7 +93,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with tha expected parameters'
             def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
             mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
-                    '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
+                    '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ, NO_AUTH_HEADER) >> responseFromDmi
         when: 'a get module references is called'
             def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
         then: 'the result is the response from DMI service'
@@ -110,7 +112,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
                                                       [moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK)
             def expectedModuleReferencesInRequest = '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
             mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
-                    '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ) >> responseFromDmi
+                    '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ, NO_AUTH_HEADER) >> responseFromDmi
         when: 'get new yang resources from DMI service'
             def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
         then: 'the result has the 2 expected yang (re)sources (order is not guaranteed)'
@@ -142,7 +144,8 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
         and: 'a positive response from DMI service when it is called with the expected parameters'
             def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
             mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
-                    '{"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
+                    '{"data":{"modules":[{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}]},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}',
+                    READ, NO_AUTH_HEADER) >> responseFromDmi
         when: 'get new yang resources from DMI service'
             def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
         then: 'the result is the response from DMI service'
index aaa0344..0eabaa1 100644 (file)
@@ -20,7 +20,6 @@
 
 package org.onap.cps.ncmp.api.impl.utils
 
-
 import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence
 import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
@@ -68,25 +67,41 @@ class AlternateIdCheckerSpec extends Specification {
             'other alternate id' || false
     }
 
-    def 'Check a batch of NEW cm handles with #scenario.'() {
+    def 'Check a batch of created cm handles with #scenario.'() {
         given: 'a batch of 2 new cm handles alternate id ids #alt1 and #alt2'
             def batch = [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: alt1),
                          new NcmpServiceCmHandle(cmHandleId: 'ch-2', alternateId: alt2)]
-        and: 'the database already contains cm handle(s) with these alternate ids: #alreadyinDb'
+        and: 'the database already contains cm handle(s) with these alternate ids: #altAlreadyInDb'
             mockInventoryPersistenceService.getCmHandleDataNodeByAlternateId(_) >>
                 {  args -> altAlreadyInDb.contains(args[0]) ? new DataNode() : throwDataNodeNotFoundException() }
         when: 'the batch of new cm handles is checked'
-            def result = objectUnderTest.getIdsOfCmHandlesWithRejectedAlternateId(batch)
-        then: 'the result only contains the ids of the acceptable cm handles'
-            assert result.contains('ch-1') == rejectCh1
-            assert result.contains('ch-2') == rejectCh2
+            def result = objectUnderTest.getIdsOfCmHandlesWithRejectedAlternateId(batch, AlternateIdChecker.Operation.CREATE)
+        then: 'the result contains ids of the rejected cm handles'
+            assert result == expectedRejectedCmHandleIds
         where: 'the following alternate ids are used'
-            scenario                          | alt1   | alt2   | altAlreadyInDb  || rejectCh1 | rejectCh2
-            'no alternate ids'                | ''     | ''     | ['dont matter'] || false      | false
-            'new alternate ids'               | 'fdn1' | 'fdn2' | ['other fdn']   || false      | false
-            'one already used alternate id'   | 'fdn1' | 'fdn2' | ['fdn1']        || true       | false
-            'two already used alternate ids'  | 'fdn1' | 'fdn2' | ['fdn1','fdn2'] || true       | true
-            'duplicate alternate id in batch' | 'fdn1' | 'fdn1' | ['dont matter'] || false      | true
+            scenario                          | alt1   | alt2   | altAlreadyInDb  || expectedRejectedCmHandleIds
+            'no alternate ids'                | ''     | ''     | ['dont matter'] || []
+            'new alternate ids'               | 'fdn1' | 'fdn2' | ['other fdn']   || []
+            'one already used alternate id'   | 'fdn1' | 'fdn2' | ['fdn1']        || ['ch-1']
+            'duplicate alternate id in batch' | 'fdn1' | 'fdn1' | ['dont matter'] || ['ch-2']
+    }
+
+    def 'Check a batch of updates to existing cm handles with #scenario.'() {
+        given: 'a batch of 1 existing cm handle update alternate id to #proposedAlt'
+            def batch = [new NcmpServiceCmHandle(cmHandleId: 'ch-1', alternateId: proposedAlt)]
+        and: 'the database already contains a cm handle with alternate id: #altAlreadyInDb'
+            mockInventoryPersistenceService.getCmHandleDataNodeByAlternateId(_) >>
+                    {  args -> altAlreadyInDb.equals(args[0]) ? new DataNode() : throwDataNodeNotFoundException() }
+            mockInventoryPersistenceService.getYangModelCmHandle(_) >> new YangModelCmHandle(alternateId: altAlreadyInDb)
+        when: 'the batch of cm handle updates is checked'
+            def result = objectUnderTest.getIdsOfCmHandlesWithRejectedAlternateId(batch, AlternateIdChecker.Operation.UPDATE)
+        then: 'the result contains ids of the rejected cm handles'
+            assert result == expectedRejectedCmHandleIds
+        where: 'the following parameters are used'
+            scenario                      | proposedAlt | altAlreadyInDb || expectedRejectedCmHandleIds
+            'no alternate id'             | 'fdn1'      | ''             || []
+            'used the same alternate id'  | 'fdn1'      | 'fdn1'         || []
+            'used different alternate id' | 'otherFdn'  | 'fdn1'         || ['ch-1']
     }
 
     def throwDataNodeNotFoundException() {
index 5c49cbe..699bf3c 100644 (file)
@@ -32,7 +32,7 @@
 
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-parent</artifactId>
-    <version>3.4.6-SNAPSHOT</version>
+    <version>3.4.7-SNAPSHOT</version>
     <packaging>pom</packaging>
 
     <properties>
                 <plugin>
                     <groupId>org.springframework.boot</groupId>
                     <artifactId>spring-boot-maven-plugin</artifactId>
-                    <version>3.2.2</version>
+                    <version>3.1.2</version>
                     <executions>
                         <execution>
                             <goals>
index 023ab19..fb161c7 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index f60a9be..f394270 100644 (file)
@@ -33,8 +33,6 @@ dataspaces:
         $ref: 'components.yml#/components/responses/NoContent'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -63,8 +61,6 @@ schemaSet:
                 $ref: 'components.yml#/components/schemas/SchemaSetDetails'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -90,8 +86,6 @@ schemaSetBySchemaSetName:
               $ref: 'components.yml#/components/schemas/SchemaSetDetails'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -111,8 +105,6 @@ schemaSetBySchemaSetName:
         $ref: 'components.yml#/components/responses/NoContent'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -141,8 +133,6 @@ anchorsByDataspace:
                 $ref: 'components.yml#/components/schemas/AnchorDetails'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -168,8 +158,6 @@ anchorByDataspaceAndAnchorName:
               $ref: 'components.yml#/components/schemas/AnchorDetails'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -189,8 +177,6 @@ anchorByDataspaceAndAnchorName:
         $ref: 'components.yml#/components/responses/NoContent'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -216,8 +202,6 @@ adminDataspaces:
                $ref: 'components.yml#/components/schemas/DataspaceDetails'
      '400':
        $ref: 'components.yml#/components/responses/BadRequest'
-     '401':
-       $ref: 'components.yml#/components/responses/Unauthorized'
      '403':
        $ref: 'components.yml#/components/responses/Forbidden'
      '500':
@@ -242,8 +226,6 @@ adminDataspace:
              $ref: 'components.yml#/components/schemas/DataspaceDetails'
      '400':
        $ref: 'components.yml#/components/responses/BadRequest'
-     '401':
-       $ref: 'components.yml#/components/responses/Unauthorized'
      '403':
        $ref: 'components.yml#/components/responses/Forbidden'
      '500':
index 56f7f1b..c92f773 100644 (file)
@@ -31,8 +31,6 @@ dataspaces:
         $ref: 'components.yml#/components/responses/Created'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -57,8 +55,6 @@ anchorsByDataspace:
         $ref: 'components.yml#/components/responses/Created'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -88,8 +84,6 @@ schemaSet:
         $ref: 'components.yml#/components/responses/Created'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
index 14e2cfe..e501ad8 100644 (file)
@@ -30,8 +30,6 @@ dataspaces:
         $ref: 'components.yml#/components/responses/CreatedV2'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -55,8 +53,6 @@ anchorsByDataspace:
         $ref: 'components.yml#/components/responses/CreatedV2'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -85,8 +81,6 @@ schemaSet:
         $ref: 'components.yml#/components/responses/CreatedV2'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
index 0a032e4..b9d2e59 100644 (file)
@@ -46,8 +46,6 @@ listElementByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/Created'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -78,8 +76,6 @@ listElementByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/Ok'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -122,8 +118,6 @@ nodesByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/Created'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '409':
@@ -157,8 +151,6 @@ nodesByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/Ok'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -180,8 +172,6 @@ nodesByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/NoContent'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -212,8 +202,6 @@ nodesByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/Ok'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
index 67ddecd..3941856 100644 (file)
@@ -41,8 +41,6 @@ nodeByDataspaceAndAnchor:
                 $ref: 'components.yml#/components/examples/dataSample'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -67,8 +65,6 @@ listElementByDataspaceAndAnchor:
         $ref: 'components.yml#/components/responses/NoContent'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
index c7629b7..cbb5ce4 100644 (file)
@@ -40,8 +40,6 @@ nodeByDataspaceAndAnchor:
                 $ref: 'components.yml#/components/examples/dataSample'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -73,8 +71,6 @@ deltaByDataspaceAndAnchors:
                 $ref: 'components.yml#/components/examples/deltaReportSample'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
index 6ec117f..9db2823 100644 (file)
@@ -43,8 +43,6 @@ nodesByDataspaceAndAnchorAndCpsPath:
                 $ref: 'components.yml#/components/examples/dataSample'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
index 4443fb1..7f0ceff 100644 (file)
@@ -40,8 +40,6 @@ nodesByDataspaceAndAnchorAndCpsPath:
                 $ref: 'components.yml#/components/examples/dataSample'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
@@ -73,8 +71,6 @@ nodesByDataspaceAndCpsPath:
                 $ref: 'components.yml#/components/examples/dataSampleAcrossAnchors'
       '400':
         $ref: 'components.yml#/components/responses/BadRequest'
-      '401':
-        $ref: 'components.yml#/components/responses/Unauthorized'
       '403':
         $ref: 'components.yml#/components/responses/Forbidden'
       '500':
index 0af6a36..9e484af 100644 (file)
@@ -28,7 +28,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index bd99be1..a6e1e10 100644 (file)
@@ -26,7 +26,7 @@
     <parent>\r
         <groupId>org.onap.cps</groupId>\r
         <artifactId>cps-parent</artifactId>\r
-        <version>3.4.6-SNAPSHOT</version>\r
+        <version>3.4.7-SNAPSHOT</version>\r
         <relativePath>../cps-parent/pom.xml</relativePath>\r
     </parent>\r
 \r
@@ -71,7 +71,7 @@
         <!-- Add Hibernate support for Postgres datatype JSONB and Postgres arrays -->\r
         <dependency>\r
             <groupId>io.hypersistence</groupId>\r
-            <artifactId>hypersistence-utils-hibernate-63</artifactId>\r
+            <artifactId>hypersistence-utils-hibernate-60</artifactId>\r
         </dependency>\r
         <dependency>\r
             <groupId>org.projectlombok</groupId>\r
index b449a78..b0f9a2d 100755 (executable)
@@ -69,7 +69,6 @@ import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.parser.api.YangSyntaxErrorException;
 import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangModelDependencyInfo;
 import org.springframework.dao.DataIntegrityViolationException;
-import org.springframework.retry.RetryContext;
 import org.springframework.retry.annotation.Backoff;
 import org.springframework.retry.annotation.Retryable;
 import org.springframework.retry.support.RetrySynchronizationManager;
@@ -278,8 +277,8 @@ public class CpsModulePersistenceServiceImpl implements CpsModulePersistenceServ
                                 dataIntegrityViolationException, newYangResourceEntities);
                 convertedException.ifPresent(
                         e -> {
-                            final RetryContext context = RetrySynchronizationManager.getContext();
-                            int retryCount = context == null ? 0 : context.getRetryCount();
+                            int retryCount = RetrySynchronizationManager.getContext() == null ? 0
+                                                     : RetrySynchronizationManager.getContext().getRetryCount();
                             log.warn("Cannot persist duplicated yang resource. System will attempt this method "
                                     + "up to 5 times. Current retry count : {}", ++retryCount, e);
                         });
index fdc8177..58716f3 100644 (file)
@@ -29,7 +29,7 @@
   <parent>
     <groupId>org.onap.cps</groupId>
     <artifactId>cps-parent</artifactId>
-    <version>3.4.6-SNAPSHOT</version>
+    <version>3.4.7-SNAPSHOT</version>
     <relativePath>../cps-parent/pom.xml</relativePath>
   </parent>
 
       <artifactId>cloudevents-spring</artifactId>
     </dependency>
     <!-- T E S T   D E P E N D E N C I E S -->
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.groovy</groupId>
       <artifactId>groovy</artifactId>
index fffce8d..9b424a5 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
     </parent>
 
     <artifactId>dmi-plugin-demo-and-csit-stub-app</artifactId>
             <artifactId>dmi-plugin-demo-and-csit-stub-service</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.jetty</groupId>
+            <artifactId>jetty-server</artifactId>
+            <version>11.0.16</version>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <version>6.0.0</version>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
index bddeab1..ac9eead 100644 (file)
@@ -21,7 +21,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>dmi-plugin-demo-and-csit-stub</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
     </parent>
     <artifactId>dmi-plugin-demo-and-csit-stub-service</artifactId>
 
index 1819dcc..b536c75 100644 (file)
@@ -52,6 +52,7 @@ import org.springframework.kafka.core.KafkaTemplate;
 import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
@@ -89,7 +90,7 @@ public class DmiRestStubController {
      * @return ResponseEntity response entity having module response as json string.
      */
     @PostMapping("/v1/ch/{cmHandleId}/modules")
-    public ResponseEntity<String> getModuleReferences(@PathVariable("cmHandleId") final String cmHandleId,
+    public ResponseEntity<String> getModuleReferences(@PathVariable final String cmHandleId,
                                                       @RequestBody final Object moduleReferencesRequest) {
         delay(moduleReferencesDelayMs);
         final String moduleResponseContent = getModuleResourceResponse(cmHandleId,
@@ -108,7 +109,7 @@ public class DmiRestStubController {
      */
     @PostMapping("/v1/ch/{cmHandleId}/moduleResources")
     public ResponseEntity<String> retrieveModuleResources(
-            @PathVariable("cmHandleId") final String cmHandleId,
+            @PathVariable final String cmHandleId,
             @RequestBody final Object moduleResourcesReadRequest) {
         delay(moduleResourcesDelayMs);
         final String moduleResourcesResponseContent = getModuleResourceResponse(cmHandleId,
@@ -118,7 +119,7 @@ public class DmiRestStubController {
     }
 
     /**
-     * Get resource data from passthrough operational or running for a cm handle.
+     * Create resource data from passthrough operational or running for a cm handle.
      *
      * @param cmHandleId              The identifier for a network function, network element, subnetwork,
      *                                or any other cm object by managed Network CM Proxy
@@ -134,7 +135,9 @@ public class DmiRestStubController {
             @PathVariable("datastoreName") final String datastoreName,
             @RequestParam(value = "resourceIdentifier") final String resourceIdentifier,
             @RequestParam(value = "options", required = false) final String options,
-            @RequestParam(value = "topic", required = false) final String topic) {
+            @RequestParam(value = "topic", required = false) final String topic,
+            @RequestHeader(value = "Authorization", required = false) final String authorization) {
+        log.info("DMI AUTH HEADER: {}", authorization);
         delay(dataForCmHandleDelayMs);
         final String sampleJson = ResourceFileReaderUtil.getResourceFileContent(applicationContext.getResource(
                 ResourceLoader.CLASSPATH_URL_PREFIX + "data/operational/ietf-network-topology-sample-rfc8345.json"));
index ede50da..4cec8e6 100644 (file)
@@ -22,7 +22,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
 
index bade85e..2798b78 100644 (file)
@@ -55,16 +55,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -134,16 +124,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -202,16 +182,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -279,16 +249,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -351,16 +311,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -429,16 +379,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -511,16 +451,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -595,16 +525,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -671,16 +591,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -749,16 +659,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -826,16 +726,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -907,16 +797,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -991,16 +871,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1067,16 +937,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1155,16 +1015,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1250,16 +1100,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1347,16 +1187,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1444,16 +1274,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1556,16 +1376,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1680,16 +1490,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1801,16 +1601,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1886,16 +1676,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1994,16 +1774,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -2103,16 +1873,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -2205,16 +1965,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -2300,16 +2050,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -2396,16 +2136,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -2502,16 +2232,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized request
-                details: This request is unauthorized
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -2766,16 +2486,6 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
       description: Bad Request
-    Unauthorized:
-      content:
-        application/json:
-          example:
-            status: 401
-            message: Unauthorized request
-            details: This request is unauthorized
-          schema:
-            $ref: '#/components/schemas/ErrorMessage'
-      description: Unauthorized
     Forbidden:
       content:
         application/json:
index 53f51f3..ff9f4ba 100644 (file)
@@ -32,16 +32,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -115,16 +105,6 @@ paths:
                   type: string
                 type: array
           description: OK
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -169,16 +149,6 @@ paths:
                   type: string
                 type: array
           description: OK
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -226,16 +196,6 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
       description: Bad Request
-    Unauthorized:
-      content:
-        application/json:
-          example:
-            status: 401
-            message: Unauthorized error message
-            details: Unauthorized error details
-          schema:
-            $ref: '#/components/schemas/ErrorMessage'
-      description: Unauthorized
     Forbidden:
       content:
         application/json:
index a1cc5d9..9203b6d 100644 (file)
@@ -56,6 +56,12 @@ paths:
           default: application/json
           example: application/yang-data+json
           type: string
+      - description: Authorization parameter for request.
+        in: header
+        name: Authorization
+        required: false
+        schema:
+          type: string
       responses:
         "204":
           content: {}
@@ -70,16 +76,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -199,6 +195,12 @@ paths:
         schema:
           default: false
           type: boolean
+      - description: Authorization parameter for request.
+        in: header
+        name: Authorization
+        required: false
+        schema:
+          type: string
       responses:
         "200":
           content:
@@ -220,16 +222,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -312,6 +304,12 @@ paths:
           default: application/json
           example: application/yang-data+json
           type: string
+      - description: Authorization parameter for request.
+        in: header
+        name: Authorization
+        required: false
+        schema:
+          type: string
       requestBody:
         content:
           '*/*':
@@ -339,16 +337,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -430,6 +418,12 @@ paths:
           default: application/json
           example: application/yang-data+json
           type: string
+      - description: Authorization parameter for request.
+        in: header
+        name: Authorization
+        required: false
+        schema:
+          type: string
       requestBody:
         content:
           application/json:
@@ -461,16 +455,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -553,6 +537,12 @@ paths:
           default: application/json
           example: application/yang-data+json
           type: string
+      - description: Authorization parameter for request.
+        in: header
+        name: Authorization
+        required: false
+        schema:
+          type: string
       requestBody:
         content:
           application/json:
@@ -587,16 +577,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -649,6 +629,12 @@ paths:
         required: true
         schema:
           type: string
+      - description: Authorization parameter for request.
+        in: header
+        name: Authorization
+        required: false
+        schema:
+          type: string
       requestBody:
         content:
           application/json:
@@ -672,16 +658,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -806,16 +782,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -883,16 +849,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -954,16 +910,6 @@ paths:
                   $ref: '#/components/schemas/RestModuleDefinition'
                 type: array
           description: OK
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1041,16 +987,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1104,16 +1040,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "404":
           content:
             application/json:
@@ -1167,16 +1093,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "404":
           content:
             application/json:
@@ -1254,16 +1170,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1327,16 +1233,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "404":
           content:
             application/json:
@@ -1399,16 +1295,6 @@ paths:
               schema:
                 $ref: '#/components/schemas/ErrorMessage'
           description: Bad Request
-        "401":
-          content:
-            application/json:
-              example:
-                status: 401
-                message: Unauthorized error message
-                details: Unauthorized error details
-              schema:
-                $ref: '#/components/schemas/ErrorMessage'
-          description: Unauthorized
         "403":
           content:
             application/json:
@@ -1645,6 +1531,13 @@ components:
       schema:
         default: false
         type: boolean
+    authorizationParamInHeader:
+      description: Authorization parameter for request.
+      in: header
+      name: Authorization
+      required: false
+      schema:
+        type: string
     contentParamInHeader:
       description: "Content parameter for request, if content parameter is null, default\
         \ value is application/json."
@@ -1716,16 +1609,6 @@ components:
           schema:
             $ref: '#/components/schemas/ErrorMessage'
       description: Bad Request
-    Unauthorized:
-      content:
-        application/json:
-          example:
-            status: 401
-            message: Unauthorized error message
-            details: Unauthorized error details
-          schema:
-            $ref: '#/components/schemas/ErrorMessage'
-      description: Unauthorized
     Forbidden:
       content:
         application/json:
index a134d0d..e79a188 100644 (file)
@@ -16,6 +16,33 @@ CPS Release Notes
 ..      * * *   NEW DELHI   * * *
 ..      =========================
 
+Version: 3.4.7
+==============
+
+Release Data
+------------
+
++--------------------------------------+--------------------------------------------------------+
+| **CPS Project**                      |                                                        |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Docker images**                    | onap/cps-and-ncmp:3.4.7                                |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Release designation**              | 3.4.7 New Delhi                                        |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+| **Release date**                     | Not yet released                                       |
+|                                      |                                                        |
++--------------------------------------+--------------------------------------------------------+
+
+Bug Fixes
+---------
+3.4.7
+
+Features
+--------
+
 Version: 3.4.6
 ==============
 
@@ -32,17 +59,27 @@ Release Data
 | **Release designation**              | 3.4.6 New Delhi                                        |
 |                                      |                                                        |
 +--------------------------------------+--------------------------------------------------------+
-| **Release date**                     | Not yet released                                       |
+| **Release date**                     | 2024 February 29                                       |
 |                                      |                                                        |
 +--------------------------------------+--------------------------------------------------------+
 
 Bug Fixes
 ---------
 3.4.6
+    - `CPS-2126 <https://jira.onap.org/browse/CPS-2126>`_ Passing HTTP Authorization Bearer Token to DMI Plugins.
 
 
 Features
 --------
+    - `CPS-2133 <https://jira.onap.org/browse/CPS-2133>`_ Revert Uplift of Spring Boot version from 3.2.2 to 3.1.2
+
+Notes
+-----
+This release brings improvements to compatibility with Service Mesh and for that below measures are been taken.
+
+Basic authorization provided using Spring security is been removed from CPS-Core and NCMP and hence authorization is no longer enforced.(basic auth header will be ignored, but is still allowed).
+NCMP will propagate a bearer token to DMI conditionally.
+401 Unauthorized will not be returned. Best effort has been made to ensure backwards compatibility.
 
 Version: 3.4.5
 ==============
index 04280b9..b379e9f 100644 (file)
@@ -23,7 +23,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
index 23504e4..1577524 100644 (file)
@@ -41,12 +41,14 @@ import org.onap.cps.spi.utils.SessionManager
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration
 import org.springframework.boot.autoconfigure.domain.EntityScan
+import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.context.annotation.ComponentScan
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories
 import org.springframework.http.HttpStatus
 import org.springframework.http.MediaType
 import org.springframework.test.web.client.MockRestServiceServer
+import org.springframework.test.web.servlet.MockMvc
 import org.springframework.web.client.RestTemplate
 import org.testcontainers.spock.Testcontainers
 import spock.lang.Shared
@@ -56,9 +58,10 @@ import spock.util.concurrent.PollingConditions
 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
 
-@SpringBootTest(classes = [CpsDataspaceService])
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = [CpsDataspaceService])
 @Testcontainers
 @EnableAutoConfiguration
+@AutoConfigureMockMvc
 @EnableJpaRepositories(basePackageClasses = [DataspaceRepository])
 @ComponentScan(basePackages = ['org.onap.cps'])
 @EntityScan('org.onap.cps.spi.entities')
@@ -67,6 +70,9 @@ abstract class CpsIntegrationSpecBase extends Specification {
     @Shared
     DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance()
 
+    @Autowired
+    MockMvc mvc;
+
     @Autowired
     CpsDataspaceService cpsDataspaceService
 
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpBearerTokenPassthroughSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/NcmpBearerTokenPassthroughSpec.groovy
new file mode 100644 (file)
index 0000000..0dabbf3
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ *  ============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.integration.functional
+
+import java.time.Duration
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.test.web.client.match.MockRestRequestMatchers
+
+import static org.springframework.http.HttpMethod.GET
+import static org.springframework.http.HttpMethod.DELETE
+import static org.springframework.http.HttpMethod.PATCH
+import static org.springframework.http.HttpMethod.POST
+import static org.springframework.http.HttpMethod.PUT
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.method
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
+
+class NcmpBearerTokenPassthroughSpec extends CpsIntegrationSpecBase {
+
+    static final NO_MODULE_SET_TAG = ''
+    static final MODULE_REFERENCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_Response.json')
+    static final MODULE_RESOURCES_RESPONSE = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_ResourcesResponse.json')
+
+    def setup() {
+        registerCmHandle(DMI_URL, 'ch-1', NO_MODULE_SET_TAG, MODULE_REFERENCES_RESPONSE, MODULE_RESOURCES_RESPONSE)
+    }
+
+    def cleanup() {
+        deregisterCmHandle(DMI_URL, 'ch-1')
+    }
+
+    def 'Bearer token is passed from NCMP to DMI in pass-through data operations.'() {
+        given: 'DMI will expect to receive a request with a bearer token'
+            def targetDmiUrl = "$DMI_URL/dmi/v1/ch/ch-1/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=my-resource-id"
+            mockDmiServer.expect(requestTo(targetDmiUrl))
+                    .andExpect(MockRestRequestMatchers.header(HttpHeaders.AUTHORIZATION, 'Bearer some-bearer-token'))
+                    .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON))
+
+        when: 'a pass-through data request is sent to NCMP with a bearer token'
+            mvc.perform(request(httpMethod, '/ncmp/v1/ch/ch-1/data/ds/ncmp-datastore:passthrough-running')
+                    .queryParam('resourceIdentifier', 'my-resource-id')
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .content('{ "some-json": "data" }')
+                    .header(HttpHeaders.AUTHORIZATION, 'Bearer some-bearer-token'))
+                    .andExpect(status().is2xxSuccessful())
+
+        then: 'DMI has received request with bearer token'
+            mockDmiServer.verify()
+
+        where: 'all HTTP operations are applied'
+            httpMethod << [GET, POST, PUT, PATCH, DELETE]
+    }
+
+    def 'Basic auth header is NOT passed from NCMP to DMI in pass-through data operations.'() {
+        given: 'DMI will expect to receive a request with no authorization header'
+            def targetDmiUrl = "$DMI_URL/dmi/v1/ch/ch-1/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=my-resource-id"
+            mockDmiServer.expect(requestTo(targetDmiUrl))
+                    .andExpect(MockRestRequestMatchers.headerDoesNotExist(HttpHeaders.AUTHORIZATION))
+                    .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON))
+
+        when: 'a pass-through data request is sent to NCMP with basic authentication'
+            mvc.perform(request(httpMethod, '/ncmp/v1/ch/ch-1/data/ds/ncmp-datastore:passthrough-running')
+                    .queryParam('resourceIdentifier', 'my-resource-id')
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .content('{ "some-json": "data" }')
+                    .header(HttpHeaders.AUTHORIZATION, 'Basic Y3BzdXNlcjpjcHNyMGNrcyE='))
+                    .andExpect(status().is2xxSuccessful())
+
+        then: 'DMI has received request with no authorization header'
+            mockDmiServer.verify()
+
+        where: 'all HTTP operations are applied'
+            httpMethod << [GET, POST, PUT, PATCH, DELETE]
+    }
+
+    def 'Bearer token is passed from NCMP to DMI in async batch pass-through data operation.'() {
+        given: 'DMI will expect to receive a request with a bearer token'
+            mockDmiServer.expect(method(POST))
+                    .andExpect(MockRestRequestMatchers.header(HttpHeaders.AUTHORIZATION, 'Bearer some-bearer-token'))
+                    .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON))
+
+        when: 'a pass-through async data request is sent to NCMP with a bearer token'
+            def requestBody = """{"operations": [{
+                "operation": "read",
+                "operationId": "operational-1",
+                "datastore": "ncmp-datastore:passthrough-running",
+                "resourceIdentifier": "my-resource-id",
+                "targetIds": ["ch-1"]
+            }]}"""
+        mvc.perform(request(POST, '/ncmp/v1/data')
+                    .queryParam('topic', 'my-topic')
+                    .contentType(MediaType.APPLICATION_JSON)
+                    .content(requestBody)
+                    .header(HttpHeaders.AUTHORIZATION, 'Bearer some-bearer-token'))
+                    .andExpect(status().is2xxSuccessful())
+
+        then: 'DMI will receive the async request with bearer token'
+            mockDmiServer.verify(Duration.ofSeconds(1))
+    }
+
+}
index f77cb02..3d61bdb 100644 (file)
@@ -112,7 +112,7 @@ app:
       topic: ${DMI_DEVICE_HEARTBEAT_TOPIC:dmi-device-heartbeat}
 
 notification:
-  enabled: false
+  enabled: true
   async:
     executor:
       core-pool-size: 2
index 99ddaa8..9e2f8b4 100644 (file)
@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.onap.cps</groupId>
         <artifactId>cps-parent</artifactId>
-        <version>3.4.6-SNAPSHOT</version>
+        <version>3.4.7-SNAPSHOT</version>
         <relativePath>../cps-parent/pom.xml</relativePath>
     </parent>
     <modelVersion>4.0.0</modelVersion>
diff --git a/pom.xml b/pom.xml
index 35acb5e..2a02945 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
 \r
     <groupId>org.onap.cps</groupId>\r
     <artifactId>cps-aggregator</artifactId>\r
-    <version>3.4.6-SNAPSHOT</version>\r
+    <version>3.4.7-SNAPSHOT</version>\r
     <packaging>pom</packaging>\r
 \r
     <name>cps</name>\r
index 24717bc..730f69e 100644 (file)
@@ -1,6 +1,6 @@
 {
     "info": {
-        "_postman_id": "e86df76f-6b33-4648-ba66-ea9d3129c052",
+        "_postman_id": "e864733f-4781-45b6-8ea2-0b841a703dae",
         "name": "CPS-CORE",
         "description": "A collection of the endpoints in CPS-CORE. This is not an exhaustive collection but captures the main functionality.\n\nTo perform this functionality execute the API calls in order to create a dataspace, schema set (file is provided), anchor, and data node. Then GET the nodes to retrieve the information. The APIs in CPS-ADMIN can be used after initial POST requests.\n\nbookstore-model.yang can be found at cps/postman-collections/bookstore-model.yang",
         "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
                 "header": [],
                 "body": {
                     "mode": "raw",
-                    "raw": "{\n    \"bookstore-address\": [\n        {\n            \"bookstore-name\": \"Easons\",\n            \"address\": \"Dublin,Ireland\",\n            \"postal-code\": \"D02HA21\"\n        }\n    ],\n    \"bookstore\": {\n        \"bookstore-name\": \"Easons\",\n        \"premises\": {\n            \"addresses\": [\n                {\n                    \"house-number\": 2,\n                    \"street\": \"Main Street\",\n                    \"town\": \"Maynooth\",\n                    \"county\": \"Kildare\"\n                },\n                {\n                    \"house-number\": 24,\n                    \"street\": \"Grafton Street\",\n                    \"town\": \"Dublin\",\n                    \"county\": \"Dublin\"\n                }\n            ]\n        },\n        \"categories\": [\n            {\n                \"code\": 1,\n                \"name\": \"Children\",\n                \"books\": [\n                    {\n                        \"title\": \"Matilda\",\n                        \"lang\": \"English\",\n                        \"authors\": [\n                            \"Roald Dahl\"\n                        ],\n                        \"editions\": [\n                            1988,\n                            2000\n                        ],\n                        \"price\": 20\n                    },\n                    {\n                        \"title\": \"The Gruffalo\",\n                        \"lang\": \"English\",\n                        \"authors\": [\n                            \"Julia Donaldson\"\n                        ],\n                        \"editions\": [\n                            1999\n                        ],\n                        \"price\": 15\n                    }\n                ]\n            },\n            {\n                \"code\": 2,\n                \"name\": \"Thriller\",\n                \"books\": [\n                    {\n                        \"title\": \"Annihilation\",\n                        \"lang\": \"English\",\n                        \"authors\": [\n                            \"Jeff VanderMeer\"\n                        ],\n                        \"editions\": [\n                            2014\n                        ],\n                        \"price\": 15\n                    }\n                ]\n            },\n            {\n                \"code\": 3,\n                \"name\": \"Comedy\",\n                \"books\": [\n                    {\n                        \"title\": \"Good Omens\",\n                        \"lang\": \"English\",\n                        \"authors\": [\n                            \"Neil Gaiman\",\n                            \"Terry Pratchett\"\n                        ],\n                        \"editions\": [\n                            2006\n                        ],\n                        \"price\": 13\n                    },\n                    {\n                        \"title\": \"The Colour of Magic\",\n                        \"lang\": \"English\",\n                        \"authors\": [\n                            \"Terry Pratchett\"\n                        ],\n                        \"editions\": [\n                            1983\n                        ],\n                        \"price\": 12\n                    },\n                    {\n                        \"title\": \"The Light Fantastic\",\n                        \"lang\": \"English\",\n                        \"authors\": [\n                            \"Terry Pratchett\"\n                        ],\n                        \"editions\": [\n                            1986\n                        ],\n                        \"price\": 14\n                    },\n                    {\n                        \"title\": \"A Book with No Language\",\n                        \"lang\": \"\",\n                        \"authors\": [\n                            \"Joe Bloggs\"\n                        ],\n                        \"editions\": [\n                            2023\n                        ],\n                        \"price\": 20\n                    }\n                ]\n            },\n            {\n                \"code\": 4,\n                \"name\": \"Computing\",\n                \"books\": [\n                    {\n                        \"title\": \"Debian GNU/Linux\",\n                        \"lang\": \"German\",\n                        \"authors\": [\n                            \"Peter H. Ganten\",\n                            \"Wulf Alex\"\n                        ],\n                        \"editions\": [\n                            2007,\n                            2013,\n                            2021\n                        ],\n                        \"price\": 39\n                    },\n                    {\n                        \"title\": \"Logarithm tables\",\n                        \"lang\": \"N/A\",\n                        \"authors\": [\n                            \"Joe Bloggs\"\n                        ],\n                        \"editions\": [\n                            2009\n                        ],\n                        \"price\": 11\n                    }\n                ]\n            },\n            {\n                \"code\": 5,\n                \"name\": \"Discount books\",\n                \"books\": [\n                    {\n                        \"title\": \"Book 1\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 1\n                    },\n                    {\n                        \"title\": \"Book 2\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 2\n                    },\n                    {\n                        \"title\": \"Book 3\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 3\n                    },\n                    {\n                        \"title\": \"Book 4\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 4\n                    },\n                    {\n                        \"title\": \"Book 5\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 5\n                    },\n                    {\n                        \"title\": \"Book 6\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 6\n                    },\n                    {\n                        \"title\": \"Book 7\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 7\n                    },\n                    {\n                        \"title\": \"Book 8\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 8\n                    },\n                    {\n                        \"title\": \"Book 9\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 9\n                    },\n                    {\n                        \"title\": \"Book 10\",\n                        \"lang\": \"blah\",\n                        \"authors\": [],\n                        \"editions\": [],\n                        \"price\": 10\n                    }\n                ]\n            }\n        ]\n    }\n}",
+                    "raw": "{\n  \"bookstore-address\": [\n    {\n      \"bookstore-name\": \"Easons\",\n      \"address\": \"Dublin,Ireland\",\n      \"postal-code\": \"D02HA21\"\n    }\n  ],\n  \"bookstore\": {\n    \"bookstore-name\": \"Easons\",\n    \"premises\": {\n      \"addresses\": [\n        {\n          \"house-number\": 2,\n          \"street\": \"Main Street\",\n          \"town\": \"Maynooth\",\n          \"county\": \"Kildare\"\n        },\n        {\n          \"house-number\": 24,\n          \"street\": \"Grafton Street\",\n          \"town\": \"Dublin\",\n          \"county\": \"Dublin\"\n        }\n      ]\n    },\n    \"categories\": [\n      {\n        \"code\": 1,\n        \"name\": \"Children\",\n        \"books\" : [\n          {\n            \"title\": \"Matilda\",\n            \"lang\": \"English\",\n            \"authors\": [\"Roald Dahl\"],\n            \"editions\": [1988, 2000],\n            \"price\": 20\n          },\n          {\n            \"title\": \"The Gruffalo\",\n            \"lang\": \"English\",\n            \"authors\": [\"Julia Donaldson\"],\n            \"editions\": [1999],\n            \"price\": 15\n          }\n        ]\n      },\n      {\n        \"code\": 2,\n        \"name\": \"Thriller\",\n        \"books\" : [\n          {\n            \"title\": \"Annihilation\",\n            \"lang\": \"English\",\n            \"authors\": [\"Jeff VanderMeer\"],\n            \"editions\": [2014],\n            \"price\": 15\n          }\n        ]\n      },\n      {\n        \"code\": 3,\n        \"name\": \"Comedy\",\n        \"books\" : [\n          {\n            \"title\": \"Good Omens\",\n            \"lang\": \"English\",\n            \"authors\": [\"Neil Gaiman\", \"Terry Pratchett\"],\n            \"editions\": [2006],\n            \"price\": 13\n          },\n          {\n            \"title\": \"The Colour of Magic\",\n            \"lang\": \"English\",\n            \"authors\": [\"Terry Pratchett\"],\n            \"editions\": [1983],\n            \"price\": 12\n          },\n          {\n            \"title\": \"The Light Fantastic\",\n            \"lang\": \"English\",\n            \"authors\": [\"Terry Pratchett\"],\n            \"editions\": [1986],\n            \"price\": 14\n          },\n          {\n            \"title\": \"A Book with No Language\",\n            \"lang\": \"\",\n            \"authors\": [\"Joe Bloggs\"],\n            \"editions\": [2023],\n            \"price\": 20\n          }\n        ]\n      },\n      {\n        \"code\": 4,\n        \"name\": \"Computing\",\n        \"books\" : [\n          {\n            \"title\": \"Debian GNU/Linux\",\n            \"lang\": \"German\",\n            \"authors\": [\"Peter H. Ganten\", \"Wulf Alex\"],\n            \"editions\": [2007, 2013, 2021],\n            \"price\": 39\n          },\n          {\n            \"title\": \"Logarithm tables\",\n            \"lang\": \"N/A\",\n            \"authors\": [\"Joe Bloggs\"],\n            \"editions\": [2009],\n            \"price\": 11\n          }\n        ]\n      },\n      {\n        \"code\": 5,\n        \"name\": \"Discount books\",\n        \"books\" : [\n          {\n            \"title\": \"Book 1\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 1\n          },\n          {\n            \"title\": \"Book 2\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 2\n          },\n          {\n            \"title\": \"Book 3\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 3\n          },\n          {\n            \"title\": \"Book 4\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 4\n          },\n          {\n            \"title\": \"Book 5\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 5\n          },\n          {\n            \"title\": \"Book 6\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 6\n          },\n          {\n            \"title\": \"Book 7\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 7\n          },\n          {\n            \"title\": \"Book 8\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 8\n          },\n          {\n            \"title\": \"Book 9\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 9\n          },\n          {\n            \"title\": \"Book 10\",\n            \"lang\": \"blah\",\n            \"authors\": [],\n            \"editions\": [],\n            \"price\": 10\n          }\n        ]\n      }\n    ]\n  }\n}\n",
                     "options": {
                         "raw": {
                             "language": "json"
             "response": []
         },
         {
-            "name": "Get Node Staff No Descendants",
+            "name": "Get Node Categories No Descendants",
             "request": {
                 "method": "GET",
                 "header": [],
                 "url": {
-                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/staff&descendants=none",
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/categories&descendants=none",
                     "protocol": "http",
                     "host": [
                         "{{CPS_HOST}}"
                     "query": [
                         {
                             "key": "xpath",
-                            "value": "/bookstore/staff"
+                            "value": "/bookstore/categories"
                         },
                         {
                             "key": "descendants",
             "response": []
         },
         {
-            "name": "Get Node Inventory All Descendants",
+            "name": "Get Node Premises All Descendants",
             "request": {
                 "method": "GET",
                 "header": [],
                 "url": {
-                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/inventory&descendants=all",
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/premises&descendants=all",
                     "protocol": "http",
                     "host": [
                         "{{CPS_HOST}}"
                     "query": [
                         {
                             "key": "xpath",
-                            "value": "/bookstore/inventory"
+                            "value": "/bookstore/premises"
                         },
                         {
                             "key": "descendants",
             "response": []
         },
         {
-            "name": "Get Node Inventory Categories Direct Descendants",
+            "name": "Get Node Categories with code 2 Direct Descendants",
             "request": {
                 "method": "GET",
                 "header": [],
                 "url": {
-                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/inventory/categories[@code='2']&descendants=direct",
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/categories[@code='2']&descendants=direct",
                     "protocol": "http",
                     "host": [
                         "{{CPS_HOST}}"
                     "query": [
                         {
                             "key": "xpath",
-                            "value": "/bookstore/inventory/categories[@code='2']"
+                            "value": "/bookstore/categories[@code='2']"
                         },
                         {
                             "key": "descendants",
                 "method": "GET",
                 "header": [],
                 "url": {
-                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/nodes/query?cps-path=/bookstore/inventory/categories[@numberOfBooks=1]&descendants=-1",
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/nodes/query?cps-path=/bookstore/categories[@name=\"Discount books\"]&descendants=-1",
                     "protocol": "http",
                     "host": [
                         "{{CPS_HOST}}"
                     "query": [
                         {
                             "key": "cps-path",
-                            "value": "/bookstore/inventory/categories[@numberOfBooks=1]"
+                            "value": "/bookstore/categories[@name=\"Discount books\"]"
                         },
                         {
                             "key": "descendants",
                 "method": "GET",
                 "header": [],
                 "url": {
-                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/nodes/query?cps-path=//categories[@code=1]/ancestor::inventory&descendants=0",
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/nodes/query?cps-path=//books[@lang=\"German\"]/ancestor::categories&descendants=0",
                     "protocol": "http",
                     "host": [
                         "{{CPS_HOST}}"
                     "query": [
                         {
                             "key": "cps-path",
-                            "value": "//categories[@code=1]/ancestor::inventory"
+                            "value": "//books[@lang=\"German\"]/ancestor::categories"
                         },
                         {
                             "key": "descendants",
                 "header": [],
                 "body": {
                     "mode": "raw",
-                    "raw": "{\r\n    \"staff\": {\r\n        \"manager\": \"Jane Doe\",\r\n        \"members\": [\r\n            {\"name\": \"Some Guy\"},\r\n            {\"name\": \"Another Person\"}\r\n        ]\r\n    }\r\n}",
+                    "raw": "{\r\n    \"bookstore\": {\r\n        \"bookstore-name\": \"Chapters\"\r\n    }\r\n}",
+                    "options": {
+                        "raw": {
+                            "language": "json"
+                        }
+                    }
+                },
+                "url": {
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/nodes?xpath=/",
+                    "protocol": "http",
+                    "host": [
+                        "{{CPS_HOST}}"
+                    ],
+                    "port": "{{CPS_PORT}}",
+                    "path": [
+                        "cps",
+                        "api",
+                        "v2",
+                        "dataspaces",
+                        "my-store",
+                        "anchors",
+                        "bookstore-anchor",
+                        "nodes"
+                    ],
+                    "query": [
+                        {
+                            "key": "xpath",
+                            "value": "/"
+                        }
+                    ]
+                }
+            },
+            "response": []
+        },
+        {
+            "name": "Put Nodes",
+            "request": {
+                "method": "PUT",
+                "header": [],
+                "body": {
+                    "mode": "raw",
+                    "raw": "\r\n    {\r\n        \"premises\": {\r\n            \"addresses\": [\r\n                {\r\n                    \"town\": \"Maynooth\",\r\n                    \"county\": \"Kildare\",\r\n                    \"street\": \"Main Street\",\r\n                    \"house-number\": 2\r\n                },\r\n                {\r\n                    \"town\": \"Dublin\",\r\n                    \"county\": \"Dublin\",\r\n                    \"street\": \"Grafton Street\",\r\n                    \"house-number\": 24\r\n                },\r\n                {\r\n                    \"house-number\": 13,\r\n                    \"street\": \"Church Street\",\r\n                    \"town\": \"Athlone\",\r\n                    \"county\": \"Westmeath\"\r\n                }\r\n            ]\r\n        }\r\n    }\r\n",
                     "options": {
                         "raw": {
                             "language": "json"
             "response": []
         },
         {
-            "name": "Get Node Staff Direct Descendants",
+            "name": "Get Node Premises Direct Descendants",
             "request": {
                 "method": "GET",
                 "header": [],
                 "url": {
-                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/staff&descendants=1",
+                    "raw": "http://{{CPS_HOST}}:{{CPS_PORT}}/cps/api/v2/dataspaces/my-store/anchors/bookstore-anchor/node?xpath=/bookstore/premises&descendants=1",
                     "protocol": "http",
                     "host": [
                         "{{CPS_HOST}}"
                     "query": [
                         {
                             "key": "xpath",
-                            "value": "/bookstore/staff"
+                            "value": "/bookstore/premises"
                         },
                         {
                             "key": "descendants",
diff --git a/releases/3.4.6-container.yaml b/releases/3.4.6-container.yaml
new file mode 100644 (file)
index 0000000..72ba08b
--- /dev/null
@@ -0,0 +1,8 @@
+distribution_type: container
+container_release_tag: 3.4.6
+project: cps
+log_dir: cps-maven-docker-stage-master/938/
+ref: 4a978d3c66da16bc96b54cba807138fc9b0c79fa
+containers:
+  - name: 'cps-and-ncmp'
+    version: '3.4.6-20240229T165311Z'
diff --git a/releases/3.4.6.yaml b/releases/3.4.6.yaml
new file mode 100644 (file)
index 0000000..b3a9a35
--- /dev/null
@@ -0,0 +1,4 @@
+distribution_type: maven
+log_dir: cps-maven-stage-master/946/
+project: cps
+version: 3.4.6
\ No newline at end of file
index ef7c2f0..bbaf5fe 100644 (file)
@@ -25,7 +25,7 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>org.onap.cps</groupId>
     <artifactId>spotbugs</artifactId>
-    <version>3.4.6-SNAPSHOT</version>
+    <version>3.4.7-SNAPSHOT</version>
 
     <properties>
         <nexusproxy>https://nexus.onap.org</nexusproxy>
index dbf29f3..b3ec570 100644 (file)
@@ -22,7 +22,7 @@
 
 major=3
 minor=4
-patch=6
+patch=7
 
 base_version=${major}.${minor}.${patch}