Added support for added external A1-P adapter. This makes it possible to design and include
adapter to APIs for accessing of A1 policies (in a NearRT-RIC) without any changes in this
SW.
Issue-ID: CCSDK-3655
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
Change-Id: Idc7bf97963a2455bde983b06a5f861df77d901ae
## License
ONAP : ccsdk oran
-Copyright (C) 2019-2020 Nordix Foundation. All rights reserved.
+Copyright (C) 2019-2022 Nordix Foundation. All rights reserved.
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
import java.util.List;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.RicConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy;
import reactor.core.publisher.Flux;
*/
public interface A1Client {
+ public interface Factory {
+ A1Client create(RicConfig ricConfig, AsyncRestClientFactory restClientFactory);
+ }
+
public enum A1ProtocolType {
UNKNOWN, //
STD_V1_1, // STD A1 version 1.1
OSC_V1, // OSC 'A1'
CCSDK_A1_ADAPTER_STD_V1_1, // CCSDK_A1_ADAPTER with STD A1 version 1.1 southbound
CCSDK_A1_ADAPTER_STD_V2_0_0, // CCSDK_A1_ADAPTER with STD A1 version 2.0.0 southbound
- CCSDK_A1_ADAPTER_OSC_V1 // CCSDK_A1_ADAPTER with OSC 'A1' southbound
+ CCSDK_A1_ADAPTER_OSC_V1, // CCSDK_A1_ADAPTER with OSC 'A1' southbound
+ CUSTOM_PROTOCOL // Some other protocol handled by some custom A1 adapter class.
}
public Mono<A1ProtocolType> getProtocolVersion();
package org.onap.ccsdk.oran.a1policymanagementservice.clients;
+import java.lang.reflect.Constructor;
+
import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1Client.A1ProtocolType;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ControllerConfig;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.RicConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric;
import org.slf4j.Logger;
|| version == A1ProtocolType.CCSDK_A1_ADAPTER_OSC_V1
|| version == A1ProtocolType.CCSDK_A1_ADAPTER_STD_V2_0_0) {
return new CcsdkA1AdapterClient(version, ric.getConfig(), getControllerConfig(ric), this.restClientFactory);
+ } else if (version == A1ProtocolType.CUSTOM_PROTOCOL) {
+ return createCustomAdapter(ric);
} else {
logger.error("Unhandled protocol: {}", version);
throw new ServiceException("Unhandled protocol");
}
}
+ private A1Client createCustomAdapter(Ric ric) throws ServiceException {
+ try {
+ Class<?> clazz = Class.forName(ric.getConfig().customAdapterClass());
+ if (A1Client.class.isAssignableFrom(clazz)) {
+ Constructor<?> constructor = clazz.getConstructor(RicConfig.class, AsyncRestClientFactory.class);
+ return (A1Client) constructor.newInstance(ric.getConfig(), this.restClientFactory);
+ } else if (A1Client.Factory.class.isAssignableFrom(clazz)) {
+ A1Client.Factory factory = (A1Client.Factory) clazz.getDeclaredConstructor().newInstance();
+ return factory.create(ric.getConfig(), this.restClientFactory);
+ } else {
+ throw new ServiceException("The custom class must either implement A1Client.Factory or A1Client");
+ }
+ } catch (ClassNotFoundException e) {
+ throw new ServiceException("Could not find class: " + ric.getConfig().customAdapterClass(), e);
+ } catch (Exception e) {
+ throw new ServiceException("Cannot create custom adapter: " + ric.getConfig().customAdapterClass(), e);
+ }
+ }
+
private void assertNoControllerConfig(Ric ric, A1ProtocolType version) throws ServiceException {
if (!ric.getConfig().controllerName().isEmpty()) {
ric.setProtocolVersion(A1ProtocolType.UNKNOWN);
public class StdA1ClientVersion2 implements A1Client {
static final int CONCURRENCY_RIC = 1; // How many paralell requests that is sent to one NearRT RIC
+ public static class Factory implements A1Client.Factory {
+ @Override
+ public A1Client create(RicConfig ricConfig, AsyncRestClientFactory restClientFactory) {
+ return new StdA1ClientVersion2(ricConfig, restClientFactory);
+ }
+ }
+
public static class OranV2UriBuilder implements A1UriBuilder {
private final RicConfig ricConfig;
private List<RicConfig> parseRics(JsonObject config) throws ServiceException {
List<RicConfig> result = new ArrayList<>();
for (JsonElement ricElem : getAsJsonArray(config, "ric")) {
- JsonObject ricAsJson = ricElem.getAsJsonObject();
- JsonElement controllerNameElement = ricAsJson.get(CONTROLLER);
+ JsonObject ricJsonObj = ricElem.getAsJsonObject();
RicConfig ricConfig = ImmutableRicConfig.builder() //
- .ricId(get(ricAsJson, "name", "id", "ricId").getAsString()) //
- .baseUrl(get(ricAsJson, "baseUrl").getAsString()) //
- .managedElementIds(parseManagedElementIds(get(ricAsJson, "managedElementIds").getAsJsonArray())) //
- .controllerName(controllerNameElement != null ? controllerNameElement.getAsString() : "") //
+ .ricId(get(ricJsonObj, "name", "id", "ricId").getAsString()) //
+ .baseUrl(get(ricJsonObj, "baseUrl").getAsString()) //
+ .managedElementIds(parseManagedElementIds(get(ricJsonObj, "managedElementIds").getAsJsonArray())) //
+ .controllerName(getString(ricJsonObj, CONTROLLER, ""))
+ .customAdapterClass(getString(ricJsonObj, "customAdapterClass", "")) //
.build();
if (!ricConfig.baseUrl().isEmpty()) {
result.add(ricConfig);
return result;
}
+ String getString(JsonObject obj, String name, String defaultValue) {
+ JsonElement elem = obj.get(name);
+ if (elem != null) {
+ return elem.getAsString();
+ }
+ return defaultValue;
+ }
+
Map<String, ControllerConfig> parseControllerConfigs(JsonObject config) throws ServiceException {
if (config.get(CONTROLLER) == null) {
return new HashMap<>();
public ImmutableList<String> managedElementIds();
+ public String customAdapterClass();
+
}
private RicConfig ricConfig;
private RicState state = RicState.UNAVAILABLE;
private Map<String, PolicyType> supportedPolicyTypes = new HashMap<>();
- @Getter
+
@Setter
private A1ProtocolType protocolVersion = A1ProtocolType.UNKNOWN;
this.state = state;
}
+ public synchronized A1ProtocolType getProtocolVersion() {
+ if (this.ricConfig.customAdapterClass().isEmpty()) {
+ return this.protocolVersion;
+ } else {
+ return A1ProtocolType.CUSTOM_PROTOCOL;
+ }
+ }
+
/**
* Gets the nodes managed by this Ric.
*
import java.util.Vector;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ControllerConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ImmutableControllerConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ImmutableRicConfig;
+import org.onap.ccsdk.oran.a1policymanagementservice.configuration.RicConfig;
import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.ServiceException;
import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric;
private Ric ric;
private A1ClientFactory factoryUnderTest;
- private static ImmutableRicConfig ricConfig(String controllerName) {
+ private static ImmutableRicConfig ricConfig(String controllerName, String customAdapter) {
return ImmutableRicConfig.builder() //
.ricId(RIC_NAME) //
.baseUrl("baseUrl") //
.managedElementIds(new Vector<>()) //
.controllerName(controllerName) //
+ .customAdapterClass(customAdapter) //
.build();
}
+ private static ImmutableRicConfig ricConfig(String controllerName) {
+ return ricConfig(controllerName, "");
+ }
+
@BeforeEach
void createFactoryUnderTest() {
SecurityContext sec = new SecurityContext("");
factoryUnderTest = spy(new A1ClientFactory(applicationConfigMock, sec));
this.ric = new Ric(ricConfig(""));
-
}
@Test
assertEquals(A1ProtocolType.STD_V1_1, ric.getProtocolVersion(), "Not correct protocol");
}
+ public static class CustomA1AdapterFactory implements A1Client.Factory {
+ @Override
+ public A1Client create(RicConfig ricConfig, AsyncRestClientFactory restClientFactory) {
+ return new StdA1ClientVersion2(ricConfig, restClientFactory);
+ }
+ }
+
+ @Test
+ void testCustomAdapterCreation() {
+
+ Ric ric = new Ric(ricConfig("", CustomA1AdapterFactory.class.getName()));
+ A1Client client = factoryUnderTest.createA1Client(ric).block();
+
+ assertEquals(client.getClass(), StdA1ClientVersion2.class);
+
+ ric = new Ric(ricConfig("", "org.onap.ccsdk.oran.a1policymanagementservice.clients.StdA1ClientVersion2"));
+ client = factoryUnderTest.createA1Client(ric).block();
+
+ assertEquals(client.getClass(), StdA1ClientVersion2.class);
+
+ ric = new Ric(
+ ricConfig("", "org.onap.ccsdk.oran.a1policymanagementservice.clients.StdA1ClientVersion2$Factory"));
+ client = factoryUnderTest.createA1Client(ric).block();
+
+ assertEquals(client.getClass(), StdA1ClientVersion2.class);
+
+ Exception e = Assertions.assertThrows(Exception.class, () -> {
+ factoryUnderTest.createClient(new Ric(ricConfig("", "junk")), A1ProtocolType.CUSTOM_PROTOCOL);
+ });
+ assertEquals("Could not find class: junk", e.getMessage());
+ }
+
@Test
void getProtocolVersion_error() throws ServiceException {
whenGetProtocolVersionThrowException(clientMock1, clientMock2, clientMock3, clientMock4);
.baseUrl(url) //
.managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
return new Ric(cfg);
}
.baseUrl("RicBaseUrl") //
.managedElementIds(new ArrayList<>()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
asyncRestClientMock = mock(AsyncRestClient.class);
clientUnderTest = new OscA1Client(ricConfig, asyncRestClientMock);
.baseUrl(RIC_URL) //
.managedElementIds(new ArrayList<>()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
asyncRestClientMock = mock(AsyncRestClient.class);
clientUnderTest = new StdA1ClientVersion2(ricConfig, asyncRestClientMock);
.baseUrl("ric1_url") //
.managedElementIds(new Vector<>()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
private static final ImmutableRicConfig RIC_CONFIG_2 = ImmutableRicConfig.builder() //
.baseUrl("ric1_url") //
.managedElementIds(new Vector<>()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
private static final ImmutableRicConfig RIC_CONFIG_3 = ImmutableRicConfig.builder() //
.baseUrl("ric1_url") //
.managedElementIds(new Vector<>()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
ConfigParserResult configParserResult(RicConfig... rics) {
.baseUrl("changed_ric1_url") //
.managedElementIds(new Vector<>()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
update = appConfigUnderTest.setConfiguration(configParserResult(changedRicConfig, RIC_CONFIG_2, RIC_CONFIG_3))
.baseUrl(ricId) //
.managedElementIds(mes) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
}
.baseUrl("http://localhost:8080/") //
.managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
private RefreshConfigTask createTestObject(boolean configFileExists) {
.baseUrl("baseUrl1") //
.managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
.controllerName("controllerName") //
+ .customAdapterClass("") //
.build());
private static final String POLICY_1_ID = "policyId1";
.baseUrl("baseUrl1") //
.managedElementIds(Collections.emptyList()) //
.controllerName("controllerName") //
+ .customAdapterClass("") //
.build());
policy1 = createPolicy("policyId1", false);
policyTypes = new PolicyTypes(appConfig);
.baseUrl("baseUrl") //
.managedElementIds(Collections.emptyList()) //
.controllerName("") //
+ .customAdapterClass("") //
.build();
private Ric ric = new Ric(ricConfig);
private PolicyType policyType = PolicyType.builder() //
-{
+{
"config": {
"description": "Application configuration",
"ric": [
{
"name": "ric2",
"baseUrl": "http://localhost:8081/",
+ "customAdapterClass": "org.onap.ccsdk.oran.a1policymanagementservice.clients.StdA1ClientVersion2$Factory",
"managedElementIds": [
"kista_3",
"kista_4"
{
"config": {
- "//description" : "Test",
+ "description": "Test",
"controller": [
{
"name": "controller1",
{
"name": "ric2",
"baseUrl": "http://localhost:8085/",
+ "customAdapterClass": "org.onap.ccsdk.oran.a1policymanagementservice.clients.StdA1ClientVersion2$Factory",
"managedElementIds": [
"kista_3",
"kista_4"
}
}
}
-}
+}
\ No newline at end of file