RIC Dashboard Release Notes
===========================
-Version 2.0.0, 20 Jan 2020
+Version 2.0.0, 24 Jan 2020
--------------------------
* Change application properties file to YAML format
* Add mock list of RIC instances to application properties
* Upgrade E2 Manager API and submodule to tag 3.0.3
* Add instance selector dialog component and service
* Repair onSidenavClose method
+* Extend to support selecting a RIC instance within a region
Version 1.3.0, 26 Nov 2019
--------------------------
import java.util.List;
import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegion;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
@Autowired
- private RicInstanceList instanceConfig;
+ private RicRegionList instanceConfig;
public static void main(String[] args) {
SpringApplication.run(DashboardApplication.class, args);
// Ensure output appears on the console by using level WARN
logger.warn("run: version '{}'", getImplementationVersion(MethodHandles.lookup().lookupClass()));
// Validate configuration
- List<RicInstance> instances = instanceConfig.getInstances();
- Assert.notEmpty(instances, "Instance list empty");
- for (RicInstance it : instances) {
- logger.warn("run: RIC instance {}", it);
- Assert.hasText(it.getKey(), "Instance key missing");
- Assert.hasText(it.getName(), "Name missing for instance " + it.getKey());
- Assert.hasText(it.getAppUrlPrefix(), "App URL prefix missing for instance " + it.getKey());
- Assert.hasText(it.getCaasUrlPrefix(), "Caas URL prefix missing for instance " + it.getKey());
- Assert.hasText(it.getPltUrlPrefix(), "Plt URL prefix missing for instance " + it.getKey());
+ List<RicRegion> regions = instanceConfig.getRegions();
+ Assert.notEmpty(regions, "Region list empty");
+ for (RicRegion r : regions) {
+ Assert.notEmpty(r.getInstances(), "Instance list empty for region " + r.getName());
+ for (RicInstance it : r.getInstances()) {
+ logger.warn("run: RIC region {} instance {}", r, it);
+ Assert.hasText(it.getKey(), "Instance key missing");
+ Assert.hasText(it.getName(), "Name missing for instance " + it.getKey());
+ Assert.hasText(it.getAppUrlPrefix(), "App URL prefix missing for instance " + it.getKey());
+ Assert.hasText(it.getCaasUrlPrefix(), "Caas URL prefix missing for instance " + it.getKey());
+ Assert.hasText(it.getPltUrlPrefix(), "Plt URL prefix missing for instance " + it.getKey());
+ }
}
}
import org.oransc.ric.a1med.client.api.A1MediatorApi;
import org.oransc.ric.a1med.client.invoker.ApiClient;
import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
- public A1MediatorApiBuilder(final RicInstanceList instanceConfig, final String urlSuffix) {
+ public A1MediatorApiBuilder(final RicRegionList instanceConfig, final String urlSuffix) {
logger.debug("ctor: suffix {}", urlSuffix);
this.instanceConfig = instanceConfig;
this.urlSuffix = urlSuffix;
import java.lang.invoke.MethodHandles;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
// Populated by the autowired constructor
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
@Autowired
public A1MediatorConfiguration(@Value("${a1med.url.suffix}") final String urlSuffix,
- final RicInstanceList instanceConfig) {
+ final RicRegionList instanceConfig) {
logger.info("ctor: URL suffix {}", urlSuffix);
this.urlSuffix = urlSuffix;
this.instanceConfig = instanceConfig;
import org.oransc.ric.plt.appmgr.client.api.XappApi;
import org.oransc.ric.plt.appmgr.client.invoker.ApiClient;
import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
- public AppManagerApiBuilder(final RicInstanceList instanceConfig, final String urlSuffix) {
+ public AppManagerApiBuilder(final RicRegionList instanceConfig, final String urlSuffix) {
logger.debug("ctor: suffix {}", urlSuffix);
this.instanceConfig = instanceConfig;
this.urlSuffix = urlSuffix;
import java.lang.invoke.MethodHandles;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
// Populated by the autowired constructor
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
@Autowired
public AppManagerConfiguration(@Value("${appmgr.url.suffix}") final String urlSuffix,
- final RicInstanceList instanceConfig) {
+ final RicRegionList instanceConfig) {
logger.info("ctor: URL suffix {}", urlSuffix);
this.urlSuffix = urlSuffix;
this.instanceConfig = instanceConfig;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.oransc.ric.portal.dashboard.util.HttpsURLConnectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// Populated by the autowired constructor
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
@Autowired
public CaasIngressConfiguration( //
@Value("${caasingress.plt.url.suffix}") final String pltUrlSuffix, //
@Value("${caasingress.insecure}") final Boolean insecureFlag, //
- final RicInstanceList instanceConfig) throws KeyManagementException, NoSuchAlgorithmException {
+ final RicRegionList instanceConfig) throws KeyManagementException, NoSuchAlgorithmException {
logger.debug("ctor: suffix {} insecure flag {}", pltUrlSuffix, insecureFlag);
this.urlSuffix = pltUrlSuffix;
this.instanceConfig = instanceConfig;
import org.oransc.ric.e2mgr.client.api.NodebApi;
import org.oransc.ric.e2mgr.client.invoker.ApiClient;
import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.client.RestTemplate;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
- public E2ManagerApiBuilder(final RicInstanceList instanceConfig, final String urlSuffix) {
+ public E2ManagerApiBuilder(final RicRegionList instanceConfig, final String urlSuffix) {
logger.debug("ctor: suffix {}", urlSuffix);
this.instanceConfig = instanceConfig;
this.urlSuffix = urlSuffix;
import java.lang.invoke.MethodHandles;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
// Populated by the autowired constructor
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
@Autowired
public E2ManagerConfiguration(@Value("${e2mgr.url.suffix}") final String urlSuffix,
- final RicInstanceList instanceConfig) {
+ final RicRegionList instanceConfig) {
logger.info("ctor: URL suffix {}", urlSuffix);
this.urlSuffix = urlSuffix;
this.instanceConfig = instanceConfig;
package org.oransc.ric.portal.dashboard.config;
+import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
-import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegion;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
* in application properties like this:
*
* <pre>
- * ricinstances:
- instances:
- -
- key: key1
- name: Friendly Name One
- urlPrefix: http://foo.bar.one/
- -
- key: key2
- name: Friendly Name Two
- urlPrefix: http://foo.bar.two/
+ ricinstances:
+ regions:
+ -
+ name: Region ABC
+ instances:
+ -
+ key: key1
+ name: Friendly Name One
+ appUrlPrefix: http://foo.bar.one/
+ -
+ key: key2
+ name: Friendly Name Two
+ appUrlPrefix: http://foo.bar.two/
+ -
+ name: Region DEF
+ instances:
+ -
+ key: key3
+ name: Friendly Name Three
+ appUrlPrefix: http://foo.bar.three/
* </pre>
*/
@Configuration
@Profile("!test")
public class RICInstanceConfiguration {
- private List<RicInstance> instances = new ArrayList<>();
+ private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+ private List<RicRegion> regions = new ArrayList<>();
// Called by spring with config data
- public void setInstances(List<RicInstance> instances) {
- this.instances = instances;
+ public void setRegions(List<RicRegion> regions) {
+ this.regions = regions;
}
@Bean
- public RicInstanceList ricInstanceList() {
- return new RicInstanceList(instances);
+ public RicRegionList ricRegions() {
+ logger.debug("Creating bean ricRegions");
+ return new RicRegionList(regions);
}
}
import org.oransc.ric.portal.dashboard.k8sapi.SimpleKubernetesClient;
import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.util.DefaultUriBuilderFactory;
private Map<String, SimpleKubernetesClient> cache = new ConcurrentHashMap<>();
private final String urlSuffix;
- private final RicInstanceList instanceConfig;
+ private final RicRegionList instanceConfig;
- public SimpleKubernetesClientBuilder(final RicInstanceList instanceConfig, final String urlSuffix) {
+ public SimpleKubernetesClientBuilder(final RicRegionList instanceConfig, final String urlSuffix) {
logger.debug("ctor: suffix {}", urlSuffix);
this.instanceConfig = instanceConfig;
this.urlSuffix = urlSuffix;
import org.oransc.ric.portal.dashboard.DashboardUserManager;
import org.oransc.ric.portal.dashboard.model.ErrorTransport;
import org.oransc.ric.portal.dashboard.model.IDashboardResponse;
-import org.oransc.ric.portal.dashboard.model.RicInstanceKeyName;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+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.SuccessTransport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private DashboardUserManager dashboardUserManager;
@Autowired
- private RicInstanceList instanceConfig;
+ private RicRegionList instanceConfig;
@ApiOperation(value = "Gets the Dashboard MANIFEST.MF property Implementation-Version.", response = SuccessTransport.class)
@GetMapping(VERSION_METHOD)
return dashboardUserManager.getUsers();
}
- @ApiOperation(value = "Gets the list of RIC instances.", response = RicInstanceKeyName.class, responseContainer = "List")
+ @ApiOperation(value = "Gets the RIC regions and instances.", response = RicRegion.class, responseContainer = "List")
@GetMapping(INSTANCE_METHOD)
@Secured({ DashboardConstants.ROLE_ADMIN, DashboardConstants.ROLE_STANDARD })
- public List<RicInstanceKeyName> getInstances() {
- logger.debug("getInstances");
- return instanceConfig.getKeyNameList();
+ public List<RicRegionTransport> getRegionsInstances() {
+ logger.debug("getRegionsInstances");
+ return instanceConfig.getSimpleInstances();
}
@ApiOperation(value = "Gets the kibana metrics URL for the specified app.", response = SuccessTransport.class)
@Override
public String toString() {
- return this.getClass().getName() + "[name=" + getName() + ", version=" + getVersion() + "]";
+ return this.getClass().getSimpleName() + "[name=" + getName() + ", version=" + getVersion() + "]";
}
}
@Override
public String toString() {
- return this.getClass().getName() + "[ecompUser=" + ecompUser + ", isAccountNonExpired=" + isAccountNonExpired()
- + ", isAccountNonLocked=" + isAccountNonLocked() + ", isCredentialsNonExpired="
+ return this.getClass().getSimpleName() + "[ecompUser=" + ecompUser + ", isAccountNonExpired="
+ + isAccountNonExpired() + ", isAccountNonLocked=" + isAccountNonLocked() + ", isCredentialsNonExpired="
+ isCredentialsNonExpired() + "]";
}
@Override
public String toString() {
- return this.getClass().getName() + "[timestamp=" + getTimestamp() + ", error=" + getError() + ", path="
+ return this.getClass().getSimpleName() + "[timestamp=" + getTimestamp() + ", error=" + getError() + ", path="
+ getPath() + "]";
}
@Override
public String toString() {
- return this.getClass().getName() + "[nodebIdentity=" + getNodebIdentity() + ", nodebStatus=" + getNodebStatus()
- + "]";
+ return this.getClass().getSimpleName() + "[nodebIdentity=" + getNodebIdentity() + ", nodebStatus="
+ + getNodebStatus() + "]";
}
}
@Override
public String toString() {
- return this.getClass().getName() + "[key=" + getKey() + ", name=" + getName() + ", appUrlPrefix=" + appUrlPrefix
- + ", pltUrlPrefix=" + pltUrlPrefix + ", caasUrlPrefix=" + caasUrlPrefix + "]";
+ return this.getClass().getSimpleName() + "[key=" + getKey() + ", name=" + getName() + ", appUrlPrefix="
+ + appUrlPrefix + ", pltUrlPrefix=" + pltUrlPrefix + ", caasUrlPrefix=" + caasUrlPrefix + "]";
}
@Override
@Override
public String toString() {
- return this.getClass().getName() + "[key=" + getKey() + ", name=" + getName() + "]";
+ return this.getClass().getSimpleName() + "[key=" + getKey() + ", name=" + getName() + "]";
}
@Override
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ric.portal.dashboard.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Transport model for RIC region which has a list of instances.
+ */
+public class RicRegion implements IDashboardResponse {
+
+ private String name;
+ private List<RicInstance> instances;
+
+ /**
+ * Builds an empty object.
+ */
+ public RicRegion() {
+ // no-arg constructor
+ }
+
+ /**
+ * Convenience constructor for minimal value set.
+ *
+ * @param name
+ * Name
+ */
+ public RicRegion(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String s) {
+ this.name = s;
+ }
+
+ public RicRegion name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public List<RicInstance> getInstances() {
+ return instances;
+ }
+
+ public void setInstances(List<RicInstance> instances) {
+ this.instances = instances;
+ }
+
+ /**
+ * Gets a list of key-name pairs.
+ *
+ * @return List of RicInstanceKeyName objects.
+ */
+ public List<RicInstanceKeyName> getKeyNameList() {
+ List<RicInstanceKeyName> list = new ArrayList<>();
+ for (RicInstance i : instances)
+ list.add(i.toKeyName());
+ return list;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "[name=" + getName() + ", instances=" + instances + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = result * result + ((instances == null) ? 0 : instances.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ RicRegion other = (RicRegion) obj;
+ return Objects.equals(name, other.name) && instances.size() == other.instances.size();
+ }
+
+}
* ========================LICENSE_START=================================
* O-RAN-SC
* %%
- * Copyright (C) 2019 AT&T Intellectual Property
+ * Copyright (C) 2020 AT&T Intellectual Property
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.oransc.ric.portal.dashboard.exception.UnknownInstanceException;
-public class RicInstanceList {
+/**
+ * Used as a bean to publish configuration data in a convenient way.
+ */
+public class RicRegionList {
- private final List<RicInstance> instances;
+ private final List<RicRegion> regions;
- public RicInstanceList() {
- this.instances = new ArrayList<>();
+ public RicRegionList() {
+ this.regions = new ArrayList<>();
}
- public RicInstanceList(List<RicInstance> list) {
- this.instances = list;
+ public RicRegionList(List<RicRegion> list) {
+ this.regions = list;
}
- public List<RicInstance> getInstances() {
- return instances;
+ public List<RicRegion> getRegions() {
+ return regions;
}
/**
- * Gets a list of key-name pairs.
+ * Builds a response that has only key-name pairs.
*
- * @return List of RicInstanceKeyName objects.
+ * @return List of RicRegionTransport objects
*/
- public List<RicInstanceKeyName> getKeyNameList() {
- List<RicInstanceKeyName> list = new ArrayList<>();
- for (RicInstance i : instances)
- list.add(i.toKeyName());
- return list;
+ public List<RicRegionTransport> getSimpleInstances() {
+ List<RicRegionTransport> response = new ArrayList<>();
+ for (RicRegion r : regions)
+ response.add(new RicRegionTransport().name(r.getName()).instances(r.getKeyNameList()));
+ return response;
}
/**
- * Gets the instance with the specified key
+ * Gets the instance with the specified key in any region
*
* @param instanceKey
* Key to fetch
* If the key is not known
*/
public RicInstance getInstance(String instanceKey) {
- for (RicInstance i : instances)
- if (i.getKey().equals(instanceKey))
- return i;
+ for (RicRegion r : regions)
+ for (RicInstance i : r.getInstances())
+ if (i.getKey().equals(instanceKey))
+ return i;
throw new UnknownInstanceException(instanceKey);
}
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "[regions=" + regions + "]";
+ }
+
}
--- /dev/null
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2020 AT&T Intellectual Property
+ * %%
+ * 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.ric.portal.dashboard.model;
+
+import java.util.List;
+
+/**
+ * Transport model for RIC region which has a list of instances with ONLY
+ * key-name pairs.
+ */
+public class RicRegionTransport implements IDashboardResponse {
+
+ private String name;
+ private List<RicInstanceKeyName> instances;
+
+ public String getName() {
+ return name;
+ }
+
+ public RicRegionTransport name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public List<RicInstanceKeyName> getInstances() {
+ return instances;
+ }
+
+ public RicRegionTransport instances(List<RicInstanceKeyName> instances) {
+ this.instances = instances;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + "[name=" + getName() + ", instances=" + instances + "]";
+ }
+
+}
@Override
public String toString() {
- return this.getClass().getName() + "[status=" + getStatus() + ", data=" + getData() + "]";
+ return this.getClass().getSimpleName() + "[status=" + getStatus() + ", data=" + getData() + "]";
}
}
ac: http://jar-app-props-kibana-url-ac
mc: http://jar-app-props-kibana-url-mc
-# Instances
+# Regions and instances
+# The regions are a just convenience for users,
+# the keys must be unique across all instances.
ricinstances:
- instances:
+ regions:
-
- key: i1
- name: Primary RIC Instance
- appUrlPrefix: App prefix 1
- caasUrlPrefix: Caas prefix 1
- pltUrlPrefix: Plt prefix 1
+ name: Region AAA
+ instances:
+ -
+ key: i1
+ name: Primary RIC Instance
+ appUrlPrefix: App prefix 1
+ caasUrlPrefix: Caas prefix 1
+ pltUrlPrefix: Plt prefix 1
+ -
+ key: i2
+ name: RIC Instance Nr Two
+ appUrlPrefix: App prefix 2
+ caasUrlPrefix: Caas prefix 2
+ pltUrlPrefix: Plt prefix 2
-
- key: i2
- name: RIC Instance Nr Two
- appUrlPrefix: App prefix 2
- caasUrlPrefix: Caas prefix 2
- pltUrlPrefix: Plt prefix 2
+ name: Region DDD
+ instances:
+ -
+ key: i3
+ name: RIC Instance in region D
+ appUrlPrefix: App prefix 3
+ caasUrlPrefix: Caas prefix 3
+ pltUrlPrefix: Plt prefix 3
import java.util.List;
import org.oransc.ric.portal.dashboard.model.RicInstance;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegion;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
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;
private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
// Publish constants for use in tests
+ public static final String REGION_NAME_1 = "Region AAA";
+ public static final String REGION_NAME_2 = "Region DDD";
public static final String INSTANCE_KEY_1 = "i1";
public static final String INSTANCE_KEY_2 = "i2";
public static final String[] INSTANCE_KEYS = { INSTANCE_KEY_1, INSTANCE_KEY_2 };
- // Simulate remote method delay for UI testing
- private int delayMs;
-
- @Autowired
- public RICInstanceMockConfiguration(@Value("${mock.config.delay:0}") int delayMs) {
- logger.debug("ctor: configured with delay {}", delayMs);
- this.delayMs = delayMs;
- }
+ // No constructor needed, don't simulate delay from the Dashboard
@Bean
- public RicInstanceList ricInstanceList() throws InterruptedException {
- if (delayMs > 0) {
- logger.debug("ricInstanceList sleeping {}", delayMs);
- Thread.sleep(delayMs);
- }
- List<RicInstance> instances = new ArrayList<>();
- for (String key : INSTANCE_KEYS) {
- RicInstance i = new RicInstance().key(key).name("RIC Instance " + key)
- .appUrlPrefix("http://" + key + ".domain.name/app")
- .pltUrlPrefix("http://" + key + ".domain.name/plt")
- .caasUrlPrefix("http://" + key + ".domain.name/caas");
- instances.add(i);
- }
- return new RicInstanceList(instances);
+ public RicRegionList ricRegions() {
+ logger.debug("Creating mock bean ricRegions");
+ List<RicRegion> regions = new ArrayList<>();
+ RicRegion region1 = new RicRegion().name(REGION_NAME_1);
+ regions.add(region1);
+ List<RicInstance> instances1 = new ArrayList<>();
+ region1.setInstances(instances1);
+ String key1 = INSTANCE_KEY_1;
+ instances1.add(new RicInstance().key(key1).name("RIC Instance " + key1) //
+ .appUrlPrefix("http://" + key1 + ".domain.name/app") //
+ .pltUrlPrefix("http://" + key1 + ".domain.name/plt") //
+ .caasUrlPrefix("http://" + key1 + ".domain.name/caas"));
+ RicRegion region2 = new RicRegion().name(REGION_NAME_2);
+ regions.add(region2);
+ List<RicInstance> instances2 = new ArrayList<>();
+ region2.setInstances(instances2);
+ String key2 = INSTANCE_KEY_2;
+ instances2.add(new RicInstance().key(key2).name("RIC Instance " + key2) //
+ .appUrlPrefix("http://" + key2 + ".domain.name/app") //
+ .pltUrlPrefix("http://" + key2 + ".domain.name/plt") //
+ .caasUrlPrefix("http://" + key2 + ".domain.name/caas"));
+ return new RicRegionList(regions);
}
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
-import org.oransc.ric.portal.dashboard.model.RicInstanceList;
+import org.oransc.ric.portal.dashboard.model.RicRegionList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
// Relies on Spring-Boot feature of populating instances data from configuration
@Autowired
- protected RicInstanceList instanceConfig;
+ protected RicRegionList instanceConfig;
// Sonar finds the annotations on this class and insists on at least one test.
@Test
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
public void contextLoads() {
// Silence Sonar warning about missing assertion.
logger.info(m.toString());
}
+ private void checkRicRegion(RicRegion m) {
+ Assert.assertEquals(s1, m.getName());
+ }
+
+ @Test
+ public void testRicRegion() {
+ RicRegion m = new RicRegion();
+ m.setName(s1);
+ checkRicRegion(m);
+ Assert.assertTrue(m.equals(m));
+ Assert.assertFalse(m.equals(null));
+ Assert.assertFalse(m.equals(new RicRegion()));
+ Assert.assertNotEquals(1, m.hashCode());
+ logger.info(m.toString());
+ }
+
@Test
- public void testRicInstanceList() {
- RicInstanceList m = new RicInstanceList();
- List<RicInstance> list = new ArrayList<>();
- m = new RicInstanceList(list);
- Assert.assertEquals(list, m.getInstances());
- Assert.assertNotNull(m.getKeyNameList());
+ public void testRicRegionList() {
+ RicRegionList m = new RicRegionList();
+ List<RicRegion> list = new ArrayList<>();
+ m = new RicRegionList(list);
+ Assert.assertEquals(list, m.getRegions());
+ Assert.assertNotNull(m.getSimpleInstances());
try {
m.getInstance(s1);
} catch (UnknownInstanceException ex) {
export interface RicInstance {
key: string;
name: string;
-}
\ No newline at end of file
+}
+
+export interface RicRegion {
+ name: string;
+ instances: Array<RicInstance>;
+}
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { shareReplay, tap } from 'rxjs/operators';
-import { RicInstance } from '../../interfaces/dashboard.types';
+import { RicInstance, RicRegion } from '../../interfaces/dashboard.types';
import { DashboardService } from '../dashboard/dashboard.service';
@Injectable({
})
export class InstanceSelectorService {
- private instanceArray: Observable<RicInstance[]>;
- private selectedInstance: BehaviorSubject<RicInstance> = new BehaviorSubject<RicInstance>({ key: '', name:''});
+ private allInstances: Observable<RicRegion[]>;
+ private selectedInstance: BehaviorSubject<RicInstance> = new BehaviorSubject<RicInstance>({ key: '', name: '' });
constructor(
private dashboardSvc: DashboardService,
private httpClient: HttpClient) {
}
- getInstanceArray(): Observable<RicInstance[]> {
- if (this.instanceArray) {
- return this.instanceArray;
+ getAllInstances(): Observable<RicRegion[]> {
+ if (this.allInstances) {
+ return this.allInstances;
}
const path = this.dashboardSvc.buildPath('admin', null, 'instance');
- return this.instanceArray = this.httpClient.get<RicInstance[]>(path)
+ return this.allInstances = this.httpClient.get<RicRegion[]>(path)
.pipe(
shareReplay(1)
);
}
updateSelectedInstance(instance: RicInstance) {
- this.selectedInstance.next(instance)
+ this.selectedInstance.next(instance);
}
}
Select RIC Instance
</div>
<form [formGroup]="instanceForm" novalidate autocomplete="off" (ngSubmit)="changeInstance(instanceForm.value.instance)">
+ <div mat-dialog-content>
+ <mat-form-field>
+ <mat-label>Select a region</mat-label>
+ <mat-select (selectionChange)="changeRegion($event.value)">
+ <mat-option *ngFor="let region of allRegions" [value]="region">
+ {{region.name}}
+ </mat-option>
+ </mat-select>
+ </mat-form-field>
+ </div>
<div mat-dialog-content>
<mat-form-field>
<mat-label>Select an instance</mat-label>
<mat-select formControlName="instance">
- <mat-option *ngFor="let instance of instanceArray" [value]="instance">
+ <mat-option *ngFor="let instance of regionInstances" [value]="instance">
{{instance.name}}
</mat-option>
</mat-select>
* ========================LICENSE_END===================================
*/
-import { Component, OnDestroy, OnInit } from '@angular/core';
+import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
-import { Subscription } from 'rxjs';
import { finalize } from 'rxjs/operators';
-import { RicInstance } from '../../interfaces/dashboard.types';
+import { RicInstance, RicRegion } from '../../interfaces/dashboard.types';
import { InstanceSelectorService } from '../../services/instance-selector/instance-selector.service';
import { LoadingDialogService } from '../../services/ui/loading-dialog.service';
selector: 'rd-instance-selector-dialog',
templateUrl: './instance-selector-dialog.component.html',
})
-export class InstanceSelectorDialogComponent implements OnInit, OnDestroy {
+export class InstanceSelectorDialogComponent implements OnInit {
- private instanceArray: RicInstance[];
+ private allRegions: RicRegion[];
+ private regionInstances: RicInstance[];
private instanceForm: FormGroup;
- private instanceChange: Subscription;
constructor(
private dialogRef: MatDialogRef<InstanceSelectorDialogComponent>,
ngOnInit() {
this.instanceForm = new FormGroup({
- instance: new FormControl('', [Validators.required]),
- })
+ instance: new FormControl('', [Validators.required])
+ });
this.loadingDialogService.startLoading('Loading RIC instances');
- this.instanceSelectorService.getInstanceArray()
+ this.instanceSelectorService.getAllInstances()
.pipe(
finalize(() => this.loadingDialogService.stopLoading())
)
- .subscribe((instanceArray: RicInstance[]) => {
- this.instanceArray = instanceArray;
- })
-
- this.instanceChange = this.instanceSelectorService.getSelectedInstance().subscribe((selectedInstance: RicInstance) => {
- if (selectedInstance.key) {
- this.instanceForm.setValue({ instance: selectedInstance })
- }
- });
+ .subscribe((regArray: RicRegion[]) => {
+ this.allRegions = regArray;
+ });
}
- ngOnDestroy() {
- this.instanceChange.unsubscribe();
- }
-
- changeInstance(selectedInstance) {
+ changeInstance(selectedInstance: RicInstance) {
this.instanceSelectorService.updateSelectedInstance(selectedInstance);
this.dialogRef.close(true);
}
+ changeRegion(selectedRegion: RicRegion) {
+ this.instanceForm.setValue({ instance: '' });
+ this.regionInstances = selectedRegion.instances;
+ }
}