/application-tlab2.properties
/application.properties
/dashboard-users.json
+/dashboard-stats.json
* @return List of App stat objects by instance key, possibly empty
*/
public List<AppStats> getStatsByInstance(String instanceKey) {
- List<AppStats> statsByInstance = new ArrayList<AppStats>();
+ List<AppStats> statsByInstance = new ArrayList<>();
for (AppStats st : this.stats) {
if (st.getInstanceKey().equals(instanceKey)) {
logger.debug("getStatsByInstance: match on instance key {}", instanceKey);
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;
+ // Log the existing object to avoid using tainted (user-supplied) data
+ String msg = "App exists with name " + st.getStatsDetails().getAppName() + " and url "
+ + st.getStatsDetails().getMetricUrl() + " on instance key " + st.getInstanceKey();
logger.warn(msg);
throw new StatsManagerException(msg);
}
public synchronized void updateStats(String instanceKey, StatsDetailsTransport statsSetupRequest)
throws StatsManagerException, IOException {
logger.debug("updateStats: appId {}, instanceKey {}", statsSetupRequest.getAppId(), instanceKey);
- boolean editStatsObjectFound = false;
+ boolean statsObjectFound = false;
for (AppStats st : stats) {
if (st.getInstanceKey().equals(instanceKey)
AppStats newAppStat = new AppStats(instanceKey, statsSetupRequest);
stats.remove(st);
stats.add(newAppStat);
- editStatsObjectFound = true;
+ statsObjectFound = true;
saveStats();
break;
}
}
- if (!editStatsObjectFound) {
+ if (!statsObjectFound) {
String msg = "Stats to be updated does not exist ";
logger.warn(msg);
throw new StatsManagerException(msg);
public synchronized AppStats deleteStats(String instanceKey, int appId) throws StatsManagerException, IOException {
logger.debug("deleteStats: appId {}, instanceKey {}", appId, instanceKey);
- boolean deleteStatsObjectFound = false;
+ boolean statsObjectFound = false;
AppStats stat = null;
for (AppStats st : stats) {
if (st.getInstanceKey().equals(instanceKey) && st.getStatsDetails().getAppId() == appId) {
stat = st;
stats.remove(stat);
- deleteStatsObjectFound = true;
+ statsObjectFound = true;
try {
saveStats();
break;
}
}
- if (!deleteStatsObjectFound) {
+ if (!statsObjectFound) {
String msg = "deleteStats: no match on app id {} of instance key {}";
+ // Replace log pattern-breaking characters
+ instanceKey = instanceKey.replaceAll("[\n|\r|\t]", "_");
logger.warn(msg, appId, instanceKey);
throw new StatsManagerException(msg);
}
import org.onap.portalsdk.core.restful.domain.EcompUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Profile;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
*
* Migrate to a database someday?
*/
+@Profile("!test")
public class DashboardUserManager {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
}
/**
- * Constructur that accepts a file path
+ * Constructor that accepts a file path
*
* @param userFilePath
* File path
@Value("${portalapi.appname}")
private String appName;
@Value("${portalapi.username}")
- private String userName;
+ private String portalApiUsername;
@Value("${portalapi.password}")
- private String password;
+ private String portalApiPassword;
@Value("${portalapi.decryptor}")
private String decryptor;
@Value("${portalapi.usercookie}")
public PortalAuthManager portalAuthManagerBean() throws ClassNotFoundException, IllegalAccessException,
InstantiationException, InvocationTargetException, NoSuchMethodException {
logger.debug("portalAuthManagerBean");
- return new PortalAuthManager(appName, userName, password, decryptor, userCookie);
+ return new PortalAuthManager(appName, portalApiUsername, portalApiPassword, decryptor, userCookie);
}
/*
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.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
public static final String XAPPMETRICS_METHOD = "metrics";
public static final String STATAPPMETRIC_METHOD = "appmetric";
- @Value("${metrics.url.ml}")
- private String mlAppMetricsUrl;
-
@Autowired
private DashboardUserManager dashboardUserManager;
@PutMapping(DashboardConstants.RIC_INSTANCE_KEY + "/{" + DashboardConstants.RIC_INSTANCE_KEY + "}/"
+ STATAPPMETRIC_METHOD)
@Secured({ DashboardConstants.ROLE_ADMIN })
- public ResponseEntity<String> updateStats(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey,
+ public void updateStats(@PathVariable(DashboardConstants.RIC_INSTANCE_KEY) String instanceKey,
@RequestBody StatsDetailsTransport statsSetupRequest) throws StatsManagerException, IOException {
logger.debug("updateStats for instance {} request {}", instanceKey, statsSetupRequest);
appStatsManager.updateStats(instanceKey, statsSetupRequest);
- return ResponseEntity.ok(null);
}
@ApiOperation(value = "Deletes xApp metric status.")
}
/**
- * Logs a warning if an invalid RIC instance key is used.
+ * Logs the error and generates a response when a REST controller method takes
+ * an UnknownInstanceException, an invalid RIC instance key was used.
*
* @param ex
* The exception
}
/**
- * Logs a warning if a StatsManagerException is thrown.
+ * Logs the error and generates a response when a REST controller method takes
+ * an StatsManagerException.
*
* @param ex
* The exception
package org.oransc.ric.portal.dashboard.model;
+import java.util.Objects;
+
/**
* POJO for RIC instance details.
*/
super();
}
+ @Override
public RicInstance key(String key) {
super.key(key);
return this;
}
+ @Override
public RicInstance name(String name) {
super.name(name);
return this;
return result;
}
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RicInstance other = (RicInstance) obj;
+ return Objects.equals(appUrlPrefix, other.appUrlPrefix) && Objects.equals(pltUrlPrefix, other.pltUrlPrefix);
+ }
+
}
# paths to files that store details;
# use a persistent volume in a K8S deployment
-userfile: users.json
-statsfile: stats.json
+userfile: dashboard-users.json
+statsfile: dashboard-stats.json
# Dashboard properties related to Portal
portalapi:
# Instance-specific URL prefixes must be supplied at deployment time
-# A1 Mediator
-a1med:
- url:
- # uses pltUrlPrefix
- suffix: /a1mediator
-
# App Manager
appmgr:
url:
@Value("${portalapi.appname}")
private String appName;
@Value("${portalapi.username}")
- private String userName;
+ private String portalApiUsername;
@Value("${portalapi.password}")
- private String password;
+ private String portalApiPassword;
@Value("${portalapi.decryptor}")
private String decryptor;
@Value("${portalapi.usercookie}")
@Bean
public PortalAuthManager portalAuthManagerBean() throws Exception {
logger.debug("portalAuthManagerBean");
- return new PortalAuthManager(IPortalRestCentralService.CREDENTIALS_APP,
- IPortalRestCentralService.CREDENTIALS_USER, IPortalRestCentralService.CREDENTIALS_PASS, decryptor,
- userCookie);
+ return new PortalAuthManager(IPortalRestCentralService.CREDENTIALS_APP, portalApiUsername, portalApiPassword,
+ decryptor, userCookie);
}
}
import java.lang.invoke.MethodHandles;
import java.net.URI;
import java.util.List;
+
+import org.junit.Assert;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
-import org.junit.jupiter.api.MethodOrderer;
import org.onap.portalsdk.core.restful.domain.EcompUser;
import org.oransc.ric.portal.dashboard.DashboardConstants;
import org.oransc.ric.portal.dashboard.config.RICInstanceMockConfiguration;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
+import org.springframework.web.client.RestClientException;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class AdminControllerTest extends AbstractControllerTest {
statsDetails.setMetricUrl("https://www.example2-next.com");
AppStats stNext = testRestTemplateAdminRole().postForObject(uri, statsDetails, AppStats.class);
Assertions.assertTrue(st.getStatsDetails().getAppId() < stNext.getStatsDetails().getAppId());
+ try {
+ testRestTemplateAdminRole().postForObject(uri, statsDetails, AppStats.class);
+ Assert.assertTrue(false);
+ } catch (RestClientException ex) {
+ logger.info("Caught exception on create as expected: {}", ex.toString());
+ }
}
@Order(3)
ResponseEntity<String> stringResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity,
String.class);
Assertions.assertTrue(stringResponse.getStatusCode().is2xxSuccessful());
+
+ StatsDetailsTransport bogusDetails = new StatsDetailsTransport();
+ bogusDetails.setAppId(-1);
+ bogusDetails.setAppName("bogus");
+ HttpEntity<StatsDetailsTransport> bogusEntity = new HttpEntity<>(bogusDetails);
+ ResponseEntity<String> voidResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, bogusEntity,
+ String.class);
+ Assertions.assertTrue(voidResponse.getStatusCode().is4xxClientError());
}
@Order(4)
ResponseEntity<String> stringResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.DELETE, null,
String.class);
Assertions.assertTrue(stringResponse.getStatusCode().is2xxSuccessful());
+
+ URI uri99 = buildUri(null, AdminController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, AdminController.STATAPPMETRIC_METHOD,
+ DashboardConstants.APP_ID, "999999");
+ ResponseEntity<String> voidResponse = testRestTemplateAdminRole().exchange(uri99, HttpMethod.DELETE, null,
+ String.class);
+ Assertions.assertTrue(voidResponse.getStatusCode().is4xxClientError());
}
@Test
import java.lang.invoke.MethodHandles;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/**
* Tests whether the default (not mock) configuration classes run to completion.
*/
@ExtendWith(SpringExtension.class)
-@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-@ActiveProfiles("default")
+// This way of setting the active profile should not be necessary. See:
+// https://github.com/spring-projects/spring-boot/issues/19788
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.profiles.active:default")
public class DefaultContextTest {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- // If this test is annotated and run by maven, two cases in
- // PortalRestCentralServiceTest fail. I traced it down to a second
- // occurrence of the Dashboard user manager bean, which I can only speculate
- // gets instantiated when the active profile is not "test". Because I cannot
- // explain nor fix the behavior, this remains commented out.
- // @Test
+ /**
+ * I expect the server to loaded then be torn down again. And when a single test
+ * is run, that is the behavior. But if all the tests are run, this test is
+ * reached while working thru the package and it appears that the "default"
+ * profile is added to the active "test" profile. Junit continues on thru the
+ * remaining tests, the non-mock configuration bean is used to authenticate
+ * Portal API requests, but because it has no username and password (the entries
+ * in application.yaml are blank), access is denied and these tests fail:
+ * <UL>
+ * <LI>{@link PortalRestCentralServiceTest#createUserTest()}
+ * <LI>{@link PortalRestCentralServiceTest#updateUserTest()}
+ * </UL>
+ * Maybe:
+ *
+ * I worked around the problem by using the application.yaml credentials.
+ * I also annotated this class above trying to limit the active profile,
+ * but I'm not confident it is working nor that it's needed.
+ */
+ @Test
public void contextLoads() {
// Silence Sonar warning about missing assertion.
Assertions.assertTrue(logger.isWarnEnabled());
- logger.info("Context loads on default profile");
+ logger.info("DefaultContextTest#contextLoads on default profile");
}
}
import java.net.URI;
import java.util.List;
-import org.junit.After;
import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
import org.oransc.ric.portal.dashboard.DashboardConstants;
import org.oransc.ric.portal.dashboard.config.E2ManagerMockConfiguration;
import org.oransc.ric.portal.dashboard.config.RICInstanceMockConfiguration;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class E2ManagerControllerTest extends AbstractControllerTest {
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private ResponseEntity<Void> reset() {
- URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
- RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.NODEB_PREFIX, "ignored",
- E2ManagerController.RESET_METHOD);
- logger.info("Invoking {}", uri);
- ResetRequest reset = new ResetRequest();
- HttpEntity<ResetRequest> entity = new HttpEntity<>(reset);
- return testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity, Void.class);
- }
-
- @Test
- public void resetTest() {
- ResponseEntity<Void> voidResponse = reset();
- logger.debug("resetTest: response {}", voidResponse);
- Assertions.assertTrue(voidResponse.getStatusCode().is2xxSuccessful());
- }
-
@Test
+ @Order(1)
public void versionTest() {
URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.VERSION_METHOD);
logger.info("Invoking {}", uri);
}
@Test
+ @Order(2)
public void healthTest() {
URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.HEALTH_METHOD);
}
@Test
+ @Order(3)
public void ranDetailsTest() {
URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.RAN_METHOD);
}
@Test
+ @Order(4)
public void nodebListTest() {
URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.NODEB_LIST_METHOD);
}
@Test
+ @Order(5)
public void nodebStatusTest() {
URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.NODEB_PREFIX,
Assertions.assertNotNull(response.getRanName());
}
+ // This empties the list of RAN elements
+ @Test
+ @Order(6)
+ public void resetTest() {
+ URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
+ RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.NODEB_PREFIX, "ignored",
+ E2ManagerController.RESET_METHOD);
+ logger.info("Invoking {}", uri);
+ ResetRequest reset = new ResetRequest();
+ HttpEntity<ResetRequest> entity = new HttpEntity<>(reset);
+ ResponseEntity<Void> voidResponse = testRestTemplateAdminRole().exchange(uri, HttpMethod.PUT, entity, Void.class);
+ logger.debug("resetTest: response {}", voidResponse);
+ Assertions.assertTrue(voidResponse.getStatusCode().is2xxSuccessful());
+ }
+
// Aka big--button test, run this last
- @After
+ @Test
+ @Order(7)
public void nodebShutdownPutTest() {
URI uri = buildUri(null, E2ManagerController.CONTROLLER_PATH, DashboardConstants.RIC_INSTANCE_KEY,
RICInstanceMockConfiguration.INSTANCE_KEY_1, E2ManagerController.NODEB_SHUTDOWN_METHOD);
import org.oransc.ric.portal.dashboard.DashboardConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ // Get values from configuration, probably blank
+ @Value("${portalapi.username}")
+ private String portalApiUsername;
+ @Value("${portalapi.password}")
+ private String portalApiPassword;
+
@Test
public void getAnalyticsTest() {
// paths are hardcoded here exactly like the EPSDK-FW library :(
private HttpEntity<Object> getEntityWithAuthHeaders(Object body) {
HttpHeaders headers = new HttpHeaders();
- headers.set(IPortalRestCentralService.CREDENTIALS_USER, IPortalRestCentralService.CREDENTIALS_USER);
- headers.set(IPortalRestCentralService.CREDENTIALS_PASS, IPortalRestCentralService.CREDENTIALS_PASS);
+ headers.set(IPortalRestCentralService.CREDENTIALS_USER, portalApiUsername);
+ headers.set(IPortalRestCentralService.CREDENTIALS_PASS, portalApiPassword);
HttpEntity<Object> entity = new HttpEntity<>(body, headers);
return entity;
}
return user;
}
+ /** See comments in {@link DefaultContextTest} */
@Test
public void createUserTest() {
- final String loginId = "login1";
+ final String loginId = "login-" + Long.toString(System.currentTimeMillis());
URI create = buildUri(null, PortalApiConstants.API_PREFIX, "user");
logger.info("createUserTest invoking {}", create);
HttpEntity<Object> requestEntity = getEntityWithAuthHeaders(createEcompUser(loginId));
Assertions.assertTrue(response.getStatusCode().is2xxSuccessful());
}
+ /** See comments in {@link DefaultContextTest} */
@Test
public void updateUserTest() {
- final String loginId = "login2";
+ final String loginId = "login-" + Long.toString(System.currentTimeMillis());
URI create = buildUri(null, PortalApiConstants.API_PREFIX, "user");
EcompUser user = createEcompUser(loginId);
logger.info("updateUserTest invoking {}", create);
HttpEntity<Object> requestEntity = getEntityWithAuthHeaders(user);
ResponseEntity<String> response = restTemplate.exchange(create, HttpMethod.POST, requestEntity, String.class);
- logger.info("updateUserTest response {}", response);
+ logger.info("updateUserTest create response {}", response);
Assertions.assertTrue(response.getStatusCode().is2xxSuccessful());
URI update = buildUri(null, PortalApiConstants.API_PREFIX, "user", loginId);
user.setEmail("user@company.org");
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+ private void checkAppStats(AppStats m) {
+ Assert.assertEquals(s1, m.getInstanceKey());
+ Assert.assertTrue(i1 == m.getStatsDetails().getAppId());
+ Assert.assertEquals(s2, m.getStatsDetails().getAppName());
+ Assert.assertEquals(s3, m.getStatsDetails().getMetricUrl());
+ }
+
+ @Test
+ public void testAppStats() {
+ StatsDetailsTransport n = new StatsDetailsTransport();
+ n.setAppId(i1);
+ n.setAppName(s2);
+ n.setMetricUrl(s3);
+ AppStats m = new AppStats();
+ m = new AppStats(s1, n);
+ m.setInstanceKey(s1);
+ m.setStatsDetails(n);
+ checkAppStats(m);
+ logger.info(m.toString());
+ }
+
private void checkAppTransport(AppTransport m) {
Assert.assertEquals(s1, m.getName());
Assert.assertEquals(s2, m.getVersion());
logger.info(m.toString());
}
+ private void checkRicRegionTransport(RicRegionTransport m) {
+ Assert.assertEquals(s1, m.getName());
+ Assert.assertFalse(m.getInstances().isEmpty());
+ }
+
+ @Test
+ public void testRicRegionTransport() {
+ RicRegionTransport m = new RicRegionTransport().name(s1);
+ m.instances(new ArrayList<RicInstanceKeyName>());
+ m.getInstances().add(new RicInstanceKeyName(s1, s2));
+ checkRicRegionTransport(m);
+ Assert.assertTrue(m.equals(m));
+ Assert.assertFalse(m.equals(null));
+ Assert.assertFalse(m.equals(new RicRegionTransport()));
+ Assert.assertNotEquals(1, m.hashCode());
+ logger.info(m.toString());
+ }
+
+ private void checkStatsDetailsTransport(StatsDetailsTransport m) {
+ Assert.assertTrue(i1 == m.getAppId());
+ Assert.assertEquals(s1, m.getAppName());
+ Assert.assertEquals(s2, m.getMetricUrl());
+ }
+
+ @Test
+ public void testStatDetailsTransport() {
+ StatsDetailsTransport m = new StatsDetailsTransport();
+ m.setAppId(i1);
+ m.setAppName(s1);
+ m.setMetricUrl(s2);
+ checkStatsDetailsTransport(m);
+ Assert.assertTrue(m.equals(m));
+ Assert.assertFalse(m.equals(null));
+ Assert.assertFalse(m.equals(new StatsDetailsTransport()));
+ Assert.assertNotEquals(1, m.hashCode());
+ logger.info(m.toString());
+ }
+
}