From d375c04a9c1917a9bf98285fb1f30062cff7a6d6 Mon Sep 17 00:00:00 2001 From: PatrikBuhr Date: Tue, 14 Apr 2020 13:50:07 +0200 Subject: [PATCH] Bugfix Parsing of controller output. Renamed the config/application_configuration.json to application_configuration.json_example so it does not by default is loaded by the builyt container. Change-Id: Ie631a3f745a977c7414ed60b2f3d09cd6687360a Issue-ID: NONRTRIC-164 Signed-off-by: PatrikBuhr --- ...json => application_configuration.json_example} | 0 .../policyagent/clients/AsyncRestClient.java | 16 +++++++- .../oransc/policyagent/clients/SdncJsonHelper.java | 37 +++++++++++++---- .../policyagent/clients/SdncOscA1Client.java | 28 ++++++++----- .../policyagent/tasks/RefreshConfigTask.java | 6 +-- .../oransc/policyagent/tasks/RicSupervision.java | 10 ++--- .../policyagent/clients/SdncOscA1ClientTest.java | 47 ++++++++++++++-------- 7 files changed, 100 insertions(+), 44 deletions(-) rename policy-agent/config/{application_configuration.json => application_configuration.json_example} (100%) diff --git a/policy-agent/config/application_configuration.json b/policy-agent/config/application_configuration.json_example similarity index 100% rename from policy-agent/config/application_configuration.json rename to policy-agent/config/application_configuration.json_example diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java index 5110718d..f0b2ce33 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/AsyncRestClient.java @@ -34,6 +34,7 @@ import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.lang.Nullable; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec; +import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Mono; import reactor.netty.http.client.HttpClient; @@ -137,10 +138,21 @@ public class AsyncRestClient { private Mono> retrieve(RequestHeadersSpec request) { return request.retrieve() // - .toEntity(String.class); + .toEntity(String.class) // + .doOnError(this::onHttpError); } - Mono toBody(ResponseEntity entity) { + private void onHttpError(Throwable t) { + if (t instanceof WebClientResponseException) { + WebClientResponseException exception = (WebClientResponseException) t; + logger.debug("HTTP error status = '{}', body '{}'", exception.getStatusCode(), + exception.getResponseBodyAsString()); + } else { + logger.debug("HTTP error: {}", t.getMessage()); + } + } + + private Mono toBody(ResponseEntity entity) { if (entity.getBody() == null) { return Mono.just(""); } else { diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncJsonHelper.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncJsonHelper.java index 0245a153..4d3cbf88 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncJsonHelper.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncJsonHelper.java @@ -26,12 +26,15 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; +import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.List; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -39,10 +42,13 @@ import reactor.core.publisher.Mono; /** * Common json functionality used by the SDNC clients */ +@SuppressWarnings("java:S1192") // Same text in several traces class SdncJsonHelper { private static Gson gson = new GsonBuilder() // .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) // .create(); + private static final String OUTPUT = "output"; + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private SdncJsonHelper() { } @@ -58,6 +64,7 @@ class SdncJsonHelper { } return Flux.fromIterable(arrayList); } catch (JSONException ex) { // invalid json + logger.debug("Invalid json {}", ex.getMessage()); return Flux.error(ex); } } @@ -69,20 +76,35 @@ class SdncJsonHelper { return gson.toJson(jsonObj); } - public static Mono getValueFromResponse(String response, String key) { + public static String createOutputJsonString(T params) { + JsonElement paramsJson = gson.toJsonTree(params); + JsonObject jsonObj = new JsonObject(); + jsonObj.add(OUTPUT, paramsJson); + return gson.toJson(jsonObj); + } + + public static Mono getOutput(String response) { try { JSONObject outputJson = new JSONObject(response); - JSONObject responseParams = outputJson.getJSONObject("output"); - if (!responseParams.has(key)) { - return Mono.just(""); - } - String value = responseParams.get(key).toString(); - return Mono.just(value); + JSONObject responseParams = outputJson.getJSONObject(OUTPUT); + return Mono.just(responseParams); } catch (JSONException ex) { // invalid json + logger.debug("Invalid json {}", ex.getMessage()); return Mono.error(ex); } } + public static Mono getValueFromResponse(String response, String key) { + return getOutput(response) // + .flatMap(responseParams -> { + if (!responseParams.has(key)) { + return Mono.just(""); + } + String value = responseParams.get(key).toString(); + return Mono.just(value); + }); + } + public static Mono extractPolicySchema(String inputString) { try { JSONObject jsonObject = new JSONObject(inputString); @@ -90,6 +112,7 @@ class SdncJsonHelper { String schemaString = schemaObject.toString(); return Mono.just(schemaString); } catch (JSONException ex) { // invalid json + logger.debug("Invalid json {}", ex.getMessage()); return Mono.error(ex); } } diff --git a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java index ece40e14..68601735 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/clients/SdncOscA1Client.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Optional; import org.immutables.value.Value; +import org.json.JSONObject; import org.oransc.policyagent.configuration.ControllerConfig; import org.oransc.policyagent.configuration.RicConfig; import org.oransc.policyagent.repository.Policy; @@ -57,8 +58,8 @@ public class SdncOscA1Client implements A1Client { @Value.Immutable @org.immutables.gson.Gson.TypeAdapters - public interface AdapterResponse { - public String body(); + public interface AdapterOutput { + public Optional body(); public int httpStatus(); } @@ -217,6 +218,7 @@ public class SdncOscA1Client implements A1Client { .body(body) // .build(); final String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams); + logger.debug("POST inputJsonString = {}", inputJsonString); return restClient .postWithAuthHeader(controllerUrl(rpcName), inputJsonString, this.controllerConfig.userName(), @@ -224,17 +226,25 @@ public class SdncOscA1Client implements A1Client { .flatMap(this::extractResponseBody); } - private Mono extractResponseBody(String response) { - AdapterResponse output = gson.fromJson(response, ImmutableAdapterResponse.class); - String body = output.body(); + private Mono extractResponse(JSONObject responseOutput) { + AdapterOutput output = gson.fromJson(responseOutput.toString(), ImmutableAdapterOutput.class); + Optional optionalBody = output.body(); + String body = optionalBody.isPresent() ? optionalBody.get() : ""; if (HttpStatus.valueOf(output.httpStatus()).is2xxSuccessful()) { return Mono.just(body); + } else { + logger.debug("Error response: {} {}", output.httpStatus(), body); + byte[] responseBodyBytes = body.getBytes(StandardCharsets.UTF_8); + WebClientResponseException e = new WebClientResponseException(output.httpStatus(), "statusText", null, + responseBodyBytes, StandardCharsets.UTF_8, null); + + return Mono.error(e); } - byte[] responseBodyBytes = body.getBytes(StandardCharsets.UTF_8); - WebClientResponseException e = new WebClientResponseException(output.httpStatus(), "statusText", null, - responseBodyBytes, StandardCharsets.UTF_8, null); + } - return Mono.error(e); + private Mono extractResponseBody(String responseStr) { + return SdncJsonHelper.getOutput(responseStr) // + .flatMap(this::extractResponse); } private String controllerUrl(String rpcName) { diff --git a/policy-agent/src/main/java/org/oransc/policyagent/tasks/RefreshConfigTask.java b/policy-agent/src/main/java/org/oransc/policyagent/tasks/RefreshConfigTask.java index 35da96d2..7cfe4868 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/tasks/RefreshConfigTask.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/tasks/RefreshConfigTask.java @@ -127,16 +127,16 @@ public class RefreshConfigTask { .filter(notUsed -> !this.isConsulUsed) // .flatMap(notUsed -> loadConfigurationFromFile()) // .onErrorResume(this::ignoreError) // - .doOnNext(json -> logger.debug("loadFromFile")) // + .doOnNext(json -> logger.debug("loadFromFile succeeded")) // .doOnTerminate(() -> logger.error("loadFromFile Terminate")); Flux loadFromConsul = getEnvironment(systemEnvironment) // .flatMap(this::createCbsClient) // .flatMapMany(this::periodicConfigurationUpdates) // .onErrorResume(this::ignoreError) // - .doOnNext(json -> logger.debug("loadFromConsul")) // + .doOnNext(json -> logger.debug("loadFromConsul succeeded")) // .doOnNext(json -> this.isConsulUsed = true) // - .doOnTerminate(() -> logger.error("loadFromConsul Terminate")); + .doOnTerminate(() -> logger.error("loadFromConsul Terminated")); return Flux.merge(loadFromFile, loadFromConsul) // .flatMap(this::parseConfiguration) // diff --git a/policy-agent/src/main/java/org/oransc/policyagent/tasks/RicSupervision.java b/policy-agent/src/main/java/org/oransc/policyagent/tasks/RicSupervision.java index c2dd18ec..2666d606 100644 --- a/policy-agent/src/main/java/org/oransc/policyagent/tasks/RicSupervision.java +++ b/policy-agent/src/main/java/org/oransc/policyagent/tasks/RicSupervision.java @@ -74,11 +74,7 @@ public class RicSupervision { @Scheduled(fixedRate = 1000 * 60) public void checkAllRics() { logger.debug("Checking Rics starting"); - createTask().subscribe( // - ric -> logger.debug("Ric: {} checked", ric.ric.name()), // - null, // - () -> logger.debug("Checking Rics completed") // - ); + createTask().subscribe(null, null, () -> logger.debug("Checking all RICs completed")); } private Flux createTask() { @@ -95,7 +91,9 @@ public class RicSupervision { .flatMap(x -> checkRicPolicies(ricData)) // .flatMap(x -> ricData.ric.getLock().unlock()) // .doOnError(throwable -> ricData.ric.getLock().unlockBlocking()) // - .flatMap(x -> checkRicPolicyTypes(ricData)); // + .flatMap(x -> checkRicPolicyTypes(ricData)) // + .doOnNext(x -> logger.debug("Ric: {} checked OK", ricData.ric.name())) // + .doOnError(t -> logger.debug("Ric: {} check Failed, exception: {}", ricData.ric.name(), t.getMessage())); } private static class RicData { diff --git a/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java b/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java index 18ef0979..2b60fe05 100644 --- a/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java +++ b/policy-agent/src/test/java/org/oransc/policyagent/clients/SdncOscA1ClientTest.java @@ -30,6 +30,7 @@ import com.google.gson.Gson; import java.util.Arrays; import java.util.List; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -37,8 +38,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; 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.clients.SdncOscA1Client.AdapterOutput; import org.oransc.policyagent.configuration.ControllerConfig; import org.oransc.policyagent.configuration.ImmutableControllerConfig; import org.oransc.policyagent.repository.Policy; @@ -105,7 +105,7 @@ public class SdncOscA1ClientTest { assertEquals(POLICY_TYPE_1_ID, policyTypeIds.get(0), ""); String expUrl = RIC_1_URL + "/a1-p/policytypes"; - AdapterRequest expectedParams = ImmutableAdapterRequest.builder() // + ImmutableAdapterRequest expectedParams = ImmutableAdapterRequest.builder() // .nearRtRicUrl(expUrl) // .build(); String expInput = SdncJsonHelper.createInputJsonString(expectedParams); @@ -122,13 +122,12 @@ public class SdncOscA1ClientTest { return SdncOscA1Client.gson; } - private String createResponse(Object obj) { - AdapterResponse output = ImmutableAdapterResponse.builder() // - .body(gson().toJson(obj)) // + private String createResponse(Object body) { + AdapterOutput output = ImmutableAdapterOutput.builder() // + .body(gson().toJson(body)) // .httpStatus(200) // .build(); - - return gson().toJson(output); + return SdncJsonHelper.createOutputJsonString(output); } @Test @@ -140,7 +139,7 @@ public class SdncOscA1ClientTest { List returned = clientUnderTest.getPolicyIdentities().block(); assertEquals(2, returned.size(), ""); - AdapterRequest expectedParams = ImmutableAdapterRequest.builder() // + ImmutableAdapterRequest expectedParams = ImmutableAdapterRequest.builder() // .nearRtRicUrl(policiesUrl()) // .build(); String expInput = SdncJsonHelper.createInputJsonString(expectedParams); @@ -164,7 +163,7 @@ public class SdncOscA1ClientTest { .block(); assertEquals("OK", returned, ""); final String expUrl = policiesUrl() + "/" + POLICY_1_ID; - AdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() // + ImmutableAdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() // .nearRtRicUrl(expUrl) // .body(POLICY_JSON_VALID) // .build(); @@ -176,19 +175,19 @@ public class SdncOscA1ClientTest { @Test public void testPutPolicyRejected() { final String policyJson = "{}"; - AdapterResponse adapterResponse = ImmutableAdapterResponse.builder() // + AdapterOutput adapterOutput = ImmutableAdapterOutput.builder() // .body("NOK") // .httpStatus(400) // ERROR .build(); - String resp = gson().toJson(adapterResponse); + String resp = SdncJsonHelper.createOutputJsonString(adapterOutput); whenAsyncPostThenReturn(Mono.just(resp)); Mono returnedMono = clientUnderTest .putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, policyJson, POLICY_TYPE_1_ID)); final String expUrl = policiesUrl() + "/" + POLICY_1_ID; - AdapterRequest expRequestParams = ImmutableAdapterRequest.builder() // + ImmutableAdapterRequest expRequestParams = ImmutableAdapterRequest.builder() // .nearRtRicUrl(expUrl) // .body(policyJson) // .build(); @@ -208,7 +207,7 @@ public class SdncOscA1ClientTest { .block(); assertEquals("OK", returned, ""); final String expUrl = policiesUrl() + "/" + POLICY_1_ID; - AdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() // + ImmutableAdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() // .nearRtRicUrl(expUrl) // .build(); String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams); @@ -228,7 +227,7 @@ public class SdncOscA1ClientTest { assertEquals("OK", returnedStatus, "unexpected status"); final String expUrl = policiesUrl() + "/" + POLICY_1_ID + "/status"; - AdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() // + ImmutableAdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() // .nearRtRicUrl(expUrl) // .build(); String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams); @@ -242,15 +241,29 @@ public class SdncOscA1ClientTest { whenPostReturnOkResponse(); A1ProtocolType returnedVersion = clientUnderTest.getProtocolVersion().block(); assertEquals(A1ProtocolType.SDNC_OSC_STD_V1_1, returnedVersion, ""); + + whenPostReturnOkResponseNoBody(); + returnedVersion = clientUnderTest.getProtocolVersion().block(); + assertEquals(A1ProtocolType.SDNC_OSC_STD_V1_1, returnedVersion, ""); } private void whenPostReturnOkResponse() { - AdapterResponse adapterResponse = ImmutableAdapterResponse.builder() // + AdapterOutput adapterOutput = ImmutableAdapterOutput.builder() // .body("OK") // .httpStatus(200) // .build(); - String resp = gson().toJson(adapterResponse); + String resp = SdncJsonHelper.createOutputJsonString(adapterOutput); + whenAsyncPostThenReturn(Mono.just(resp)); + } + + private void whenPostReturnOkResponseNoBody() { + AdapterOutput adapterOutput = ImmutableAdapterOutput.builder() // + .httpStatus(200) // + .body(Optional.empty()) // + .build(); + + String resp = SdncJsonHelper.createOutputJsonString(adapterOutput); whenAsyncPostThenReturn(Mono.just(resp)); } -- 2.16.6