Infrastructure for having mutiple RIC APIs 93/2293/4
authorPatrikBuhr <patrik.buhr@est.tech>
Mon, 20 Jan 2020 12:27:40 +0000 (13:27 +0100)
committerPatrikBuhr <patrik.buhr@est.tech>
Wed, 22 Jan 2020 12:24:31 +0000 (13:24 +0100)
RIC (A1) protocol is selected by confuration parameter.

Change-Id: I5486955cea9f38b3bb9e6ce3e88d94206bb85a1c
Issue-ID: NONRTRIC-84
Signed-off-by: PatrikBuhr <patrik.buhr@est.tech>
23 files changed:
policy-agent/src/main/java/org/oransc/policyagent/BeanFactory.java
policy-agent/src/main/java/org/oransc/policyagent/clients/A1Client.java
policy-agent/src/main/java/org/oransc/policyagent/clients/A1ClientFactory.java [new file with mode: 0644]
policy-agent/src/main/java/org/oransc/policyagent/clients/OscA1Client.java [new file with mode: 0644]
policy-agent/src/main/java/org/oransc/policyagent/clients/StdA1Client.java [moved from policy-agent/src/main/java/org/oransc/policyagent/clients/A1ClientImpl.java with 67% similarity]
policy-agent/src/main/java/org/oransc/policyagent/configuration/ApplicationConfig.java
policy-agent/src/main/java/org/oransc/policyagent/configuration/RicConfig.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/PolicyController.java
policy-agent/src/main/java/org/oransc/policyagent/controllers/RicRepositoryController.java
policy-agent/src/main/java/org/oransc/policyagent/repository/Ric.java
policy-agent/src/main/java/org/oransc/policyagent/repository/Rics.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RepositorySupervision.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/RicRecoveryTask.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/ServiceSupervision.java
policy-agent/src/main/java/org/oransc/policyagent/tasks/StartupService.java
policy-agent/src/test/java/org/oransc/policyagent/ApplicationTest.java
policy-agent/src/test/java/org/oransc/policyagent/MockPolicyAgent.java
policy-agent/src/test/java/org/oransc/policyagent/clients/StdA1ClientTest.java [moved from policy-agent/src/test/java/org/oransc/policyagent/clients/A1ClientImplTest.java with 91% similarity]
policy-agent/src/test/java/org/oransc/policyagent/tasks/RepositorySupervisionTest.java
policy-agent/src/test/java/org/oransc/policyagent/tasks/StartupServiceTest.java
policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1Client.java
policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1ClientFactory.java [new file with mode: 0644]
policy-agent/src/test/resources/test_application_configuration.json

index 06b66ca..f0826e9 100644 (file)
@@ -20,8 +20,7 @@
 
 package org.oransc.policyagent;
 
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientImpl;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyTypes;
@@ -58,8 +57,8 @@ class BeanFactory {
     }
 
     @Bean
-    A1Client getA1Client() {
-        return new A1ClientImpl();
+    A1ClientFactory getA1ClientFactory() {
+        return new A1ClientFactory();
     }
 
 }
index 8d244ee..31b5142 100644 (file)
@@ -27,14 +27,20 @@ import reactor.core.publisher.Mono;
 
 public interface A1Client {
 
-    public Mono<Collection<String>> getPolicyTypeIdentities(String nearRtRicUrl);
+    public static enum A1ProtocolType {
+        UNKNOWN, STD_V1
+    }
 
-    public Mono<Collection<String>> getPolicyIdentities(String nearRtRicUrl);
+    public Mono<A1ProtocolType> getProtocolVersion();
 
-    public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId);
+    public Mono<Collection<String>> getPolicyTypeIdentities();
+
+    public Mono<Collection<String>> getPolicyIdentities();
+
+    public Mono<String> getPolicyTypeSchema(String policyTypeId);
 
     public Mono<String> putPolicy(Policy policy);
 
-    public Mono<String> deletePolicy(String nearRtRicUrl, String policyId);
+    public Mono<String> deletePolicy(String policyId);
 
 }
diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/A1ClientFactory.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/A1ClientFactory.java
new file mode 100644 (file)
index 0000000..a3d17bc
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ========================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.clients;
+
+import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
+import org.oransc.policyagent.exceptions.ServiceException;
+import org.oransc.policyagent.repository.Ric;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Mono;
+
+public class A1ClientFactory {
+
+    private static final Logger logger = LoggerFactory.getLogger(A1ClientFactory.class);
+
+    public Mono<A1Client> createA1Client(Ric ric) {
+        return getProtocolVersion(ric) //
+            .flatMap(version -> createA1Client(ric, version));
+    }
+
+    private Mono<A1Client> createA1Client(Ric ric, A1ProtocolType version) {
+        if (version == A1ProtocolType.STD_V1) {
+            return Mono.just(createStdA1ClientImpl(ric));
+        }
+        return Mono.error(new ServiceException("Not supported protocoltype: " + version));
+    }
+
+    private Mono<A1Client.A1ProtocolType> getProtocolVersion(Ric ric) {
+        if (ric.getProtocolVersion() == A1ProtocolType.UNKNOWN) {
+            return fetchVersion(ric, new OscA1Client(ric.getConfig())) //
+                .onErrorResume(err -> fetchVersion(ric, createStdA1ClientImpl(ric)))
+                .doOnNext(version -> ric.setProtocolVersion(version))
+                .doOnNext(version -> logger.debug("Recover ric: {}, protocol version:{}", ric.name(), version)) //
+                .doOnError(t -> logger.warn("Could not get protocol version from RIC: {}", ric.name())); //
+        } else {
+            return Mono.just(ric.getProtocolVersion());
+        }
+    }
+
+    protected A1Client createStdA1ClientImpl(Ric ric) {
+        return new StdA1Client(ric.getConfig());
+    }
+
+    private Mono<A1Client.A1ProtocolType> fetchVersion(Ric ric, A1Client a1Client) {
+        return Mono.just(a1Client) //
+            .flatMap(client -> a1Client.getProtocolVersion());
+    }
+
+}
diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/OscA1Client.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/OscA1Client.java
new file mode 100644 (file)
index 0000000..273f27b
--- /dev/null
@@ -0,0 +1,72 @@
+/*-
+ * ========================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.clients;
+
+import java.lang.invoke.MethodHandles;
+import java.util.Collection;
+
+import org.oransc.policyagent.configuration.RicConfig;
+import org.oransc.policyagent.repository.Policy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import reactor.core.publisher.Mono;
+
+public class OscA1Client implements A1Client {
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+    private final RicConfig ricConfig;
+
+    public OscA1Client(RicConfig ricConfig) {
+        this.ricConfig = ricConfig;
+        logger.debug("OscA1Client for ric: {}", this.ricConfig.name());
+    }
+
+    @Override
+    public Mono<Collection<String>> getPolicyTypeIdentities() {
+        return Mono.error(new Exception("Not impl"));
+    }
+
+    @Override
+    public Mono<Collection<String>> getPolicyIdentities() {
+        return Mono.error(new Exception("Not impl"));
+    }
+
+    @Override
+    public Mono<String> getPolicyTypeSchema(String policyTypeId) {
+        return Mono.error(new Exception("Not impl"));
+    }
+
+    @Override
+    public Mono<String> putPolicy(Policy policy) {
+        return Mono.error(new Exception("Not impl"));
+    }
+
+    @Override
+    public Mono<String> deletePolicy(String policyId) {
+        return Mono.error(new Exception("Not impl"));
+    }
+
+    @Override
+    public Mono<A1ProtocolType> getProtocolVersion() {
+        return Mono.error(new Exception("Not impl"));
+    }
+
+}
@@ -28,43 +28,46 @@ import java.util.List;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
+import org.oransc.policyagent.configuration.RicConfig;
 import org.oransc.policyagent.repository.Policy;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import reactor.core.publisher.Mono;
 
-public class A1ClientImpl implements A1Client {
+public class StdA1Client implements A1Client {
     private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
-    private static String getBaseUrl(final String nearRtRicUrl) {
-        return nearRtRicUrl + "/A1-P/v1";
+    private final RicConfig ricConfig;
+    private final AsyncRestClient restClient;
+
+    public StdA1Client(RicConfig ricConfig) {
+        this.ricConfig = ricConfig;
+        this.restClient = new AsyncRestClient(getBaseUrl());
     }
 
-    protected AsyncRestClient createClient(final String nearRtRicUrl) {
-        return new AsyncRestClient(getBaseUrl(nearRtRicUrl));
+    public StdA1Client(RicConfig ricConfig, AsyncRestClient restClient) {
+        this.ricConfig = ricConfig;
+        this.restClient = restClient;
     }
 
     @Override
-    public Mono<Collection<String>> getPolicyTypeIdentities(String nearRtRicUrl) {
-        logger.debug("getPolicyTypeIdentities nearRtRicUrl = {}", nearRtRicUrl);
-        AsyncRestClient client = createClient(nearRtRicUrl);
-        return client.get("/policytypes/identities") //
+    public Mono<Collection<String>> getPolicyTypeIdentities() {
+        logger.debug("getPolicyTypeIdentities nearRtRicUrl = {}", ricConfig.baseUrl());
+        return restClient.get("/policytypes/identities") //
             .flatMap(this::parseJsonArrayOfString);
     }
 
     @Override
-    public Mono<Collection<String>> getPolicyIdentities(String nearRtRicUrl) {
-        logger.debug("getPolicyIdentities nearRtRicUrl = {}", nearRtRicUrl);
-        AsyncRestClient client = createClient(nearRtRicUrl);
-        return client.get("/policies/identities") //
+    public Mono<Collection<String>> getPolicyIdentities() {
+        logger.debug("getPolicyIdentities nearRtRicUrl = {}", ricConfig.baseUrl());
+        return restClient.get("/policies/identities") //
             .flatMap(this::parseJsonArrayOfString);
     }
 
     @Override
-    public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId) {
-        logger.debug("getPolicyType nearRtRicUrl = {}, policyTypeId = {}", nearRtRicUrl, policyTypeId);
-        AsyncRestClient client = createClient(nearRtRicUrl);
-        Mono<String> response = client.get("/policytypes/" + policyTypeId);
+    public Mono<String> getPolicyTypeSchema(String policyTypeId) {
+        logger.debug("getPolicyType nearRtRicUrl = {}, policyTypeId = {}", ricConfig.baseUrl(), policyTypeId);
+        Mono<String> response = restClient.get("/policytypes/" + policyTypeId);
         return response.flatMap(this::createMono);
     }
 
@@ -72,20 +75,28 @@ public class A1ClientImpl implements A1Client {
     public Mono<String> putPolicy(Policy policy) {
         logger.debug("putPolicy nearRtRicUrl = {}, policyId = {}, policyString = {}", //
             policy.ric().getConfig().baseUrl(), policy.id(), policy.json());
-        AsyncRestClient client = createClient(policy.ric().getConfig().baseUrl());
         // TODO update when simulator is updated to include policy type
         // Mono<String> response = client.put("/policies/" + policy.id() + "?policyTypeId=" + policy.type().name(),
         // policy.json());
-        Mono<String> response = client.put("/policies/" + policy.id(), policy.json());
+        Mono<String> response = restClient.put("/policies/" + policy.id(), policy.json());
 
         return response.flatMap(this::createMono);
     }
 
     @Override
-    public Mono<String> deletePolicy(String nearRtRicUrl, String policyId) {
-        logger.debug("deletePolicy nearRtRicUrl = {}, policyId = {}", nearRtRicUrl, policyId);
-        AsyncRestClient client = createClient(nearRtRicUrl);
-        return client.delete("/policies/" + policyId);
+    public Mono<String> deletePolicy(String policyId) {
+        logger.debug("deletePolicy nearRtRicUrl = {}, policyId = {}", ricConfig.baseUrl(), policyId);
+        return restClient.delete("/policies/" + policyId);
+    }
+
+    @Override
+    public Mono<A1ProtocolType> getProtocolVersion() {
+        return getPolicyTypeIdentities() //
+            .flatMap(x -> Mono.just(A1ProtocolType.STD_V1));
+    }
+
+    private String getBaseUrl() {
+        return ricConfig.baseUrl() + "/A1-P/v1";
     }
 
     private Mono<Collection<String>> parseJsonArrayOfString(String inputString) {
@@ -112,4 +123,5 @@ public class A1ClientImpl implements A1Client {
             return Mono.error(ex);
         }
     }
+
 }
index fee0181..d4f7261 100644 (file)
@@ -23,7 +23,6 @@ package org.oransc.policyagent.configuration;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Optional;
 import java.util.Vector;
 
 import javax.validation.constraints.NotEmpty;
@@ -51,23 +50,10 @@ public class ApplicationConfig {
         return this.filepath;
     }
 
-    public synchronized void setFilepath(String filepath) {
-        this.filepath = filepath;
-    }
-
     public synchronized Collection<RicConfig> getRicConfigs() {
         return this.ricConfigs.values();
     }
 
-    public synchronized Optional<RicConfig> lookupRicConfigForManagedElement(String managedElementId) {
-        for (RicConfig ricConfig : getRicConfigs()) {
-            if (ricConfig.managedElementIds().contains(managedElementId)) {
-                return Optional.of(ricConfig);
-            }
-        }
-        return Optional.empty();
-    }
-
     public RicConfig getRic(String ricName) throws ServiceException {
         for (RicConfig ricConfig : getRicConfigs()) {
             if (ricConfig.name().equals(ricName)) {
index affce2c..1b2ebb4 100644 (file)
@@ -31,7 +31,7 @@ import io.swagger.annotations.ApiResponses;
 import java.util.Collection;
 import java.util.Vector;
 
-import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.exceptions.ServiceException;
 import org.oransc.policyagent.repository.ImmutablePolicy;
@@ -59,18 +59,19 @@ public class PolicyController {
     private final Rics rics;
     private final PolicyTypes policyTypes;
     private final Policies policies;
-    private final A1Client a1Client;
+    private final A1ClientFactory a1ClientFactory;
 
     private static Gson gson = new GsonBuilder() //
         .serializeNulls() //
         .create(); //
 
     @Autowired
-    PolicyController(ApplicationConfig config, PolicyTypes types, Policies policies, Rics rics, A1Client a1Client) {
+    PolicyController(ApplicationConfig config, PolicyTypes types, Policies policies, Rics rics,
+        A1ClientFactory a1ClientFactory) {
         this.policyTypes = types;
         this.policies = policies;
         this.rics = rics;
-        this.a1Client = a1Client;
+        this.a1ClientFactory = a1ClientFactory;
     }
 
     @GetMapping("/policy_schemas")
@@ -146,7 +147,8 @@ public class PolicyController {
         Policy policy = policies.get(id);
         if (policy != null && policy.ric().state().equals(Ric.RicState.IDLE)) {
             policies.remove(policy);
-            return a1Client.deletePolicy(policy.ric().getConfig().baseUrl(), id) //
+            return a1ClientFactory.createA1Client(policy.ric()) //
+                .flatMap(client -> client.deletePolicy(id)) //
                 .flatMap(notUsed -> {
                     return Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT));
                 });
@@ -176,7 +178,8 @@ public class PolicyController {
                 .ownerServiceName(service) //
                 .lastModified(getTimeStampUTC()) //
                 .build();
-            return a1Client.putPolicy(policy) //
+            return a1ClientFactory.createA1Client(ric) //
+                .flatMap(client -> client.putPolicy(policy)) //
                 .doOnNext(notUsed -> policies.put(policy)) //
                 .flatMap(notUsed -> {
                     return Mono.just(new ResponseEntity<>(HttpStatus.CREATED));
index 6b413b2..0d49833 100644 (file)
@@ -32,7 +32,6 @@ import java.util.Optional;
 import java.util.Vector;
 
 import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.configuration.RicConfig;
 import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Rics;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,8 +45,6 @@ import org.springframework.web.bind.annotation.RestController;
 @Api(value = "RIC Management API")
 public class RicRepositoryController {
 
-    private final ApplicationConfig appConfig;
-
     @Autowired
     private Rics rics;
 
@@ -57,7 +54,6 @@ public class RicRepositoryController {
 
     @Autowired
     RicRepositoryController(ApplicationConfig appConfig) {
-        this.appConfig = appConfig;
     }
 
     /**
@@ -73,10 +69,10 @@ public class RicRepositoryController {
     public ResponseEntity<String> getRic(
         @RequestParam(name = "managedElementId", required = false, defaultValue = "") String managedElementId) {
 
-        Optional<RicConfig> config = appConfig.lookupRicConfigForManagedElement(managedElementId);
+        Optional<Ric> ric = this.rics.lookupRicForManagedElement(managedElementId);
 
-        if (config.isPresent()) {
-            return new ResponseEntity<>(config.get().name(), HttpStatus.OK);
+        if (ric.isPresent()) {
+            return new ResponseEntity<>(ric.get().name(), HttpStatus.OK);
         } else {
             return new ResponseEntity<>("", HttpStatus.NOT_FOUND);
         }
index 235ee1a..4169150 100644 (file)
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Vector;
 
+import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
 import org.oransc.policyagent.configuration.RicConfig;
 
 /**
@@ -34,6 +35,7 @@ public class Ric {
     private final RicConfig ricConfig;
     private RicState state = RicState.UNDEFINED;
     private Map<String, PolicyType> supportedPolicyTypes = new HashMap<>();
+    private A1ProtocolType protocolVersion = A1ProtocolType.UNKNOWN;
 
     /**
      * Creates the Ric. Initial state is {@link RicState.NOT_INITIATED}.
@@ -162,4 +164,14 @@ public class Ric {
          */
         RECOVERING
     }
+
+    public A1ProtocolType getProtocolVersion() {
+        return protocolVersion;
+    }
+
+    public void setProtocolVersion(A1ProtocolType version) {
+        protocolVersion = version;
+
+    }
+
 }
index bdf9930..6f3b3e8 100644 (file)
@@ -22,6 +22,7 @@ package org.oransc.policyagent.repository;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 
 import org.oransc.policyagent.exceptions.ServiceException;
 
@@ -62,4 +63,13 @@ public class Rics {
     public synchronized void clear() {
         this.rics.clear();
     }
+
+    public synchronized Optional<Ric> lookupRicForManagedElement(String managedElementId) {
+        for (Ric ric : this.rics.values()) {
+            if (ric.getConfig().managedElementIds().contains(managedElementId)) {
+                return Optional.of(ric);
+            }
+        }
+        return Optional.empty();
+    }
 }
index 1a90382..022ca0f 100644 (file)
@@ -23,6 +23,7 @@ package org.oransc.policyagent.tasks;
 import java.util.Collection;
 
 import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Ric;
@@ -50,15 +51,15 @@ public class RepositorySupervision {
     private final Rics rics;
     private final Policies policies;
     private final PolicyTypes policyTypes;
-    private final A1Client a1Client;
+    private final A1ClientFactory a1ClientFactory;
     private final Services services;
 
     @Autowired
-    public RepositorySupervision(Rics rics, Policies policies, A1Client a1Client, PolicyTypes policyTypes,
+    public RepositorySupervision(Rics rics, Policies policies, A1ClientFactory a1ClientFactory, PolicyTypes policyTypes,
         Services services) {
         this.rics = rics;
         this.policies = policies;
-        this.a1Client = a1Client;
+        this.a1ClientFactory = a1ClientFactory;
         this.policyTypes = policyTypes;
         this.services = services;
     }
@@ -72,34 +73,51 @@ public class RepositorySupervision {
         createTask().subscribe(this::onRicChecked, this::onError, this::onComplete);
     }
 
-    private Flux<Ric> createTask() {
+    private Flux<RicData> createTask() {
         synchronized (this.rics) {
             return Flux.fromIterable(rics.getRics()) //
-                .flatMap(ric -> checkRicState(ric)) //
-                .flatMap(ric -> checkRicPolicies(ric)) //
-                .flatMap(ric -> checkRicPolicyTypes(ric));
+                .flatMap(ric -> createRicData(ric)) //
+                .flatMap(ricData -> checkRicState(ricData)) //
+                .flatMap(ricData -> checkRicPolicies(ricData)) //
+                .flatMap(ricData -> checkRicPolicyTypes(ricData));
         }
     }
 
-    private Mono<Ric> checkRicState(Ric ric) {
-        if (ric.state() == RicState.UNDEFINED) {
+    private static class RicData {
+        RicData(Ric ric, A1Client a1Client) {
+            this.ric = ric;
+            this.a1Client = a1Client;
+        }
+
+        final Ric ric;
+        final A1Client a1Client;
+    }
+
+    private Mono<RicData> createRicData(Ric ric) {
+        return Mono.just(ric) //
+            .flatMap(aRic -> this.a1ClientFactory.createA1Client(ric)) //
+            .flatMap(a1Client -> Mono.just(new RicData(ric, a1Client)));
+    }
+
+    private Mono<RicData> checkRicState(RicData ric) {
+        if (ric.ric.state() == RicState.UNDEFINED) {
             return startRecovery(ric);
-        } else if (ric.state() == RicState.RECOVERING) {
+        } else if (ric.ric.state() == RicState.RECOVERING) {
             return Mono.empty();
         } else {
             return Mono.just(ric);
         }
     }
 
-    private Mono<Ric> checkRicPolicies(Ric ric) {
-        return a1Client.getPolicyIdentities(ric.getConfig().baseUrl()) //
+    private Mono<RicData> checkRicPolicies(RicData ric) {
+        return ric.a1Client.getPolicyIdentities() //
             .onErrorResume(t -> Mono.empty()) //
             .flatMap(ricP -> validateInstances(ricP, ric));
     }
 
-    private Mono<Ric> validateInstances(Collection<String> ricPolicies, Ric ric) {
+    private Mono<RicData> validateInstances(Collection<String> ricPolicies, RicData ric) {
         synchronized (this.policies) {
-            if (ricPolicies.size() != policies.getForRic(ric.name()).size()) {
+            if (ricPolicies.size() != policies.getForRic(ric.ric.name()).size()) {
                 return startRecovery(ric);
             }
         }
@@ -111,34 +129,34 @@ public class RepositorySupervision {
         return Mono.just(ric);
     }
 
-    private Mono<Ric> checkRicPolicyTypes(Ric ric) {
-        return a1Client.getPolicyTypeIdentities(ric.getConfig().baseUrl()) //
+    private Mono<RicData> checkRicPolicyTypes(RicData ric) {
+        return ric.a1Client.getPolicyTypeIdentities() //
             .onErrorResume(t -> {
                 return Mono.empty();
             }) //
             .flatMap(ricTypes -> validateTypes(ricTypes, ric));
     }
 
-    private Mono<Ric> validateTypes(Collection<String> ricTypes, Ric ric) {
-        if (ricTypes.size() != ric.getSupportedPolicyTypes().size()) {
+    private Mono<RicData> validateTypes(Collection<String> ricTypes, RicData ric) {
+        if (ricTypes.size() != ric.ric.getSupportedPolicyTypes().size()) {
             return startRecovery(ric);
         }
         for (String typeName : ricTypes) {
-            if (!ric.isSupportingType(typeName)) {
+            if (!ric.ric.isSupportingType(typeName)) {
                 return startRecovery(ric);
             }
         }
         return Mono.just(ric);
     }
 
-    private Mono<Ric> startRecovery(Ric ric) {
-        RicRecoveryTask recovery = new RicRecoveryTask(a1Client, policyTypes, policies, services);
-        recovery.run(ric);
+    private Mono<RicData> startRecovery(RicData ric) {
+        RicRecoveryTask recovery = new RicRecoveryTask(a1ClientFactory, policyTypes, policies, services);
+        recovery.run(ric.ric);
         return Mono.empty();
     }
 
-    private void onRicChecked(Ric ric) {
-        logger.info("Ric: " + ric.name() + " checked");
+    private void onRicChecked(RicData ric) {
+        logger.info("Ric: " + ric.ric.name() + " checked");
     }
 
     private void onError(Throwable t) {
index 8b3fadb..d7e8551 100644 (file)
@@ -23,6 +23,7 @@ package org.oransc.policyagent.tasks;
 import java.util.Vector;
 
 import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.clients.AsyncRestClient;
 import org.oransc.policyagent.exceptions.ServiceException;
 import org.oransc.policyagent.repository.ImmutablePolicyType;
@@ -50,13 +51,14 @@ public class RicRecoveryTask {
 
     private static final Logger logger = LoggerFactory.getLogger(RicRecoveryTask.class);
 
-    private final A1Client a1Client;
+    private final A1ClientFactory a1ClientFactory;
     private final PolicyTypes policyTypes;
     private final Policies policies;
     private final Services services;
 
-    public RicRecoveryTask(A1Client a1Client, PolicyTypes policyTypes, Policies policies, Services services) {
-        this.a1Client = a1Client;
+    public RicRecoveryTask(A1ClientFactory a1ClientFactory, PolicyTypes policyTypes, Policies policies,
+        Services services) {
+        this.a1ClientFactory = a1ClientFactory;
         this.policyTypes = policyTypes;
         this.policies = policies;
         this.services = services;
@@ -71,16 +73,21 @@ public class RicRecoveryTask {
             }
             ric.setState(Ric.RicState.RECOVERING);
         }
-        Flux<PolicyType> recoverTypes = recoverPolicyTypes(ric);
-        Flux<?> deletePoliciesInRic = deleteAllPoliciesInRic(ric);
-        Flux<?> recreatePoliciesInRic = recreateAllPoliciesInRic(ric);
-
-        Flux.concat(recoverTypes, deletePoliciesInRic, recreatePoliciesInRic) //
+        this.a1ClientFactory.createA1Client(ric)//
+            .flatMapMany(client -> startRecover(ric, client)) //
             .subscribe(x -> logger.debug("Recover: " + x), //
                 throwable -> onRecoveryError(ric, throwable), //
                 () -> onRecoveryComplete(ric));
     }
 
+    private Flux<Object> startRecover(Ric ric, A1Client a1Client) {
+        Flux<PolicyType> recoverTypes = recoverPolicyTypes(ric, a1Client);
+        Flux<?> deletePoliciesInRic = deleteAllPoliciesInRic(ric, a1Client);
+        Flux<?> recreatePoliciesInRic = recreateAllPoliciesInRic(ric, a1Client);
+
+        return Flux.concat(recoverTypes, deletePoliciesInRic, recreatePoliciesInRic);
+    }
+
     private void onRecoveryComplete(Ric ric) {
         logger.debug("Recovery completed for:" + ric.name());
         ric.setState(Ric.RicState.IDLE);
@@ -104,11 +111,12 @@ public class RicRecoveryTask {
 
     private void onRecoveryError(Ric ric, Throwable t) {
         logger.warn("Recovery failed for: {}, reason: {}", ric.name(), t.getMessage());
-
         // If recovery fails, try to remove all instances
         deleteAllPolicies(ric);
-        Flux<PolicyType> recoverTypes = recoverPolicyTypes(ric);
-        Flux<?> deletePoliciesInRic = deleteAllPoliciesInRic(ric);
+        Flux<PolicyType> recoverTypes = this.a1ClientFactory.createA1Client(ric) //
+            .flatMapMany(a1Client -> recoverPolicyTypes(ric, a1Client));
+        Flux<?> deletePoliciesInRic = this.a1ClientFactory.createA1Client(ric) //
+            .flatMapMany(a1Client -> deleteAllPoliciesInRic(ric, a1Client));
 
         Flux.merge(recoverTypes, deletePoliciesInRic) //
             .subscribe(x -> logger.debug("Brute recover: " + x), //
@@ -125,16 +133,16 @@ public class RicRecoveryTask {
         return new AsyncRestClient(url);
     }
 
-    private Flux<PolicyType> recoverPolicyTypes(Ric ric) {
+    private Flux<PolicyType> recoverPolicyTypes(Ric ric, A1Client a1Client) {
         ric.clearSupportedPolicyTypes();
-        return a1Client.getPolicyTypeIdentities(ric.getConfig().baseUrl()) //
+        return a1Client.getPolicyTypeIdentities() //
             .flatMapMany(types -> Flux.fromIterable(types)) //
             .doOnNext(typeId -> logger.debug("For ric: {}, handling type: {}", ric.getConfig().name(), typeId)) //
-            .flatMap((policyTypeId) -> getPolicyType(ric, policyTypeId)) //
+            .flatMap((policyTypeId) -> getPolicyType(ric, policyTypeId, a1Client)) //
             .doOnNext(policyType -> ric.addSupportedPolicyType(policyType)); //
     }
 
-    private Mono<PolicyType> getPolicyType(Ric ric, String policyTypeId) {
+    private Mono<PolicyType> getPolicyType(Ric ric, String policyTypeId, A1Client a1Client) {
         if (policyTypes.contains(policyTypeId)) {
             try {
                 return Mono.just(policyTypes.getType(policyTypeId));
@@ -142,7 +150,7 @@ public class RicRecoveryTask {
                 return Mono.error(e);
             }
         }
-        return a1Client.getPolicyType(ric.getConfig().baseUrl(), policyTypeId) //
+        return a1Client.getPolicyTypeSchema(policyTypeId) //
             .flatMap(schema -> createPolicyType(policyTypeId, schema));
     }
 
@@ -160,14 +168,14 @@ public class RicRecoveryTask {
         }
     }
 
-    private Flux<String> deleteAllPoliciesInRic(Ric ric) {
-        return a1Client.getPolicyIdentities(ric.getConfig().baseUrl()) //
+    private Flux<String> deleteAllPoliciesInRic(Ric ric, A1Client a1Client) {
+        return a1Client.getPolicyIdentities() //
             .flatMapMany(policyIds -> Flux.fromIterable(policyIds)) //
             .doOnNext(policyId -> logger.debug("Deleting policy: {}, for ric: {}", policyId, ric.getConfig().name()))
-            .flatMap(policyId -> a1Client.deletePolicy(ric.getConfig().baseUrl(), policyId)); //
+            .flatMap(policyId -> a1Client.deletePolicy(policyId)); //
     }
 
-    private Flux<String> recreateAllPoliciesInRic(Ric ric) {
+    private Flux<String> recreateAllPoliciesInRic(Ric ric, A1Client a1Client) {
         synchronized (policies) {
             return Flux.fromIterable(new Vector<>(policies.getForRic(ric.name()))) //
                 .doOnNext(
index 1e7f2dc..d75ff4f 100644 (file)
@@ -20,7 +20,7 @@
 
 package org.oransc.policyagent.tasks;
 
-import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.Policy;
 import org.oransc.policyagent.repository.Service;
@@ -41,13 +41,13 @@ public class ServiceSupervision {
     private static final Logger logger = LoggerFactory.getLogger(ServiceSupervision.class);
     private final Services services;
     private final Policies policies;
-    private A1Client a1Client;
+    private A1ClientFactory a1ClientFactory;
 
     @Autowired
-    public ServiceSupervision(Services services, Policies policies, A1Client a1Client) {
+    public ServiceSupervision(Services services, Policies policies, A1ClientFactory a1ClientFactory) {
         this.services = services;
         this.policies = policies;
-        this.a1Client = a1Client;
+        this.a1ClientFactory = a1ClientFactory;
     }
 
     @Scheduled(fixedRate = 1000 * 60)
@@ -86,9 +86,10 @@ public class ServiceSupervision {
     }
 
     private Mono<Policy> deletePolicyInRic(Policy policy) {
-        return a1Client.deletePolicy(policy.ric().getConfig().baseUrl(), policy.id()) //
-            .onErrorResume(exception -> handleDeleteFromRicFailure(policy, exception)) //
-            .map((nothing) -> policy);
+        return a1ClientFactory.createA1Client(policy.ric()) //
+            .flatMap(client -> client.deletePolicy(policy.id()) //
+                .onErrorResume(exception -> handleDeleteFromRicFailure(policy, exception)) //
+                .map((nothing) -> policy));
     }
 
     private Mono<String> handleDeleteFromRicFailure(Policy policy, Throwable e) {
index 46587a2..c0ffcbd 100644 (file)
@@ -20,7 +20,7 @@
 
 package org.oransc.policyagent.tasks;
 
-import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.configuration.RicConfig;
 import org.oransc.policyagent.repository.Policies;
@@ -57,7 +57,7 @@ public class StartupService implements ApplicationConfig.Observer {
     PolicyTypes policyTypes;
 
     @Autowired
-    private A1Client a1Client;
+    private A1ClientFactory a1ClientFactory;
 
     @Autowired
     private Policies policies;
@@ -67,12 +67,12 @@ public class StartupService implements ApplicationConfig.Observer {
 
     // Only for unittesting
     StartupService(ApplicationConfig appConfig, RefreshConfigTask refreshTask, Rics rics, PolicyTypes policyTypes,
-        A1Client a1Client, Policies policies, Services services) {
+        A1ClientFactory a1ClientFactory, Policies policies, Services services) {
         this.applicationConfig = appConfig;
         this.refreshConfigTask = refreshTask;
         this.rics = rics;
         this.policyTypes = policyTypes;
-        this.a1Client = a1Client;
+        this.a1ClientFactory = a1ClientFactory;
         this.policies = policies;
         this.services = services;
     }
@@ -84,7 +84,7 @@ public class StartupService implements ApplicationConfig.Observer {
                 || event.equals(ApplicationConfig.RicConfigUpdate.CHANGED)) {
                 Ric ric = new Ric(ricConfig);
                 rics.put(ric);
-                RicRecoveryTask recoveryTask = new RicRecoveryTask(a1Client, policyTypes, policies, services);
+                RicRecoveryTask recoveryTask = new RicRecoveryTask(a1ClientFactory, policyTypes, policies, services);
                 recoveryTask.run(ric);
             } else if (event.equals(ApplicationConfig.RicConfigUpdate.REMOVED)) {
                 rics.remove(ricConfig.name());
index 0919154..4270ded 100644 (file)
@@ -28,13 +28,11 @@ import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.reflect.TypeToken;
 
-import java.net.URL;
 import java.util.List;
 import java.util.Vector;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.oransc.policyagent.clients.A1Client;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.configuration.ImmutableRicConfig;
 import org.oransc.policyagent.configuration.RicConfig;
@@ -53,6 +51,7 @@ import org.oransc.policyagent.repository.Ric;
 import org.oransc.policyagent.repository.Rics;
 import org.oransc.policyagent.tasks.RepositorySupervision;
 import org.oransc.policyagent.utils.MockA1Client;
+import org.oransc.policyagent.utils.MockA1ClientFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -81,7 +80,7 @@ public class ApplicationTest {
     private PolicyTypes policyTypes;
 
     @Autowired
-    MockA1Client a1Client;
+    MockA1ClientFactory a1ClientFactory;
 
     @Autowired
     RepositorySupervision supervision;
@@ -93,8 +92,7 @@ public class ApplicationTest {
     public static class MockApplicationConfig extends ApplicationConfig {
         @Override
         public String getLocalConfigurationFilePath() {
-            URL url = MockApplicationConfig.class.getClassLoader().getResource("test_application_configuration.json");
-            return url.getFile();
+            return ""; // No config file loaded for the test
         }
     }
 
@@ -111,8 +109,8 @@ public class ApplicationTest {
         }
 
         @Bean
-        A1Client getA1Client() {
-            return new MockA1Client(this.policyTypes);
+        MockA1ClientFactory getA1ClientFactory() {
+            return new MockA1ClientFactory(this.policyTypes);
         }
 
         @Bean
@@ -161,24 +159,32 @@ public class ApplicationTest {
     public void testRecovery() throws Exception {
         reset();
         Policy policy = addPolicy("policyId", "typeName", "service", "ric"); // This should be created in the RIC
-
         Policy policy2 = addPolicy("policyId2", "typeName", "service", "ric");
-        a1Client.putPolicy("ric", policy2); // put it in the RIC
+
+        getA1Client("ric").putPolicy(policy2); // put it in the RIC
         policies.remove(policy2); // Remove it from the repo -> should be deleted in the RIC
 
         supervision.checkAllRics(); // The created policy should be put in the RIC
-        Policies ricPolicies = a1Client.getPolicies("ric");
+        Policies ricPolicies = getA1Client("ric").getPolicies();
         assertThat(ricPolicies.size()).isEqualTo(1);
         Policy ricPolicy = ricPolicies.get("policyId");
         assertThat(ricPolicy.json()).isEqualTo(policy.json());
     }
 
+    MockA1Client getA1Client(String ricName) throws ServiceException {
+        return a1ClientFactory.getOrCreateA1Client(ricName);
+    }
+
     @Test
     public void testGetRic() throws Exception {
         reset();
+        Ric ric = addRic("ric1");
+        ric.addManagedElement("kista_1");
         String url = baseUrl() + "/ric?managedElementId=kista_1";
+
         String rsp = this.restTemplate.getForObject(url, String.class);
         System.out.println(rsp);
+
         assertThat(rsp).isEqualTo("ric1");
     }
 
index 8adc79a..bbbc06d 100644 (file)
@@ -30,14 +30,14 @@ import java.nio.file.Files;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
-import org.oransc.policyagent.clients.A1Client;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.repository.ImmutablePolicyType;
 import org.oransc.policyagent.repository.Policies;
 import org.oransc.policyagent.repository.PolicyType;
 import org.oransc.policyagent.repository.PolicyTypes;
 import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.utils.MockA1Client;
+import org.oransc.policyagent.utils.MockA1ClientFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
 import org.springframework.boot.test.context.TestConfiguration;
@@ -49,6 +49,9 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
 @SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
 public class MockPolicyAgent {
 
+    @Autowired
+    Rics rics;
+
     static class MockApplicationConfig extends ApplicationConfig {
         @Override
         public String getLocalConfigurationFilePath() {
@@ -73,11 +76,10 @@ public class MockPolicyAgent {
         }
 
         @Bean
-        public A1Client getA1Client() {
+        public MockA1ClientFactory getA1ClientFactory() {
             PolicyTypes ricTypes = new PolicyTypes();
             loadTypes(ricTypes);
-            A1Client client = new MockA1Client(ricTypes);
-            return client;
+            return new MockA1ClientFactory(ricTypes);
         }
 
         @Bean
@@ -21,7 +21,8 @@
 package org.oransc.policyagent.clients;
 
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -33,8 +34,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.Spy;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.oransc.policyagent.configuration.ImmutableRicConfig;
@@ -50,7 +49,7 @@ import reactor.test.StepVerifier;
 
 @ExtendWith(MockitoExtension.class)
 @RunWith(MockitoJUnitRunner.class)
-public class A1ClientImplTest {
+public class StdA1ClientTest {
     private static final String RIC_URL = "RicUrl";
     private static final String POLICYTYPES_IDENTITIES_URL = "/policytypes/identities";
     private static final String POLICIES_IDENTITIES_URL = "/policies/identities";
@@ -67,15 +66,14 @@ public class A1ClientImplTest {
     private static final String POLICY_JSON_INVALID = "\"policyId\":\"policy1\"}";
     private static final String POLICY_TYPE = "typeName";
 
-    @Spy
-    A1ClientImpl a1Client;
+    StdA1Client a1Client;
 
-    @Mock
     AsyncRestClient asyncRestClientMock;
 
     @BeforeEach
     public void init() {
-        doReturn(asyncRestClientMock).when(a1Client).createClient(RIC_URL);
+        asyncRestClientMock = mock(AsyncRestClient.class);
+        a1Client = spy(new StdA1Client(createRic(RIC_URL).getConfig(), asyncRestClientMock));
     }
 
     @Test
@@ -83,7 +81,7 @@ public class A1ClientImplTest {
         Mono<String> policyTypeIds = Mono.just(Arrays.toString(new String[] {POLICY_TYPE_1_NAME, POLICY_TYPE_2_NAME}));
         when(asyncRestClientMock.get(POLICYTYPES_IDENTITIES_URL)).thenReturn(policyTypeIds);
 
-        Mono<?> policyTypeIdsFlux = a1Client.getPolicyTypeIdentities(RIC_URL);
+        Mono<?> policyTypeIdsFlux = a1Client.getPolicyTypeIdentities();
         verify(asyncRestClientMock).get(POLICYTYPES_IDENTITIES_URL);
         StepVerifier.create(policyTypeIdsFlux).expectNextCount(1).expectComplete().verify();
     }
@@ -93,7 +91,7 @@ public class A1ClientImplTest {
         Mono<String> policyIds = Mono.just(Arrays.toString(new String[] {POLICY_1_ID, POLICY_2_ID}));
         when(asyncRestClientMock.get(POLICIES_IDENTITIES_URL)).thenReturn(policyIds);
 
-        Mono<?> policyIdsFlux = a1Client.getPolicyIdentities(RIC_URL);
+        Mono<?> policyIdsFlux = a1Client.getPolicyIdentities();
         verify(asyncRestClientMock).get(POLICIES_IDENTITIES_URL);
         StepVerifier.create(policyIdsFlux).expectNextCount(1).expectComplete().verify();
     }
@@ -103,7 +101,7 @@ public class A1ClientImplTest {
         when(asyncRestClientMock.get(POLICYTYPES_URL + POLICY_TYPE_1_NAME))
             .thenReturn(Mono.just(POLICY_TYPE_SCHEMA_VALID));
 
-        Mono<String> policyTypeMono = a1Client.getPolicyType(RIC_URL, POLICY_TYPE_1_NAME);
+        Mono<String> policyTypeMono = a1Client.getPolicyTypeSchema(POLICY_TYPE_1_NAME);
         verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_NAME);
         StepVerifier.create(policyTypeMono).expectNext(POLICY_TYPE_SCHEMA_VALID).expectComplete().verify();
     }
@@ -113,7 +111,7 @@ public class A1ClientImplTest {
         when(asyncRestClientMock.get(POLICYTYPES_URL + POLICY_TYPE_1_NAME))
             .thenReturn(Mono.just(POLICY_TYPE_SCHEMA_INVALID));
 
-        Mono<String> policyTypeMono = a1Client.getPolicyType(RIC_URL, POLICY_TYPE_1_NAME);
+        Mono<String> policyTypeMono = a1Client.getPolicyTypeSchema(POLICY_TYPE_1_NAME);
         verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_NAME);
         StepVerifier.create(policyTypeMono).expectErrorMatches(throwable -> throwable instanceof JSONException)
             .verify();
@@ -165,7 +163,7 @@ public class A1ClientImplTest {
     public void testDeletePolicy() {
         when(asyncRestClientMock.delete(POLICIES_URL + POLICY_1_ID)).thenReturn(Mono.empty());
 
-        Mono<?> responseMono = a1Client.deletePolicy(RIC_URL, POLICY_1_ID);
+        Mono<?> responseMono = a1Client.deletePolicy(POLICY_1_ID);
         verify(asyncRestClientMock).delete(POLICIES_URL + POLICY_1_ID);
         StepVerifier.create(responseMono).expectComplete().verify();
     }
index 1330a14..4bbe316 100644 (file)
@@ -23,14 +23,16 @@ package org.oransc.policyagent.tasks;
 import static org.awaitility.Awaitility.await;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
 
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Vector;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.runner.RunWith;
@@ -38,6 +40,7 @@ import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.configuration.ImmutableRicConfig;
 import org.oransc.policyagent.repository.ImmutablePolicy;
 import org.oransc.policyagent.repository.ImmutablePolicyType;
@@ -57,6 +60,14 @@ public class RepositorySupervisionTest {
     @Mock
     A1Client a1ClientMock;
 
+    @Mock
+    A1ClientFactory a1ClientFactory;
+
+    @BeforeEach
+    public void init() {
+        doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any());
+    }
+
     @Test
     public void test() {
         Ric ric1 = new Ric(ImmutableRicConfig.builder() //
@@ -99,14 +110,15 @@ public class RepositorySupervisionTest {
         Services services = new Services();
 
         RepositorySupervision supervisorUnderTest =
-            new RepositorySupervision(rics, policies, a1ClientMock, types, services);
+            new RepositorySupervision(rics, policies, a1ClientFactory, types, services);
 
         Mono<Collection<String>> policyIds = Mono.just(Arrays.asList("policyId1", "policyId2"));
-        when(a1ClientMock.getPolicyIdentities(anyString())).thenReturn(policyIds);
-        when(a1ClientMock.deletePolicy(anyString(), anyString())).thenReturn(Mono.empty());
-        when(a1ClientMock.getPolicyTypeIdentities(anyString())).thenReturn(policyIds);
-        when(a1ClientMock.getPolicyType(anyString(), anyString())).thenReturn(Mono.just("schema"));
-        when(a1ClientMock.putPolicy(any())).thenReturn(Mono.just("OK"));
+
+        doReturn(policyIds).when(a1ClientMock).getPolicyTypeIdentities();
+        doReturn(policyIds).when(a1ClientMock).getPolicyIdentities();
+        doReturn(Mono.empty()).when(a1ClientMock).deletePolicy(anyString());
+        doReturn(Mono.just("schema")).when(a1ClientMock).getPolicyTypeSchema(anyString());
+        doReturn(Mono.just("OK")).when(a1ClientMock).putPolicy(any());
 
         supervisorUnderTest.checkAllRics();
 
@@ -114,8 +126,7 @@ public class RepositorySupervisionTest {
         await().untilAsserted(() -> RicState.IDLE.equals(ric2.state()));
         await().untilAsserted(() -> RicState.IDLE.equals(ric3.state()));
 
-        verify(a1ClientMock).deletePolicy("baseUrl1", "policyId2");
-        verify(a1ClientMock).deletePolicy("baseUrl2", "policyId2");
+        verify(a1ClientMock, times(3)).deletePolicy("policyId2");
         verifyNoMoreInteractions(a1ClientMock);
     }
 }
index 47e7b4d..9e4701d 100644 (file)
@@ -25,8 +25,11 @@ import static org.awaitility.Awaitility.await;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.oransc.policyagent.repository.Ric.RicState.IDLE;
@@ -35,13 +38,14 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Vector;
 
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.junit.runner.RunWith;
-import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnitRunner;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
 import org.oransc.policyagent.configuration.ApplicationConfig;
 import org.oransc.policyagent.configuration.ImmutableRicConfig;
 import org.oransc.policyagent.configuration.RicConfig;
@@ -69,29 +73,35 @@ public class StartupServiceTest {
     private static final String POLICY_ID_1 = "policy1";
     private static final String POLICY_ID_2 = "policy2";
 
-    @Mock
     ApplicationConfig appConfigMock;
-
-    @Mock
     RefreshConfigTask refreshTaskMock;
 
-    @Mock
     A1Client a1ClientMock;
+    A1ClientFactory a1ClientFactory;
+
+    @BeforeEach
+    public void init() throws Exception {
+        a1ClientMock = mock(A1Client.class);
+        a1ClientFactory = mock(A1ClientFactory.class);
+        appConfigMock = mock(ApplicationConfig.class);
+        refreshTaskMock = mock(RefreshConfigTask.class);
+        doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any());
+    }
 
     @Test
     public void startup_allOk() {
         Mono<Collection<String>> policyTypes1 = Mono.just(Arrays.asList(POLICY_TYPE_1_NAME));
         Mono<Collection<String>> policyTypes2 = Mono.just(Arrays.asList(POLICY_TYPE_1_NAME, POLICY_TYPE_2_NAME));
-        when(a1ClientMock.getPolicyTypeIdentities(anyString())).thenReturn(policyTypes1).thenReturn(policyTypes2);
+        doReturn(policyTypes1, policyTypes2).when(a1ClientMock).getPolicyTypeIdentities();
         Mono<Collection<String>> policies = Mono.just(Arrays.asList(POLICY_ID_1, POLICY_ID_2));
-        when(a1ClientMock.getPolicyIdentities(anyString())).thenReturn(policies);
-        when(a1ClientMock.getPolicyType(anyString(), anyString())).thenReturn(Mono.just("Schema"));
-        when(a1ClientMock.deletePolicy(anyString(), anyString())).thenReturn(Mono.just("OK"));
+        doReturn(policies).when(a1ClientMock).getPolicyIdentities();
+        doReturn(Mono.just("Schema")).when(a1ClientMock).getPolicyTypeSchema(anyString());
+        doReturn(Mono.just("OK")).when(a1ClientMock).deletePolicy(anyString());
 
         Rics rics = new Rics();
         PolicyTypes policyTypes = new PolicyTypes();
         StartupService serviceUnderTest = new StartupService(appConfigMock, refreshTaskMock, rics, policyTypes,
-            a1ClientMock, new Policies(), new Services());
+            a1ClientFactory, new Policies(), new Services());
 
         serviceUnderTest.startup();
 
@@ -103,13 +113,9 @@ public class StartupServiceTest {
 
         await().untilAsserted(() -> assertThat(policyTypes.size()).isEqualTo(2));
 
-        verify(a1ClientMock).getPolicyTypeIdentities(FIRST_RIC_URL);
-        verify(a1ClientMock).deletePolicy(FIRST_RIC_URL, POLICY_ID_1);
-        verify(a1ClientMock).deletePolicy(FIRST_RIC_URL, POLICY_ID_2);
-
-        verify(a1ClientMock).getPolicyTypeIdentities(SECOND_RIC_URL);
-        verify(a1ClientMock).deletePolicy(SECOND_RIC_URL, POLICY_ID_1);
-        verify(a1ClientMock).deletePolicy(SECOND_RIC_URL, POLICY_ID_2);
+        verify(a1ClientMock, times(2)).getPolicyTypeIdentities();
+        verify(a1ClientMock, times(2)).deletePolicy(POLICY_ID_1);
+        verify(a1ClientMock, times(2)).deletePolicy(POLICY_ID_2);
 
         assertTrue(policyTypes.contains(POLICY_TYPE_1_NAME), POLICY_TYPE_1_NAME + " not added to PolicyTypes.");
         assertTrue(policyTypes.contains(POLICY_TYPE_2_NAME), POLICY_TYPE_2_NAME + " not added to PolicyTypes.");
@@ -146,13 +152,13 @@ public class StartupServiceTest {
     @Test
     public void startup_unableToConnectToGetTypes() {
         Mono<?> error = Mono.error(new Exception("Unable to contact ric."));
-        doReturn(error, error).when(a1ClientMock).getPolicyTypeIdentities(anyString());
-        doReturn(error).when(a1ClientMock).getPolicyIdentities(anyString());
+        doReturn(error, error).when(a1ClientMock).getPolicyTypeIdentities();
+        doReturn(error).when(a1ClientMock).getPolicyIdentities();
 
         Rics rics = new Rics();
         PolicyTypes policyTypes = new PolicyTypes();
         StartupService serviceUnderTest = new StartupService(appConfigMock, refreshTaskMock, rics, policyTypes,
-            a1ClientMock, new Policies(), new Services());
+            a1ClientFactory, new Policies(), new Services());
 
         serviceUnderTest.startup();
         serviceUnderTest.onRicConfigUpdate(getRicConfig(FIRST_RIC_NAME, FIRST_RIC_URL, MANAGED_NODE_A),
@@ -165,14 +171,14 @@ public class StartupServiceTest {
     public void startup_unableToConnectToGetPolicies() {
 
         Mono<Collection<String>> policyTypes = Mono.just(Arrays.asList(POLICY_TYPE_1_NAME));
-        when(a1ClientMock.getPolicyTypeIdentities(anyString())).thenReturn(policyTypes);
-        when(a1ClientMock.getPolicyType(anyString(), anyString())).thenReturn(Mono.just("Schema"));
+        when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(policyTypes);
+        when(a1ClientMock.getPolicyTypeSchema(anyString())).thenReturn(Mono.just("Schema"));
         Mono<?> error = Mono.error(new Exception("Unable to contact ric."));
-        doReturn(error).when(a1ClientMock).getPolicyIdentities(anyString());
+        doReturn(error).when(a1ClientMock).getPolicyIdentities();
 
         Rics rics = new Rics();
         StartupService serviceUnderTest = new StartupService(appConfigMock, refreshTaskMock, rics, new PolicyTypes(),
-            a1ClientMock, new Policies(), new Services());
+            a1ClientFactory, new Policies(), new Services());
 
         serviceUnderTest.startup();
         serviceUnderTest.onRicConfigUpdate(getRicConfig(FIRST_RIC_NAME, FIRST_RIC_URL, MANAGED_NODE_A),
index bac2739..d6cd533 100644 (file)
@@ -21,8 +21,6 @@
 package org.oransc.policyagent.utils;
 
 import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Vector;
 
 import org.oransc.policyagent.clients.A1Client;
@@ -33,7 +31,7 @@ import org.oransc.policyagent.repository.PolicyTypes;
 import reactor.core.publisher.Mono;
 
 public class MockA1Client implements A1Client {
-    private final Map<String, Policies> policies = new HashMap<>();
+    Policies policies = new Policies();
     private final PolicyTypes policyTypes;
 
     public MockA1Client(PolicyTypes policyTypes) {
@@ -41,7 +39,7 @@ public class MockA1Client implements A1Client {
     }
 
     @Override
-    public Mono<Collection<String>> getPolicyTypeIdentities(String nearRtRicUrl) {
+    public Mono<Collection<String>> getPolicyTypeIdentities() {
         synchronized (this.policyTypes) {
             Vector<String> result = new Vector<>();
             for (PolicyType p : this.policyTypes.getAll()) {
@@ -52,13 +50,11 @@ public class MockA1Client implements A1Client {
     }
 
     @Override
-    public Mono<Collection<String>> getPolicyIdentities(String nearRtRicUrl) {
+    public Mono<Collection<String>> getPolicyIdentities() {
         synchronized (this.policies) {
             Vector<String> result = new Vector<>();
-            for (Policy policy : getPolicies(nearRtRicUrl).getAll()) {
-                if (policy.ric().getConfig().baseUrl().equals(nearRtRicUrl)) {
-                    result.add(policy.id());
-                }
+            for (Policy policy : policies.getAll()) {
+                result.add(policy.id());
             }
 
             return Mono.just(result);
@@ -66,7 +62,7 @@ public class MockA1Client implements A1Client {
     }
 
     @Override
-    public Mono<String> getPolicyType(String nearRtRicUrl, String policyTypeId) {
+    public Mono<String> getPolicyTypeSchema(String policyTypeId) {
         try {
             return Mono.just(this.policyTypes.getType(policyTypeId).schema());
         } catch (Exception e) {
@@ -76,25 +72,23 @@ public class MockA1Client implements A1Client {
 
     @Override
     public Mono<String> putPolicy(Policy p) {
-        getPolicies(p.ric().getConfig().baseUrl()).put(p);
+        this.policies.put(p);
         return Mono.just("OK");
     }
 
     @Override
-    public Mono<String> deletePolicy(String nearRtRicUrl, String policyId) {
-        getPolicies(nearRtRicUrl).removeId(policyId);
+    public Mono<String> deletePolicy(String policyId) {
+        this.policies.removeId(policyId);
         return Mono.just("OK");
     }
 
-    public Policies getPolicies(String url) {
-        if (!policies.containsKey(url)) {
-            policies.put(url, new Policies());
-        }
-        return policies.get(url);
+    public Policies getPolicies() {
+        return this.policies;
     }
 
-    public void putPolicy(String url, Policy policy) {
-        getPolicies(url).put(policy);
+    @Override
+    public Mono<A1ProtocolType> getProtocolVersion() {
+        return Mono.just(A1ProtocolType.STD_V1);
     }
 
 }
diff --git a/policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1ClientFactory.java b/policy-agent/src/test/java/org/oransc/policyagent/utils/MockA1ClientFactory.java
new file mode 100644 (file)
index 0000000..314c44c
--- /dev/null
@@ -0,0 +1,57 @@
+/*-
+ * ========================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.utils;
+
+import java.lang.invoke.MethodHandles;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.oransc.policyagent.clients.A1Client;
+import org.oransc.policyagent.clients.A1ClientFactory;
+import org.oransc.policyagent.repository.PolicyTypes;
+import org.oransc.policyagent.repository.Ric;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MockA1ClientFactory extends A1ClientFactory {
+    private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+    private final Map<String, MockA1Client> clients = new HashMap<>();
+    private final PolicyTypes policyTypes;
+
+    public MockA1ClientFactory(PolicyTypes policyTypes) {
+        this.policyTypes = policyTypes;
+    }
+
+    @Override
+    protected A1Client createStdA1ClientImpl(Ric ric) {
+        return getOrCreateA1Client(ric.name());
+    }
+
+    public MockA1Client getOrCreateA1Client(String ricName) {
+        if (!clients.containsKey(ricName)) {
+            logger.debug("Creating client for RIC: {}", ricName);
+            MockA1Client client = new MockA1Client(policyTypes);
+            clients.put(ricName, client);
+        }
+        return clients.get(ricName);
+    }
+
+}