Added Controller configuration 20/3120/5
authorPatrikBuhr <patrik.buhr@est.tech>
Thu, 2 Apr 2020 12:46:33 +0000 (14:46 +0200)
committerPatrikBuhr <patrik.buhr@est.tech>
Fri, 3 Apr 2020 06:45:54 +0000 (08:45 +0200)
The controller configuration is loaded like the rest of the configuration
(from CBS or file).
There can now be several controller instances.

Change-Id: Ifacf619cacd8979622d61720fad647754c9f1615
Issue-ID: NONRTRIC-183
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
23 files changed:
policy-agent/config/application.yaml
policy-agent/config/application_configuration.json
policy-agent/src/main/java/org/oransc/policyagent/clients/A1ClientFactory.java
policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOnapA1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java
policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java
policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfigParser.java
policy-agent/src/main/java/org/oransc/policyagent/configuration/ControllerConfig.java [new file with mode: 0644]
policy-agent/src/main/java/org/oransc/policyagent/configuration/RicConfig.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RefreshConfigTask.java
policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java
policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientFactoryTest.java
policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientHelper.java
policy-agent/src/test/java/org/oransc/policyagent/clients/OscA1ClientTest.java
policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOnapA1ClientTest.java
policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java
policy-agent/src/test/java/org/oransc/policyagent/configuration/ApplicationConfigParserTest.java
policy-agent/src/test/java/org/oransc/policyagent/configuration/ApplicationConfigTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/RefreshConfigTaskTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/RicSupervisionTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/RicSynchronizationTaskTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/ServiceSupervisionTest.java
policy-agent/src/test/resources/test_application_configuration_with_dmaap_config.json

index f0fa3a0..5416a4d 100644 (file)
@@ -20,10 +20,6 @@ logging:
     org.oransc.policyagent: INFO
   file: /var/log/policy-agent/application.log
 app:
-  filepath: /opt/app/policy-agent/config/application_configuration.json
-  a1ControllerBaseUrl: http://sdnc.onap:8282
-  a1ControllerUsername: admin
-  a1ControllerPassword: Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
-
+  filepath: /opt/app/policy-agent/config/application_configuration.json  
 server:
    port : 8081
index 8f3f80b..6c21b16 100644 (file)
@@ -1,10 +1,19 @@
 {
    "config": {
       "//description": "Application configuration",
+      "controller": [
+         {
+            "name": "controller1",
+            "baseUrl": "http://a1controller:8282",
+            "userName": "admin",
+            "password": "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"
+         }
+      ],
       "ric": [
          {
             "name": "ric1",
             "baseUrl": "http://ric1:8085/",
+            "controller": "controller1",
             "managedElementIds": [
                "kista_1",
                "kista_2"
index be6d9b4..55abe2c 100644 (file)
@@ -22,6 +22,7 @@ package org.oransc.policyagent.clients;
 
 import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
 import org.oransc.policyagent.configuration.ApplicationConfig;
+import org.oransc.policyagent.configuration.ControllerConfig;
 import org.oransc.policyagent.exceptions.ServiceException;
 import org.oransc.policyagent.repository.Ric;
 import org.slf4j.Logger;
@@ -65,34 +66,52 @@ public class A1ClientFactory {
             .flatMap(version -> createA1ClientMono(ric, version));
     }
 
-    A1Client createClient(Ric ric, A1ProtocolType version) {
+    A1Client createClient(Ric ric, A1ProtocolType version) throws ServiceException {
         if (version == A1ProtocolType.STD_V1_1) {
+            assertNoControllerConfig(ric, version);
             return new StdA1ClientVersion1(ric.getConfig());
         } else if (version == A1ProtocolType.OSC_V1) {
+            assertNoControllerConfig(ric, version);
             return new OscA1Client(ric.getConfig());
         } else if (version == A1ProtocolType.SDNC_OSC_STD_V1_1 || version == A1ProtocolType.SDNC_OSC_OSC_V1) {
-            return new SdncOscA1Client(version, ric.getConfig(), appConfig.getA1ControllerBaseUrl(),
-                appConfig.getA1ControllerUsername(), appConfig.getA1ControllerPassword());
+            return new SdncOscA1Client(version, ric.getConfig(), getControllerConfig(ric));
         } else if (version == A1ProtocolType.SDNC_ONAP) {
-            return new SdncOnapA1Client(ric.getConfig(), appConfig.getA1ControllerBaseUrl(),
-                appConfig.getA1ControllerUsername(), appConfig.getA1ControllerPassword());
+            return new SdncOnapA1Client(ric.getConfig(), getControllerConfig(ric));
         } else {
             logger.error("Unhandled protocol: {}", version);
-            return null;
+            throw new ServiceException("Unhandled protocol");
+        }
+    }
+
+    private ControllerConfig getControllerConfig(Ric ric) throws ServiceException {
+        String controllerName = ric.getConfig().controllerName();
+        if (controllerName.isEmpty()) {
+            throw new ServiceException("NO controller configured for RIC: " + ric.name());
+        }
+        return this.appConfig.getControllerConfig(controllerName);
+    }
+
+    private void assertNoControllerConfig(Ric ric, A1ProtocolType version) throws ServiceException {
+        if (!ric.getConfig().controllerName().isEmpty()) {
+            throw new ServiceException(
+                "Controller config should be empty, ric: " + ric.name() + " when using protocol version: " + version);
         }
     }
 
     private Mono<A1Client> createA1ClientMono(Ric ric, A1ProtocolType version) {
-        A1Client c = createClient(ric, version);
-        return c != null ? Mono.just(c) : Mono.error(new ServiceException("Unhandled protocol: " + version));
+        try {
+            return Mono.just(createClient(ric, version));
+        } catch (ServiceException e) {
+            return Mono.error(e);
+        }
     }
 
     private Mono<A1Client.A1ProtocolType> getProtocolVersion(Ric ric) {
         if (ric.getProtocolVersion() == A1ProtocolType.UNKNOWN) {
-            return fetchVersion(createClient(ric, A1ProtocolType.STD_V1_1)) //
-                .onErrorResume(notUsed -> fetchVersion(createClient(ric, A1ProtocolType.OSC_V1))) //
-                .onErrorResume(notUsed -> fetchVersion(createClient(ric, A1ProtocolType.SDNC_OSC_STD_V1_1))) //
-                .onErrorResume(notUsed -> fetchVersion(createClient(ric, A1ProtocolType.SDNC_ONAP))) //
+            return fetchVersion(ric, A1ProtocolType.STD_V1_1) //
+                .onErrorResume(notUsed -> fetchVersion(ric, A1ProtocolType.OSC_V1)) //
+                .onErrorResume(notUsed -> fetchVersion(ric, A1ProtocolType.SDNC_OSC_STD_V1_1)) //
+                .onErrorResume(notUsed -> fetchVersion(ric, A1ProtocolType.SDNC_ONAP)) //
                 .doOnNext(ric::setProtocolVersion)
                 .doOnNext(version -> logger.debug("Established protocol version:{} for Ric: {}", version, ric.name())) //
                 .doOnError(notUsed -> logger.warn("Could not get protocol version from RIC: {}", ric.name())); //
@@ -101,7 +120,8 @@ public class A1ClientFactory {
         }
     }
 
-    private Mono<A1ProtocolType> fetchVersion(A1Client a1Client) {
-        return a1Client.getProtocolVersion();
+    private Mono<A1ProtocolType> fetchVersion(Ric ric, A1ProtocolType protocolType) {
+        return createA1ClientMono(ric, protocolType) //
+            .flatMap(A1Client::getProtocolVersion);
     }
 }
index cfabf51..9e9e7ab 100644 (file)
@@ -27,6 +27,7 @@ import java.util.Optional;
 
 import org.immutables.gson.Gson;
 import org.immutables.value.Value;
+import org.oransc.policyagent.configuration.ControllerConfig;
 import org.oransc.policyagent.configuration.RicConfig;
 import org.oransc.policyagent.repository.Policy;
 import org.slf4j.Logger;
@@ -58,20 +59,19 @@ public class SdncOnapA1Client implements A1Client {
 
     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-    private final String a1ControllerUsername;
-    private final String a1ControllerPassword;
+    private final ControllerConfig controllerConfig;
     private final RicConfig ricConfig;
     private final AsyncRestClient restClient;
 
-    public SdncOnapA1Client(RicConfig ricConfig, String baseUrl, String username, String password) {
-        this(ricConfig, username, password, new AsyncRestClient(baseUrl + "/restconf/operations"));
-        logger.debug("SdncOnapA1Client for ric: {}, a1ControllerBaseUrl: {}", ricConfig.name(), baseUrl);
+    public SdncOnapA1Client(RicConfig ricConfig, ControllerConfig controllerConfig) {
+        this(ricConfig, controllerConfig, new AsyncRestClient(controllerConfig.baseUrl() + "/restconf/operations"));
+        logger.debug("SdncOnapA1Client for ric: {}, a1ControllerBaseUrl: {}", ricConfig.name(),
+            controllerConfig.baseUrl());
     }
 
-    public SdncOnapA1Client(RicConfig ricConfig, String username, String password, AsyncRestClient restClient) {
+    public SdncOnapA1Client(RicConfig ricConfig, ControllerConfig controllerConfig, AsyncRestClient restClient) {
         this.ricConfig = ricConfig;
-        this.a1ControllerUsername = username;
-        this.a1ControllerPassword = password;
+        this.controllerConfig = controllerConfig;
         this.restClient = restClient;
     }
 
@@ -98,8 +98,8 @@ public class SdncOnapA1Client implements A1Client {
         logger.debug("POST getPolicyType inputJsonString = {}", inputJsonString);
 
         return restClient
-            .postWithAuthHeader(URL_PREFIX + "getPolicyType", inputJsonString, a1ControllerUsername,
-                a1ControllerPassword) //
+            .postWithAuthHeader(URL_PREFIX + "getPolicyType", inputJsonString, controllerConfig.userName(),
+                controllerConfig.password()) //
             .flatMap(response -> SdncJsonHelper.getValueFromResponse(response, "policy-type")) //
             .flatMap(SdncJsonHelper::extractPolicySchema);
     }
@@ -117,8 +117,8 @@ public class SdncOnapA1Client implements A1Client {
         String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
         logger.debug("POST putPolicy inputJsonString = {}", inputJsonString);
 
-        return restClient.postWithAuthHeader(URL_PREFIX + "createPolicyInstance", inputJsonString, a1ControllerUsername,
-            a1ControllerPassword);
+        return restClient.postWithAuthHeader(URL_PREFIX + "createPolicyInstance", inputJsonString,
+            controllerConfig.userName(), controllerConfig.password());
     }
 
     @Override
@@ -151,8 +151,8 @@ public class SdncOnapA1Client implements A1Client {
         logger.debug("POST getPolicyTypeIdentities inputJsonString = {}", inputJsonString);
 
         return restClient
-            .postWithAuthHeader("/A1-ADAPTER-API:getPolicyTypes", inputJsonString, a1ControllerUsername,
-                a1ControllerPassword) //
+            .postWithAuthHeader(URL_PREFIX + "getPolicyTypes", inputJsonString, controllerConfig.userName(),
+                controllerConfig.password()) //
             .flatMap(response -> SdncJsonHelper.getValueFromResponse(response, "policy-type-id-list")) //
             .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
     }
@@ -166,8 +166,8 @@ public class SdncOnapA1Client implements A1Client {
         logger.debug("POST getPolicyIdentities inputJsonString = {}", inputJsonString);
 
         return restClient
-            .postWithAuthHeader("/A1-ADAPTER-API:getPolicyInstances", inputJsonString, a1ControllerUsername,
-                a1ControllerPassword) //
+            .postWithAuthHeader(URL_PREFIX + "getPolicyInstances", inputJsonString, controllerConfig.userName(),
+                controllerConfig.password()) //
             .flatMap(response -> SdncJsonHelper.getValueFromResponse(response, "policy-instance-id-list")) //
             .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
     }
@@ -186,7 +186,7 @@ public class SdncOnapA1Client implements A1Client {
         String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
         logger.debug("POST deletePolicy inputJsonString = {}", inputJsonString);
 
-        return restClient.postWithAuthHeader("/A1-ADAPTER-API:deletePolicyInstance", inputJsonString,
-            a1ControllerUsername, a1ControllerPassword);
+        return restClient.postWithAuthHeader(URL_PREFIX + "deletePolicyInstance", inputJsonString,
+            controllerConfig.userName(), controllerConfig.password());
     }
 }
index 03fa97d..ece40e1 100644 (file)
@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Optional;
 
 import org.immutables.value.Value;
+import org.oransc.policyagent.configuration.ControllerConfig;
 import org.oransc.policyagent.configuration.RicConfig;
 import org.oransc.policyagent.repository.Policy;
 import org.slf4j.Logger;
@@ -69,8 +70,7 @@ public class SdncOscA1Client implements A1Client {
     private static final String GET_POLICY_RPC = "getA1Policy";
     private static final String UNHANDELED_PROTOCOL = "Bug, unhandeled protocoltype: ";
     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-    private final String a1ControllerUsername;
-    private final String a1ControllerPassword;
+    private final ControllerConfig controllerConfig;
     private final AsyncRestClient restClient;
     private final RicConfig ricConfig;
     private final A1ProtocolType protocolType;
@@ -85,21 +85,18 @@ public class SdncOscA1Client implements A1Client {
      * @param username username to accesss the SDNC controller
      * @param password password to accesss the SDNC controller
      */
-    public SdncOscA1Client(A1ProtocolType protocolType, RicConfig ricConfig, String controllerBaseUrl, String username,
-        String password) {
-        this(protocolType, ricConfig, username, password,
-            new AsyncRestClient(controllerBaseUrl + "/restconf/operations"));
-        logger.debug("SdncOscA1Client for ric: {}, a1ControllerBaseUrl: {}", ricConfig.name(), controllerBaseUrl);
+    public SdncOscA1Client(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig) {
+        this(protocolType, ricConfig, controllerConfig,
+            new AsyncRestClient(controllerConfig.baseUrl() + "/restconf/operations"));
+        logger.debug("SdncOscA1Client for ric: {}, a1Controller: {}", ricConfig.name(), controllerConfig);
     }
 
-    public SdncOscA1Client(A1ProtocolType protocolType, RicConfig ricConfig, String username, String password,
+    public SdncOscA1Client(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig,
         AsyncRestClient restClient) {
-        this.a1ControllerUsername = username;
-        this.a1ControllerPassword = password;
         this.restClient = restClient;
         this.ricConfig = ricConfig;
         this.protocolType = protocolType;
-
+        this.controllerConfig = controllerConfig;
     }
 
     @Override
@@ -222,7 +219,8 @@ public class SdncOscA1Client implements A1Client {
         final String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
 
         return restClient
-            .postWithAuthHeader(controllerUrl(rpcName), inputJsonString, a1ControllerUsername, a1ControllerPassword)
+            .postWithAuthHeader(controllerUrl(rpcName), inputJsonString, this.controllerConfig.userName(),
+                this.controllerConfig.password()) //
             .flatMap(this::extractResponseBody);
     }
 
index 3b4f810..5d7d5d9 100644 (file)
@@ -27,7 +27,6 @@ import java.util.Map;
 import java.util.Properties;
 
 import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
 
 import lombok.Getter;
 
@@ -42,37 +41,18 @@ public class ApplicationConfig {
     @NotEmpty
     private String filepath;
 
-    @NotEmpty
-    private String a1ControllerBaseUrl;
-
-    @NotEmpty
-    private String a1ControllerUsername;
-
-    @NotEmpty
-    private String a1ControllerPassword;
-
     private Map<String, RicConfig> ricConfigs = new HashMap<>();
     @Getter
     private Properties dmaapPublisherConfig;
     @Getter
     private Properties dmaapConsumerConfig;
 
+    private Map<String, ControllerConfig> controllerConfigs = new HashMap<>();
+
     public String getLocalConfigurationFilePath() {
         return this.filepath;
     }
 
-    public synchronized String getA1ControllerBaseUrl() {
-        return this.a1ControllerBaseUrl;
-    }
-
-    public synchronized String getA1ControllerUsername() {
-        return this.a1ControllerUsername;
-    }
-
-    public synchronized String getA1ControllerPassword() {
-        return this.a1ControllerPassword;
-    }
-
     /*
      * Do not remove, used by framework!
      */
@@ -80,29 +60,24 @@ public class ApplicationConfig {
         this.filepath = filepath;
     }
 
-    public synchronized void setA1ControllerBaseUrl(String a1ControllerBaseUrl) {
-        this.a1ControllerBaseUrl = a1ControllerBaseUrl;
-    }
-
-    public synchronized void setA1ControllerUsername(String a1ControllerUsername) {
-        this.a1ControllerUsername = a1ControllerUsername;
-    }
-
-    public synchronized void setA1ControllerPassword(String a1ControllerPassword) {
-        this.a1ControllerPassword = a1ControllerPassword;
-    }
-
     public synchronized Collection<RicConfig> getRicConfigs() {
         return this.ricConfigs.values();
     }
 
-    public RicConfig getRic(String ricName) throws ServiceException {
-        for (RicConfig ricConfig : getRicConfigs()) {
-            if (ricConfig.name().equals(ricName)) {
-                return ricConfig;
-            }
+    public synchronized ControllerConfig getControllerConfig(String name) throws ServiceException {
+        ControllerConfig controllerConfig = this.controllerConfigs.get(name);
+        if (controllerConfig == null) {
+            throw new ServiceException("Could not find controller config: " + name);
+        }
+        return controllerConfig;
+    }
+
+    public synchronized RicConfig getRic(String ricName) throws ServiceException {
+        RicConfig ricConfig = this.ricConfigs.get(ricName);
+        if (ricConfig == null) {
+            throw new ServiceException("Could not find ric configuration: " + ricName);
         }
-        throw new ServiceException("Could not find ric: " + ricName);
+        return ricConfig;
     }
 
     public static class RicConfigUpdate {
@@ -121,15 +96,16 @@ public class ApplicationConfig {
         }
     }
 
-    public synchronized Flux<RicConfigUpdate> setConfiguration(@NotNull Collection<RicConfig> ricConfigs,
-        Properties dmaapPublisherConfig, Properties dmaapConsumerConfig) {
+    public synchronized Flux<RicConfigUpdate> setConfiguration(
+        ApplicationConfigParser.ConfigParserResult parserResult) {
 
         Collection<RicConfigUpdate> modifications = new ArrayList<>();
-        this.dmaapPublisherConfig = dmaapPublisherConfig;
-        this.dmaapConsumerConfig = dmaapConsumerConfig;
+        this.dmaapPublisherConfig = parserResult.dmaapPublisherConfig();
+        this.dmaapConsumerConfig = parserResult.dmaapConsumerConfig();
+        this.controllerConfigs = parserResult.controllerConfigs();
 
         Map<String, RicConfig> newRicConfigs = new HashMap<>();
-        for (RicConfig newConfig : ricConfigs) {
+        for (RicConfig newConfig : parserResult.ricConfigs()) {
             RicConfig oldConfig = this.ricConfigs.get(newConfig.name());
             if (oldConfig == null) {
                 newRicConfigs.put(newConfig.name(), newConfig);
index 059016d..dcfbc64 100644 (file)
@@ -27,8 +27,11 @@ import com.google.gson.JsonObject;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
 import java.util.Set;
@@ -47,6 +50,7 @@ import org.springframework.http.MediaType;
 public class ApplicationConfigParser {
 
     private static final String CONFIG = "config";
+    private static final String CONTROLLER = "controller";
 
     @Value.Immutable
     @Gson.TypeAdapters
@@ -56,6 +60,8 @@ public class ApplicationConfigParser {
         Properties dmaapPublisherConfig();
 
         Properties dmaapConsumerConfig();
+
+        Map<String, ControllerConfig> controllerConfigs();
     }
 
     public ConfigParserResult parse(JsonObject root) throws ServiceException {
@@ -65,6 +71,7 @@ public class ApplicationConfigParser {
 
         JsonObject agentConfigJson = root.getAsJsonObject(CONFIG);
         List<RicConfig> ricConfigs = parseRics(agentConfigJson);
+        Map<String, ControllerConfig> controllerConfigs = parseControllerConfigs(agentConfigJson);
 
         JsonObject json = agentConfigJson.getAsJsonObject("streams_publishes");
         if (json != null) {
@@ -76,27 +83,74 @@ public class ApplicationConfigParser {
             dmaapConsumerConfig = parseDmaapConfig(json);
         }
 
+        checkConfigurationConsistency(ricConfigs, controllerConfigs);
+
         return ImmutableConfigParserResult.builder() //
             .dmaapConsumerConfig(dmaapConsumerConfig) //
             .dmaapPublisherConfig(dmaapPublisherConfig) //
             .ricConfigs(ricConfigs) //
+            .controllerConfigs(controllerConfigs) //
             .build();
     }
 
+    private void checkConfigurationConsistency(List<RicConfig> ricConfigs,
+        Map<String, ControllerConfig> controllerConfigs) throws ServiceException {
+        Set<String> ricUrls = new HashSet<>();
+        Set<String> ricNames = new HashSet<>();
+        for (RicConfig ric : ricConfigs) {
+            if (!ricUrls.add(ric.baseUrl())) {
+                throw new ServiceException("Configuration error, more than one RIC URL: " + ric.baseUrl());
+            }
+            if (!ricNames.add(ric.name())) {
+                throw new ServiceException("Configuration error, more than one RIC with name: " + ric.name());
+            }
+            if (!ric.controllerName().isEmpty() && controllerConfigs.get(ric.controllerName()) == null) {
+                throw new ServiceException(
+                    "Configuration error, controller configuration not found: " + ric.controllerName());
+            }
+
+        }
+
+    }
+
     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);
             ImmutableRicConfig ricConfig = ImmutableRicConfig.builder() //
                 .name(ricAsJson.get("name").getAsString()) //
                 .baseUrl(ricAsJson.get("baseUrl").getAsString()) //
                 .managedElementIds(parseManagedElementIds(ricAsJson.get("managedElementIds").getAsJsonArray())) //
+                .controllerName(controllerNameElement != null ? controllerNameElement.getAsString() : "") //
                 .build();
             result.add(ricConfig);
         }
         return result;
     }
 
+    Map<String, ControllerConfig> parseControllerConfigs(JsonObject config) throws ServiceException {
+        if (config.get(CONTROLLER) == null) {
+            return new HashMap<>();
+        }
+        Map<String, ControllerConfig> result = new HashMap<>();
+        for (JsonElement element : getAsJsonArray(config, CONTROLLER)) {
+            JsonObject controllerAsJson = element.getAsJsonObject();
+            ImmutableControllerConfig controllerConfig = ImmutableControllerConfig.builder() //
+                .name(controllerAsJson.get("name").getAsString()) //
+                .baseUrl(controllerAsJson.get("baseUrl").getAsString()) //
+                .password(controllerAsJson.get("password").getAsString()) //
+                .userName(controllerAsJson.get("userName").getAsString()) // )
+                .build();
+
+            if (result.put(controllerConfig.name(), controllerConfig) != null) {
+                throw new ServiceException(
+                    "Configuration error, more than one controller with name: " + controllerConfig.name());
+            }
+        }
+        return result;
+    }
+
     private List<String> parseManagedElementIds(JsonArray asJsonObject) {
         Iterator<JsonElement> iterator = asJsonObject.iterator();
         List<String> managedElementIds = new ArrayList<>();
diff --git a/policy-agent/src/main/java/org/oransc/policyagent/configuration/ControllerConfig.java b/policy-agent/src/main/java/org/oransc/policyagent/configuration/ControllerConfig.java
new file mode 100644 (file)
index 0000000..fa88d14
--- /dev/null
@@ -0,0 +1,38 @@
+/*-
+ * ========================LICENSE_START=================================
+ * O-RAN-SC
+ * %%
+ * Copyright (C) 2019 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.
+ * ========================LICENSE_END===================================
+ */
+
+package org.oransc.policyagent.configuration;
+
+import org.immutables.value.Value;
+
+@Value.Immutable
+@Value.Style(redactedMask = "####")
+
+public interface ControllerConfig {
+    public String name();
+
+    public String baseUrl();
+
+    public String userName();
+
+    @Value.Redacted
+    public String password();
+
+}
index ab54b52..8de250e 100644 (file)
@@ -28,6 +28,8 @@ import org.immutables.value.Value;
 public interface RicConfig {
     public String name();
 
+    public String controllerName();
+
     public String baseUrl();
 
     public ImmutableList<String> managedElementIds();
index 176dd6c..a6bbeea 100644 (file)
@@ -176,8 +176,7 @@ public class RefreshConfigTask {
     }
 
     private Flux<RicConfigUpdate> updateConfig(ApplicationConfigParser.ConfigParserResult config) {
-        return this.appConfig.setConfiguration(config.ricConfigs(), config.dmaapPublisherConfig(),
-            config.dmaapConsumerConfig());
+        return this.appConfig.setConfiguration(config);
     }
 
     boolean configFileExists() {
index f701ee5..b7e9a4b 100644 (file)
@@ -714,6 +714,7 @@ public class ApplicationTest {
             .name(ricName) //
             .baseUrl(ricName) //
             .managedElementIds(mes) //
+            .controllerName("") //
             .build();
         Ric ric = new Ric(conf);
         ric.setState(Ric.RicState.IDLE);
index 2095470..742734e 100644 (file)
@@ -36,7 +36,10 @@ import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
 import org.oransc.policyagent.configuration.ApplicationConfig;
+import org.oransc.policyagent.configuration.ControllerConfig;
+import org.oransc.policyagent.configuration.ImmutableControllerConfig;
 import org.oransc.policyagent.configuration.ImmutableRicConfig;
+import org.oransc.policyagent.exceptions.ServiceException;
 import org.oransc.policyagent.repository.Ric;
 
 import reactor.core.publisher.Mono;
@@ -62,19 +65,27 @@ public class A1ClientFactoryTest {
     @Mock
     A1Client clientMock4;
 
-    private ImmutableRicConfig ricConfig =
-        ImmutableRicConfig.builder().name(RIC_NAME).baseUrl("baseUrl").managedElementIds(new Vector<>()).build();
-    private Ric ric = new Ric(ricConfig);
-
+    private Ric ric;
     private A1ClientFactory factoryUnderTest;
 
+    private static ImmutableRicConfig ricConfig(String controllerName) {
+        return ImmutableRicConfig.builder() //
+            .name(RIC_NAME) //
+            .baseUrl("baseUrl") //
+            .managedElementIds(new Vector<>()) //
+            .controllerName(controllerName) //
+            .build();
+    }
+
     @BeforeEach
     public void createFactoryUnderTest() {
         factoryUnderTest = spy(new A1ClientFactory(applicationConfigMock));
+        this.ric = new Ric(ricConfig(""));
+
     }
 
     @Test
-    public void getProtocolVersion_ok() {
+    public void getProtocolVersion_ok() throws ServiceException {
         whenGetProtocolVersionThrowException(clientMock1);
         whenGetProtocolVersionReturn(clientMock2, A1ProtocolType.STD_V1_1);
         doReturn(clientMock1, clientMock2).when(factoryUnderTest).createClient(any(), any());
@@ -86,7 +97,7 @@ public class A1ClientFactoryTest {
     }
 
     @Test
-    public void getProtocolVersion_ok_Last() {
+    public void getProtocolVersion_ok_Last() throws ServiceException {
         whenGetProtocolVersionThrowException(clientMock1, clientMock2, clientMock3);
         whenGetProtocolVersionReturn(clientMock4, A1ProtocolType.STD_V1_1);
         doReturn(clientMock1, clientMock2, clientMock3, clientMock4).when(factoryUnderTest).createClient(any(), any());
@@ -98,7 +109,7 @@ public class A1ClientFactoryTest {
     }
 
     @Test
-    public void getProtocolVersion_error() {
+    public void getProtocolVersion_error() throws ServiceException {
         whenGetProtocolVersionThrowException(clientMock1, clientMock2, clientMock3, clientMock4);
         doReturn(clientMock1, clientMock2, clientMock3, clientMock4).when(factoryUnderTest).createClient(any(), any());
 
@@ -110,18 +121,27 @@ public class A1ClientFactoryTest {
         assertEquals(A1ProtocolType.UNKNOWN, ric.getProtocolVersion(), "Not correct protocol");
     }
 
-    private A1Client createClient(A1ProtocolType version) {
+    private A1Client createClient(A1ProtocolType version) throws ServiceException {
         return factoryUnderTest.createClient(ric, version);
     }
 
     @Test
-    public void create_check_types() {
+    public void create_check_types() throws ServiceException {
         assertTrue(createClient(A1ProtocolType.STD_V1_1) instanceof StdA1ClientVersion1);
         assertTrue(createClient(A1ProtocolType.OSC_V1) instanceof OscA1Client);
+    }
+
+    @Test
+    public void create_check_types_controllers() throws ServiceException {
+        this.ric = new Ric(ricConfig("anythingButEmpty"));
+        whenGetGetControllerConfigReturn();
         assertTrue(createClient(A1ProtocolType.SDNC_ONAP) instanceof SdncOnapA1Client);
+
+        whenGetGetControllerConfigReturn();
         assertTrue(createClient(A1ProtocolType.SDNC_OSC_STD_V1_1) instanceof SdncOscA1Client);
+
+        whenGetGetControllerConfigReturn();
         assertTrue(createClient(A1ProtocolType.SDNC_OSC_OSC_V1) instanceof SdncOscA1Client);
-        assertTrue(createClient(A1ProtocolType.UNKNOWN) == null);
     }
 
     private void whenGetProtocolVersionThrowException(A1Client... clientMocks) {
@@ -134,4 +154,14 @@ public class A1ClientFactoryTest {
         when(clientMock.getProtocolVersion()).thenReturn(Mono.just(protocol));
     }
 
+    private void whenGetGetControllerConfigReturn() throws ServiceException {
+        ControllerConfig controllerCfg = ImmutableControllerConfig.builder() //
+            .name("name") //
+            .baseUrl("baseUrl") //
+            .password("pass") //
+            .userName("user") //
+            .build();
+        when(applicationConfigMock.getControllerConfig(any())).thenReturn(controllerCfg);
+    }
+
 }
index c5a6b4c..1855949 100644 (file)
@@ -63,6 +63,7 @@ public class A1ClientHelper {
         RicConfig cfg = ImmutableRicConfig.builder().name("ric") //
             .baseUrl(url) //
             .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
+            .controllerName("") //
             .build();
         return new Ric(cfg);
     }
index 5023d10..b66340b 100644 (file)
@@ -70,6 +70,7 @@ public class OscA1ClientTest {
             .name("name") //
             .baseUrl("RicBaseUrl") //
             .managedElementIds(new ArrayList<>()) //
+            .controllerName("") //
             .build();
         asyncRestClientMock = mock(AsyncRestClient.class);
         clientUnderTest = new OscA1Client(ricConfig, asyncRestClientMock);
index ede6594..20bbf48 100644 (file)
@@ -35,6 +35,8 @@ import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.mockito.stubbing.OngoingStubbing;
+import org.oransc.policyagent.configuration.ControllerConfig;
+import org.oransc.policyagent.configuration.ImmutableControllerConfig;
 
 import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
@@ -66,8 +68,15 @@ public class SdncOnapA1ClientTest {
     @BeforeEach
     public void init() {
         asyncRestClientMock = mock(AsyncRestClient.class);
-        clientUnderTest = new SdncOnapA1Client(A1ClientHelper.createRic(RIC_1_URL).getConfig(), CONTROLLER_USERNAME,
-            CONTROLLER_PASSWORD, asyncRestClientMock);
+        ControllerConfig controllerCfg = ImmutableControllerConfig.builder() //
+            .name("name") //
+            .baseUrl("baseUrl") //
+            .password(CONTROLLER_PASSWORD) //
+            .userName(CONTROLLER_USERNAME) //
+            .build();
+
+        clientUnderTest =
+            new SdncOnapA1Client(A1ClientHelper.createRic(RIC_1_URL).getConfig(), controllerCfg, asyncRestClientMock);
     }
 
     @Test
index e463cae..cba60e7 100644 (file)
@@ -39,6 +39,8 @@ import org.mockito.stubbing.OngoingStubbing;
 import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
 import org.oransc.policyagent.clients.SdncOscA1Client.AdapterRequest;
 import org.oransc.policyagent.clients.SdncOscA1Client.AdapterResponse;
+import org.oransc.policyagent.configuration.ControllerConfig;
+import org.oransc.policyagent.configuration.ImmutableControllerConfig;
 import org.oransc.policyagent.repository.Policy;
 import org.oransc.policyagent.repository.Ric;
 import org.springframework.web.reactive.function.client.WebClientResponseException;
@@ -64,12 +66,22 @@ public class SdncOscA1ClientTest {
 
     AsyncRestClient asyncRestClientMock;
 
+    private ControllerConfig controllerConfig() {
+        return ImmutableControllerConfig.builder() //
+            .name("name") //
+            .baseUrl("baseUrl") //
+            .password(CONTROLLER_PASSWORD) //
+            .userName(CONTROLLER_USERNAME) //
+            .build();
+    }
+
     @BeforeEach
     public void init() {
         asyncRestClientMock = mock(AsyncRestClient.class);
         Ric ric = A1ClientHelper.createRic(RIC_1_URL);
-        clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_STD_V1_1, ric.getConfig(), CONTROLLER_USERNAME,
-            CONTROLLER_PASSWORD, asyncRestClientMock);
+
+        clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_STD_V1_1, ric.getConfig(), controllerConfig(),
+            asyncRestClientMock);
     }
 
     @Test
@@ -83,7 +95,7 @@ public class SdncOscA1ClientTest {
     public void testGetPolicyTypeIdentities_OSC() {
         clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_OSC_V1, //
             A1ClientHelper.createRic(RIC_1_URL).getConfig(), //
-            CONTROLLER_USERNAME, CONTROLLER_PASSWORD, asyncRestClientMock);
+            controllerConfig(), asyncRestClientMock);
 
         String response = createResponse(Arrays.asList(POLICY_TYPE_1_ID));
         whenAsyncPostThenReturn(Mono.just(response));
index 47448d2..3303e3f 100644 (file)
@@ -39,6 +39,7 @@ import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.StandardCharsets;
+import java.util.Map;
 import java.util.Properties;
 
 import org.junit.jupiter.api.Test;
@@ -51,7 +52,7 @@ public class ApplicationConfigParserTest {
     ApplicationConfigParser parserUnderTest = new ApplicationConfigParser();
 
     @Test
-    public void whenCorrectDmaapConfig() throws Exception {
+    public void whenCorrectConfig() throws Exception {
         JsonObject jsonRootObject = getJsonRootObject();
 
         ApplicationConfigParser.ConfigParserResult result = parserUnderTest.parse(jsonRootObject);
@@ -85,6 +86,16 @@ public class ApplicationConfigParserTest {
                 "Wrong TransportType"),
             () -> assertEquals(15000, actualConsumerConfig.get("timeout"), "Wrong timeout"),
             () -> assertEquals(100, actualConsumerConfig.get("limit"), "Wrong limit"));
+
+        Map<String, ControllerConfig> controllers = result.controllerConfigs();
+        assertEquals(1, controllers.size(), "size");
+        ImmutableControllerConfig expectedControllerConfig = ImmutableControllerConfig.builder() //
+            .baseUrl("http://localhost:8083/") //
+            .name("controller1") //
+            .userName("user") //
+            .password("password") //
+            .build(); //
+        assertEquals(expectedControllerConfig, controllers.get("controller1"), "controller contents");
     }
 
     private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException {
index d30e95a..27b9c87 100644 (file)
@@ -25,12 +25,15 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Properties;
 import java.util.Vector;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.oransc.policyagent.configuration.ApplicationConfig.RicConfigUpdate;
+import org.oransc.policyagent.configuration.ApplicationConfigParser.ConfigParserResult;
 import org.oransc.policyagent.exceptions.ServiceException;
 
 @ExtendWith(MockitoExtension.class)
@@ -40,27 +43,36 @@ public class ApplicationConfigTest {
         .name("ric1") //
         .baseUrl("ric1_url") //
         .managedElementIds(new Vector<>()) //
+        .controllerName("") //
         .build();
 
+    ConfigParserResult configParserResult(RicConfig... rics) {
+        return ImmutableConfigParserResult.builder() //
+            .ricConfigs(Arrays.asList(rics)) //
+            .dmaapConsumerConfig(new Properties()) //
+            .dmaapPublisherConfig(new Properties()) //
+            .controllerConfigs(new HashMap<>()) //
+            .build();
+    }
+
     @Test
     public void gettingNotAddedRicShouldThrowException() {
         ApplicationConfig appConfigUnderTest = new ApplicationConfig();
 
-        appConfigUnderTest.setConfiguration(Arrays.asList(RIC_CONFIG_1), null, null);
+        appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1));
 
         Exception exception = assertThrows(ServiceException.class, () -> {
             appConfigUnderTest.getRic("name");
         });
 
-        assertEquals("Could not find ric: name", exception.getMessage());
+        assertEquals("Could not find ric configuration: name", exception.getMessage());
     }
 
     @Test
     public void addRicShouldNotifyAllObserversOfRicAdded() throws Exception {
         ApplicationConfig appConfigUnderTest = new ApplicationConfig();
 
-        RicConfigUpdate update =
-            appConfigUnderTest.setConfiguration(Arrays.asList(RIC_CONFIG_1), null, null).blockFirst();
+        RicConfigUpdate update = appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1)).blockFirst();
         assertEquals(RicConfigUpdate.Type.ADDED, update.getType());
         assertTrue(appConfigUnderTest.getRicConfigs().contains(RIC_CONFIG_1), "Ric not added to configurations.");
 
@@ -72,16 +84,16 @@ public class ApplicationConfigTest {
     public void changedRicShouldNotifyAllObserversOfRicChanged() throws Exception {
         ApplicationConfig appConfigUnderTest = new ApplicationConfig();
 
-        appConfigUnderTest.setConfiguration(Arrays.asList(RIC_CONFIG_1), null, null);
+        appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1));
 
         ImmutableRicConfig changedRicConfig = ImmutableRicConfig.builder() //
             .name("ric1") //
             .baseUrl("changed_ric1_url") //
             .managedElementIds(new Vector<>()) //
+            .controllerName("") //
             .build();
 
-        RicConfigUpdate update =
-            appConfigUnderTest.setConfiguration(Arrays.asList(changedRicConfig), null, null).blockFirst();
+        RicConfigUpdate update = appConfigUnderTest.setConfiguration(configParserResult(changedRicConfig)).blockFirst();
 
         assertEquals(RicConfigUpdate.Type.CHANGED, update.getType());
         assertEquals(changedRicConfig, appConfigUnderTest.getRic(RIC_CONFIG_1.name()),
@@ -96,12 +108,12 @@ public class ApplicationConfigTest {
             .name("ric2") //
             .baseUrl("ric2_url") //
             .managedElementIds(new Vector<>()) //
+            .controllerName("") //
             .build();
 
-        appConfigUnderTest.setConfiguration(Arrays.asList(RIC_CONFIG_1, ricConfig2), null, null);
+        appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1, ricConfig2));
 
-        RicConfigUpdate update =
-            appConfigUnderTest.setConfiguration(Arrays.asList(ricConfig2), null, null).blockFirst();
+        RicConfigUpdate update = appConfigUnderTest.setConfiguration(configParserResult(ricConfig2)).blockFirst();
 
         assertEquals(RicConfigUpdate.Type.REMOVED, update.getType());
         assertEquals(1, appConfigUnderTest.getRicConfigs().size(), "Ric not deleted from configurations.");
index f81962d..1c4b21d 100644 (file)
@@ -50,6 +50,7 @@ import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Properties;
 import java.util.Vector;
 
@@ -65,6 +66,8 @@ import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.configuration.ApplicationConfig.RicConfigUpdate.Type;
 import org.oransc.policyagent.configuration.ApplicationConfigParser;
+import org.oransc.policyagent.configuration.ApplicationConfigParser.ConfigParserResult;
+import org.oransc.policyagent.configuration.ImmutableConfigParserResult;
 import org.oransc.policyagent.configuration.ImmutableRicConfig;
 import org.oransc.policyagent.configuration.RicConfig;
 import org.oransc.policyagent.repository.ImmutablePolicy;
@@ -100,6 +103,7 @@ public class RefreshConfigTaskTest {
         .name(RIC_1_NAME) //
         .baseUrl("http://localhost:8080/") //
         .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
+        .controllerName("") //
         .build();
 
     private static EnvProperties properties() {
@@ -246,7 +250,7 @@ public class RefreshConfigTaskTest {
         RicConfig removedRicConfig = getRicConfig("removed");
         Ric removedRic = new Ric(removedRicConfig);
         rics.put(removedRic);
-        appConfig.setConfiguration(Arrays.asList(changedRicConfig, removedRicConfig), null, null);
+        appConfig.setConfiguration(configParserResult(changedRicConfig, removedRicConfig));
 
         Policy policy = getPolicy(removedRic);
         policies.put(policy);
@@ -289,6 +293,7 @@ public class RefreshConfigTaskTest {
             .name(name) //
             .baseUrl("url") //
             .managedElementIds(Collections.emptyList()) //
+            .controllerName("controllerName") //
             .build();
         return ricConfig;
     }
@@ -309,9 +314,19 @@ public class RefreshConfigTaskTest {
         return policy;
     }
 
+    ConfigParserResult configParserResult(RicConfig... rics) {
+        return ImmutableConfigParserResult.builder() //
+            .ricConfigs(Arrays.asList(rics)) //
+            .dmaapConsumerConfig(new Properties()) //
+            .dmaapPublisherConfig(new Properties()) //
+            .controllerConfigs(new HashMap<>()) //
+            .build();
+    }
+
     private void modifyTheRicConfiguration(JsonObject configAsJson, String newBaseUrl) {
-        ((JsonObject) configAsJson.getAsJsonObject("config").getAsJsonArray("ric").get(0)).addProperty("baseUrl",
-            newBaseUrl);
+        ((JsonObject) configAsJson.getAsJsonObject("config") //
+            .getAsJsonArray("ric").get(0)) //
+                .addProperty("baseUrl", newBaseUrl);
     }
 
     private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException {
index 7aef0c0..3f8dd06 100644 (file)
@@ -67,6 +67,7 @@ public class RicSupervisionTest {
         .name("RIC_1") //
         .baseUrl("baseUrl1") //
         .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
+        .controllerName("controllerName") //
         .build());
 
     private static final String POLICY_1_ID = "policyId1";
index e0ce2ef..788253c 100644 (file)
@@ -77,6 +77,7 @@ public class RicSynchronizationTaskTest {
         .name(RIC_1_NAME) //
         .baseUrl("baseUrl1") //
         .managedElementIds(Collections.emptyList()) //
+        .controllerName("controllerName") //
         .build());
 
     private static final Policy POLICY_1 = ImmutablePolicy.builder() //
index 070e8da..8961615 100644 (file)
@@ -74,6 +74,7 @@ public class ServiceSupervisionTest {
         .name(RIC_NAME) //
         .baseUrl("baseUrl") //
         .managedElementIds(Collections.emptyList()) //
+        .controllerName("") //
         .build();
     private Ric ric = new Ric(ricConfig);
     private PolicyType policyType = ImmutablePolicyType.builder() //
index ec292bf..6d6cdce 100644 (file)
@@ -1,8 +1,17 @@
 {
    "config":{
+      "controller":[
+         {
+          "name":"controller1",
+          "baseUrl":"http://localhost:8083/",
+          "userName":"user",
+          "password":"password"
+        }
+      ],
       "ric":[
          {
             "name":"ric1",
+            "controller": "controller1",
             "baseUrl":"http://localhost:8083/",
             "managedElementIds":[
                "kista_1",
@@ -35,4 +44,4 @@
          }
       }
    }
-}
\ No newline at end of file
+}