Revise mock config classes to autowire properties 81/3281/2
authorLott, Christopher (cl778h) <cl778h@att.com>
Wed, 15 Apr 2020 14:11:33 +0000 (10:11 -0400)
committerLott, Christopher (cl778h) <cl778h@att.com>
Wed, 15 Apr 2020 14:39:10 +0000 (10:39 -0400)
Test that all default/required entries are in application.yaml by
replicating regular configuration class constructor autowire parameters
in the mock configuration class constructors.
Add belt-and-suspenders exclusion of key.properties, portal.properties
files to pom.xml since those files are needed to test regular startup.
Remove some unneeded imports that snuck in.

Change-Id: I86560aae11c31db6211d90669daeb100a2588bfd
Signed-off-by: Lott, Christopher (cl778h) <cl778h@att.com>
16 files changed:
dashboard/webapp-backend/pom.xml
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/AppStatsManager.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/AdminConfiguration.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/CaasIngressConfiguration.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/config/E2ManagerConfiguration.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/AdminController.java
dashboard/webapp-backend/src/main/java/org/oransc/ric/portal/dashboard/controller/CustomResponseEntityExceptionHandler.java
dashboard/webapp-backend/src/main/resources/application.yaml
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AdminMockConfiguration.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/AppManagerMockConfiguration.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/CaasIngressMockConfiguration.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/E2ManagerMockConfiguration.java
dashboard/webapp-backend/src/test/java/org/oransc/ric/portal/dashboard/config/WebSecurityMockConfiguration.java
dashboard/webapp-backend/src/test/resources/key.properties
dashboard/webapp-backend/src/test/resources/portal.properties
docs/release-notes.rst

index ed1da94..9df3855 100644 (file)
@@ -165,6 +165,17 @@ limitations under the License.
                </dependency>
        </dependencies>
        <build>
+               <!-- Ensure property files used for testing are NEVER packaged -->
+               <resources>
+                       <resource>
+                               <directory>src/main/resources</directory>
+                               <excludes>
+                                       <exclude>key.properties</exclude>
+                                       <exclude>portal.properties</exclude>
+                               </excludes>
+                               <filtering>false</filtering>
+                       </resource>
+               </resources>
                <plugins>
                        <plugin>
                                <groupId>org.springframework.boot</groupId>
index 79c75fe..98b58da 100644 (file)
@@ -25,20 +25,12 @@ import java.lang.invoke.MethodHandles;
 import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.ListIterator;
 
-import javax.servlet.http.HttpServletResponse;
-
-import org.onap.portalsdk.core.onboarding.exception.PortalAPIException;
-import org.onap.portalsdk.core.restful.domain.EcompUser;
-import org.oransc.ric.portal.dashboard.model.StatsDetailsTransport;
 import org.oransc.ric.portal.dashboard.exception.StatsManagerException;
-import org.oransc.ric.portal.dashboard.model.IDashboardResponse;
 import org.oransc.ric.portal.dashboard.model.AppStats;
+import org.oransc.ric.portal.dashboard.model.StatsDetailsTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-import org.springframework.stereotype.Service;
 
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -65,9 +57,11 @@ public class AppStatsManager {
        /**
         * Development/test-only constructor that uses default file path.
         * 
-        * @param clear If true, start empty and remove any existing file.
+        * @param clear
+        *                  If true, start empty and remove any existing file.
         * 
-        * @throws IOException On file error
+        * @throws IOException
+        *                         On file error
         */
        public AppStatsManager(boolean clear) throws IOException {
                this(STATS_FILE_PATH);
@@ -83,8 +77,10 @@ public class AppStatsManager {
        /**
         * Constructor that accepts a file path
         * 
-        * @param statsFilePath File path
-        * @throws IOException If file cannot be read
+        * @param statsFilePath
+        *                          File path
+        * @throws IOException
+        *                         If file cannot be read
         */
        public AppStatsManager(final String statsFilePath) throws IOException {
                logger.debug("ctor: statsfile {}", statsFilePath);
@@ -96,8 +92,8 @@ public class AppStatsManager {
                        final ObjectMapper mapper = new ObjectMapper();
                        stats = mapper.readValue(statsFile, new TypeReference<List<AppStats>>() {
                        });
-                       for (AppStats st: stats) {
-                               if (st.getStatsDetails().getAppId()>appMaxId) 
+                       for (AppStats st : stats) {
+                               if (st.getStatsDetails().getAppId() > appMaxId)
                                        appMaxId = st.getStatsDetails().getAppId();
                        }
                } else {
@@ -117,7 +113,8 @@ public class AppStatsManager {
        /**
         * Gets the current app metric stats by instance key.
         * 
-        * @param instanceKey Desired instance key
+        * @param instanceKey
+        *                        Desired instance key
         * @return List of App stat objects by instance key, possibly empty
         */
        public List<AppStats> getStatsByInstance(String instanceKey) {
@@ -134,8 +131,10 @@ public class AppStatsManager {
        /**
         * Gets the stats with the specified app Id and instance key
         * 
-        * @param appId       Desired app Id
-        * @param instanceKey Desired instance key
+        * @param appId
+        *                        Desired app Id
+        * @param instanceKey
+        *                        Desired instance key
         * @return Stats object; null if Id is not known
         */
        public AppStats getStatsById(String instanceKey, int appId) {
@@ -157,8 +156,8 @@ public class AppStatsManager {
        }
 
        /*
-        * Allow at most one thread to create a stats at one time.
-        * Before creating new stat, checks for composite key (appname,url) uniqueness for an instance key
+        * Allow at most one thread to create a stats at one time. Before creating new
+        * stat, checks for composite key (appname,url) uniqueness for an instance key
         */
        public synchronized AppStats createStats(String instanceKey, StatsDetailsTransport statsSetupRequest)
                        throws StatsManagerException, IOException {
@@ -168,15 +167,16 @@ public class AppStatsManager {
                        if (st.getInstanceKey().equals(instanceKey)
                                        && st.getStatsDetails().getAppName().equals(statsSetupRequest.getAppName())
                                        && st.getStatsDetails().getMetricUrl().equals(statsSetupRequest.getMetricUrl())) {
-                               String msg = "App exists with name " + statsSetupRequest.getAppName() + " and url "+statsSetupRequest.getMetricUrl()+ " on instance key " + instanceKey;
+                               String msg = "App exists with name " + statsSetupRequest.getAppName() + " and url "
+                                               + statsSetupRequest.getMetricUrl() + " on instance key " + instanceKey;
                                logger.warn(msg);
                                throw new StatsManagerException(msg);
                        }
                }
 
                AppStats newAppStat = null;
-               //Assigns appId to be 1 more than the largest value stored in memory
-               appMaxId = appMaxId+1;
+               // Assigns appId to be 1 more than the largest value stored in memory
+               appMaxId = appMaxId + 1;
                newAppStat = new AppStats(instanceKey,
                                new StatsDetailsTransport(appMaxId, statsSetupRequest.getAppName(), statsSetupRequest.getMetricUrl()));
                stats.add(newAppStat);
index c728e7c..41dd927 100644 (file)
@@ -52,7 +52,6 @@ public class AdminConfiguration {
                logger.debug("ctor statsfile '{}'", statsfile);
                this.userfile = userfile;
                this.statsfile = statsfile;
-
        }
 
        @Bean
index 648a847..4d51ef7 100644 (file)
@@ -47,8 +47,7 @@ public class CaasIngressConfiguration {
        private final RicRegionList instanceConfig;
 
        @Autowired
-       public CaasIngressConfiguration( //
-                       @Value("${caasingress.plt.url.suffix}") final String pltUrlSuffix, //
+       public CaasIngressConfiguration(@Value("${caasingress.plt.url.suffix}") final String pltUrlSuffix, //
                        @Value("${caasingress.insecure}") final Boolean insecureFlag, //
                        final RicRegionList instanceConfig) throws KeyManagementException, NoSuchAlgorithmException {
                logger.debug("ctor: suffix {} insecure flag {}", pltUrlSuffix, insecureFlag);
index ef9ab45..e3449a6 100644 (file)
@@ -47,7 +47,7 @@ public class E2ManagerConfiguration {
        @Autowired
        public E2ManagerConfiguration(@Value("${e2mgr.url.suffix}") final String urlSuffix,
                        final RicRegionList instanceConfig) {
-               logger.info("ctor: URL suffix {}", urlSuffix);
+               logger.debug("ctor: URL suffix {}", urlSuffix);
                this.urlSuffix = urlSuffix;
                this.instanceConfig = instanceConfig;
        }
index 62e9886..1a1a75d 100644 (file)
@@ -21,27 +21,25 @@ package org.oransc.ric.portal.dashboard.controller;
 
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
 import java.util.List;
 
 import org.onap.portalsdk.core.restful.domain.EcompUser;
+import org.oransc.ric.portal.dashboard.AppStatsManager;
 import org.oransc.ric.portal.dashboard.DashboardApplication;
 import org.oransc.ric.portal.dashboard.DashboardConstants;
 import org.oransc.ric.portal.dashboard.DashboardUserManager;
-import org.oransc.ric.portal.dashboard.AppStatsManager;
 import org.oransc.ric.portal.dashboard.exception.StatsManagerException;
+import org.oransc.ric.portal.dashboard.model.AppStats;
 import org.oransc.ric.portal.dashboard.model.IDashboardResponse;
-import org.oransc.ric.portal.dashboard.model.StatsDetailsTransport;
 import org.oransc.ric.portal.dashboard.model.RicRegion;
 import org.oransc.ric.portal.dashboard.model.RicRegionList;
 import org.oransc.ric.portal.dashboard.model.RicRegionTransport;
-import org.oransc.ric.portal.dashboard.model.AppStats;
+import org.oransc.ric.portal.dashboard.model.StatsDetailsTransport;
 import org.oransc.ric.portal.dashboard.model.SuccessTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.annotation.Secured;
@@ -52,7 +50,6 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import io.swagger.annotations.ApiOperation;
index 2f08806..c34aa2f 100644 (file)
@@ -107,7 +107,7 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio
                                ex.toString());
                return ResponseEntity.badRequest().body(getShortExceptionMessage(ex));
        }
-       
+
        /**
         * Logs a warning if a StatsManagerException is thrown.
         * 
@@ -119,8 +119,7 @@ public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptio
         */
        @ExceptionHandler({ StatsManagerException.class })
        public final ResponseEntity<String> handleStatsManagerException(Exception ex, WebRequest request) {
-               log.warn("handleStatsManagerException: request {}, exception {}", request.getDescription(false),
-                               ex.toString());
+               log.warn("handleStatsManagerException: request {}, exception {}", request.getDescription(false), ex.toString());
                return ResponseEntity.badRequest().body(getShortExceptionMessage(ex));
        }
 
index 9a327eb..5b936e3 100644 (file)
 server:
     port: 8080
 
-# path to file that stores user details;
+# paths to files that store details;
 # use a persistent volume in a K8S deployment
 userfile: users.json
+statsfile: stats.json
 
 # Dashboard properties related to Portal
 portalapi:
index 94dcc44..ba5b70f 100644 (file)
 package org.oransc.ric.portal.dashboard.config;
 
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.lang.invoke.MethodHandles;
-import java.util.Collection;
 import java.util.HashSet;
-import java.util.Locale;
 import java.util.Set;
 
 import org.onap.portalsdk.core.onboarding.exception.PortalAPIException;
 import org.onap.portalsdk.core.restful.domain.EcompRole;
 import org.onap.portalsdk.core.restful.domain.EcompUser;
-import org.oransc.ric.portal.dashboard.DashboardUserManager;
 import org.oransc.ric.portal.dashboard.AppStatsManager;
+import org.oransc.ric.portal.dashboard.DashboardUserManager;
 import org.oransc.ric.portal.dashboard.exception.StatsManagerException;
-import org.oransc.ric.portal.dashboard.model.AppStats;
 import org.oransc.ric.portal.dashboard.model.StatsDetailsTransport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 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.context.annotation.Profile;
 
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-
 /**
  * Creates user manager and stats manager with mock data.
  */
@@ -55,8 +48,12 @@ public class AdminMockConfiguration {
 
        private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
+       // Autowire all the properties required by the real class
+       // (even tho not used here) as a test of the properties.
        @Autowired
-       public AdminMockConfiguration() {
+       public AdminMockConfiguration(@Value("${userfile}") final String userfile,
+                       @Value("${statsfile}") final String statsfile) {
+               logger.info("ctor userfile {} statsfile {}", userfile, statsfile);
        }
 
        @Bean
index 341df53..27e59ad 100644 (file)
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.when;
 
 import java.lang.invoke.MethodHandles;
 
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
 import org.oransc.ricplt.appmgr.client.api.HealthApi;
 import org.oransc.ricplt.appmgr.client.api.XappApi;
 import org.oransc.ricplt.appmgr.client.invoker.ApiClient;
@@ -65,9 +66,13 @@ public class AppManagerMockConfiguration {
        // Simulate remote method delay for UI testing
        private int delayMs;
 
+       // Autowire all the properties required by the real class
+       // (even tho not used here) as a test of the properties.
        @Autowired
-       public AppManagerMockConfiguration(@Value("${mock.config.delay:0}") int delayMs) {
-               logger.debug("ctor: configured with delay {}", delayMs);
+       public AppManagerMockConfiguration(@Value("${appmgr.url.suffix}") final String urlSuffix, //
+                       final RicRegionList instanceConfig, //
+                       @Value("${mock.config.delay:0}") int delayMs) {
+               logger.info("ctor: configured with suffix {}, instances {}, delay {}", urlSuffix, instanceConfig, delayMs);
                this.delayMs = delayMs;
        }
 
index b10dcc8..c8bf663 100644 (file)
@@ -29,6 +29,7 @@ import java.lang.invoke.MethodHandles;
 
 import org.oransc.ric.portal.dashboard.TestUtils;
 import org.oransc.ric.portal.dashboard.k8sapi.SimpleKubernetesClient;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,9 +51,15 @@ public class CaasIngressMockConfiguration {
        // Simulate remote method delay for UI testing
        private int delayMs;
 
+       // Autowire all the properties required by the real class
+       // (even tho not used here) as a test of the properties.
        @Autowired
-       public CaasIngressMockConfiguration(@Value("${mock.config.delay:0}") int delayMs) {
-               logger.debug("ctor: configured with delay {}", delayMs);
+       public CaasIngressMockConfiguration(@Value("${caasingress.plt.url.suffix}") final String pltUrlSuffix, //
+                       @Value("${caasingress.insecure}") final Boolean insecureFlag, //
+                       final RicRegionList instanceConfig, //
+                       @Value("${mock.config.delay:0}") int delayMs) {
+               logger.info("ctor: configured with suffix {}, insecure {}, instance {}, delay {}", pltUrlSuffix, insecureFlag,
+                               instanceConfig, delayMs);
                this.delayMs = delayMs;
        }
 
index 192f2b0..16e2c75 100644 (file)
@@ -30,6 +30,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
 import org.oransc.ricplt.e2mgr.client.api.HealthCheckApi;
 import org.oransc.ricplt.e2mgr.client.api.NodebApi;
 import org.oransc.ricplt.e2mgr.client.invoker.ApiClient;
@@ -61,9 +62,13 @@ public class E2ManagerMockConfiguration {
        // Simulate remote method delay for UI testing
        private int delayMs;
 
+       // Autowire all the properties required by the real class
+       // (even tho not used here) as a test of the properties.
        @Autowired
-       public E2ManagerMockConfiguration(@Value("${mock.config.delay:0}") int delayMs) {
-               logger.debug("ctor: configured with delay {}", delayMs);
+       public E2ManagerMockConfiguration(@Value("${e2mgr.url.suffix}") final String urlSuffix, //
+                       final RicRegionList instanceConfig, //
+                       @Value("${mock.config.delay:0}") int delayMs) {
+               logger.info("ctor: configured with suffix {}, instances {}, delay {}", urlSuffix, instanceConfig, delayMs);
                this.delayMs = delayMs;
        }
 
@@ -104,11 +109,11 @@ public class E2ManagerMockConfiguration {
                // "globalNbId":null,"gnb":null,"ip":"10.2.0.6","nodeType":null,"port":36444,
                // "ranName":"AAAA123456","setupFailure":null}}]
                nodebIdList.add(new NodebIdentity().inventoryName(RAN_NAME_1).globalNbId(globalNbId));
-               nodebResponseMap.put(RAN_NAME_1,
-                               new GetNodebResponse().connectionStatus("CONNECTING").ip("127.0.0.1").port(456).ranName(RAN_NAME_2).nodeType("ENDC").port(100));
+               nodebResponseMap.put(RAN_NAME_1, new GetNodebResponse().connectionStatus("CONNECTING").ip("127.0.0.1").port(456)
+                               .ranName(RAN_NAME_2).nodeType("ENDC").port(100));
                nodebIdList.add(new NodebIdentity().inventoryName(RAN_NAME_2).globalNbId(globalNbId));
-               nodebResponseMap.put(RAN_NAME_2,
-                               new GetNodebResponse().connectionStatus("CONNECTED").ip("127.0.0.2").port(456).ranName(RAN_NAME_2).nodeType("X2").port(200));
+               nodebResponseMap.put(RAN_NAME_2, new GetNodebResponse().connectionStatus("CONNECTED").ip("127.0.0.2").port(456)
+                               .ranName(RAN_NAME_2).nodeType("X2").port(200));
 
                ApiClient apiClient = apiClient();
                NodebApi mockApi = mock(NodebApi.class);
index 257b4a4..f348ecb 100644 (file)
@@ -52,12 +52,18 @@ public class WebSecurityMockConfiguration extends WebSecurityConfigurerAdapter {
 
        // Although constructor arguments are recommended over field injection,
        // this results in fewer lines of code.
+       @Value("${portalapi.security}")
+       private Boolean portalapiSecurity;
+       @Value("${portalapi.appname}")
+       private String appName;
+       @Value("${portalapi.username}")
+       private String userName;
+       @Value("${portalapi.password}")
+       private String password;
        @Value("${portalapi.decryptor}")
        private String decryptor;
        @Value("${portalapi.usercookie}")
        private String userCookie;
-       @Value("${userfile}")
-       private String userFilePath;
 
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
index 85a5689..85bafb1 100644 (file)
@@ -17,6 +17,7 @@
 # ========================LICENSE_END===================================
 
 # Test properties for the EPSDK-FW library.
-# This file must be present on the Java classpath.
+# This file must be present on the Java classpath to test.
+# This file must not be packaged into the jar!
 
 cipher.enc.key = bogus
index 326539e..cff2111 100644 (file)
@@ -17,7 +17,8 @@
 # ========================LICENSE_END===================================
 
 # Test properties for the EPSDK-FW library.
-# This file must be present on the Java classpath.
+# This file must be present on the Java classpath to test.
+# This file must not be packaged into the jar!
 
 portal.api.impl.class = org.oransc.ric.portal.dashboard.portalapi.PortalRestCentralServiceImpl
 role_access_centralized = remote
index 32e709e..2252822 100644 (file)
@@ -5,7 +5,7 @@
 RIC Dashboard Release Notes
 ===========================
 
-Version 2.0.1, 8 Apr 2020
+Version 2.0.1, 15 Apr 2020
 --------------------------
 * update and relocate the theme selector button
 * Revise controllers to use ResponseEntity
@@ -15,6 +15,7 @@ Version 2.0.1, 8 Apr 2020
 * Upgrade to Spring-Boot 2.2.4.RELEASE
 * Set the first instance as the default one
 * Add methods to create, update and delete xApp stat metric URLs
+* Rearrange property files to support testing default context
 
 Version 2.0.0, 5 Feb 2020
 --------------------------