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 <patrik.buhr@est.tech>
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.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;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
private Mono<ResponseEntity<String>> retrieve(RequestHeadersSpec<?> request) {
return request.retrieve() //
private Mono<ResponseEntity<String>> retrieve(RequestHeadersSpec<?> request) {
return request.retrieve() //
- .toEntity(String.class);
+ .toEntity(String.class) //
+ .doOnError(this::onHttpError);
- Mono<String> toBody(ResponseEntity<String> 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<String> toBody(ResponseEntity<String> entity) {
if (entity.getBody() == null) {
return Mono.just("");
} else {
if (entity.getBody() == null) {
return Mono.just("");
} else {
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
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 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;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
/**
* Common json functionality used by the SDNC clients
*/
/**
* 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();
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() {
}
private SdncJsonHelper() {
}
}
return Flux.fromIterable(arrayList);
} catch (JSONException ex) { // invalid json
}
return Flux.fromIterable(arrayList);
} catch (JSONException ex) { // invalid json
+ logger.debug("Invalid json {}", ex.getMessage());
return Flux.error(ex);
}
}
return Flux.error(ex);
}
}
return gson.toJson(jsonObj);
}
return gson.toJson(jsonObj);
}
- public static Mono<String> getValueFromResponse(String response, String key) {
+ public static <T> String createOutputJsonString(T params) {
+ JsonElement paramsJson = gson.toJsonTree(params);
+ JsonObject jsonObj = new JsonObject();
+ jsonObj.add(OUTPUT, paramsJson);
+ return gson.toJson(jsonObj);
+ }
+
+ public static Mono<JSONObject> getOutput(String response) {
try {
JSONObject outputJson = new JSONObject(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
} catch (JSONException ex) { // invalid json
+ logger.debug("Invalid json {}", ex.getMessage());
return Mono.error(ex);
}
}
return Mono.error(ex);
}
}
+ public static Mono<String> 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<String> extractPolicySchema(String inputString) {
try {
JSONObject jsonObject = new JSONObject(inputString);
public static Mono<String> extractPolicySchema(String inputString) {
try {
JSONObject jsonObject = new JSONObject(inputString);
String schemaString = schemaObject.toString();
return Mono.just(schemaString);
} catch (JSONException ex) { // invalid json
String schemaString = schemaObject.toString();
return Mono.just(schemaString);
} catch (JSONException ex) { // invalid json
+ logger.debug("Invalid json {}", ex.getMessage());
return Mono.error(ex);
}
}
return Mono.error(ex);
}
}
import java.util.Optional;
import org.immutables.value.Value;
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;
import org.oransc.policyagent.configuration.ControllerConfig;
import org.oransc.policyagent.configuration.RicConfig;
import org.oransc.policyagent.repository.Policy;
@Value.Immutable
@org.immutables.gson.Gson.TypeAdapters
@Value.Immutable
@org.immutables.gson.Gson.TypeAdapters
- public interface AdapterResponse {
- public String body();
+ public interface AdapterOutput {
+ public Optional<String> body();
public int httpStatus();
}
public int httpStatus();
}
.body(body) //
.build();
final String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
.body(body) //
.build();
final String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
+ logger.debug("POST inputJsonString = {}", inputJsonString);
return restClient
.postWithAuthHeader(controllerUrl(rpcName), inputJsonString, this.controllerConfig.userName(),
return restClient
.postWithAuthHeader(controllerUrl(rpcName), inputJsonString, this.controllerConfig.userName(),
.flatMap(this::extractResponseBody);
}
.flatMap(this::extractResponseBody);
}
- private Mono<String> extractResponseBody(String response) {
- AdapterResponse output = gson.fromJson(response, ImmutableAdapterResponse.class);
- String body = output.body();
+ private Mono<String> extractResponse(JSONObject responseOutput) {
+ AdapterOutput output = gson.fromJson(responseOutput.toString(), ImmutableAdapterOutput.class);
+ Optional<String> optionalBody = output.body();
+ String body = optionalBody.isPresent() ? optionalBody.get() : "";
if (HttpStatus.valueOf(output.httpStatus()).is2xxSuccessful()) {
return Mono.just(body);
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);
+ private Mono<String> extractResponseBody(String responseStr) {
+ return SdncJsonHelper.getOutput(responseStr) //
+ .flatMap(this::extractResponse);
}
private String controllerUrl(String rpcName) {
}
private String controllerUrl(String rpcName) {
.filter(notUsed -> !this.isConsulUsed) //
.flatMap(notUsed -> loadConfigurationFromFile()) //
.onErrorResume(this::ignoreError) //
.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<JsonObject> loadFromConsul = getEnvironment(systemEnvironment) //
.flatMap(this::createCbsClient) //
.flatMapMany(this::periodicConfigurationUpdates) //
.onErrorResume(this::ignoreError) //
.doOnTerminate(() -> logger.error("loadFromFile Terminate"));
Flux<JsonObject> 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) //
.doOnNext(json -> this.isConsulUsed = true) //
- .doOnTerminate(() -> logger.error("loadFromConsul Terminate"));
+ .doOnTerminate(() -> logger.error("loadFromConsul Terminated"));
return Flux.merge(loadFromFile, loadFromConsul) //
.flatMap(this::parseConfiguration) //
return Flux.merge(loadFromFile, loadFromConsul) //
.flatMap(this::parseConfiguration) //
@Scheduled(fixedRate = 1000 * 60)
public void checkAllRics() {
logger.debug("Checking Rics starting");
@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<RicData> createTask() {
}
private Flux<RicData> createTask() {
.flatMap(x -> checkRicPolicies(ricData)) //
.flatMap(x -> ricData.ric.getLock().unlock()) //
.doOnError(throwable -> ricData.ric.getLock().unlockBlocking()) //
.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 {
}
private static class RicData {
import java.util.Arrays;
import java.util.List;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.OngoingStubbing;
import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
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;
import org.oransc.policyagent.configuration.ControllerConfig;
import org.oransc.policyagent.configuration.ImmutableControllerConfig;
import org.oransc.policyagent.repository.Policy;
assertEquals(POLICY_TYPE_1_ID, policyTypeIds.get(0), "");
String expUrl = RIC_1_URL + "/a1-p/policytypes";
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);
.nearRtRicUrl(expUrl) //
.build();
String expInput = SdncJsonHelper.createInputJsonString(expectedParams);
return SdncOscA1Client.gson;
}
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();
.httpStatus(200) //
.build();
-
- return gson().toJson(output);
+ return SdncJsonHelper.createOutputJsonString(output);
List<String> returned = clientUnderTest.getPolicyIdentities().block();
assertEquals(2, returned.size(), "");
List<String> returned = clientUnderTest.getPolicyIdentities().block();
assertEquals(2, returned.size(), "");
- AdapterRequest expectedParams = ImmutableAdapterRequest.builder() //
+ ImmutableAdapterRequest expectedParams = ImmutableAdapterRequest.builder() //
.nearRtRicUrl(policiesUrl()) //
.build();
String expInput = SdncJsonHelper.createInputJsonString(expectedParams);
.nearRtRicUrl(policiesUrl()) //
.build();
String expInput = SdncJsonHelper.createInputJsonString(expectedParams);
.block();
assertEquals("OK", returned, "");
final String expUrl = policiesUrl() + "/" + POLICY_1_ID;
.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();
.nearRtRicUrl(expUrl) //
.body(POLICY_JSON_VALID) //
.build();
@Test
public void testPutPolicyRejected() {
final String policyJson = "{}";
@Test
public void testPutPolicyRejected() {
final String policyJson = "{}";
- AdapterResponse adapterResponse = ImmutableAdapterResponse.builder() //
+ AdapterOutput adapterOutput = ImmutableAdapterOutput.builder() //
.body("NOK") //
.httpStatus(400) // ERROR
.build();
.body("NOK") //
.httpStatus(400) // ERROR
.build();
- String resp = gson().toJson(adapterResponse);
+ String resp = SdncJsonHelper.createOutputJsonString(adapterOutput);
whenAsyncPostThenReturn(Mono.just(resp));
Mono<String> returnedMono = clientUnderTest
.putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, policyJson, POLICY_TYPE_1_ID));
final String expUrl = policiesUrl() + "/" + POLICY_1_ID;
whenAsyncPostThenReturn(Mono.just(resp));
Mono<String> 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();
.nearRtRicUrl(expUrl) //
.body(policyJson) //
.build();
.block();
assertEquals("OK", returned, "");
final String expUrl = policiesUrl() + "/" + POLICY_1_ID;
.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);
.nearRtRicUrl(expUrl) //
.build();
String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams);
assertEquals("OK", returnedStatus, "unexpected status");
final String expUrl = policiesUrl() + "/" + POLICY_1_ID + "/status";
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);
.nearRtRicUrl(expUrl) //
.build();
String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams);
whenPostReturnOkResponse();
A1ProtocolType returnedVersion = clientUnderTest.getProtocolVersion().block();
assertEquals(A1ProtocolType.SDNC_OSC_STD_V1_1, returnedVersion, "");
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() {
}
private void whenPostReturnOkResponse() {
- AdapterResponse adapterResponse = ImmutableAdapterResponse.builder() //
+ AdapterOutput adapterOutput = ImmutableAdapterOutput.builder() //
.body("OK") //
.httpStatus(200) //
.build();
.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));
}
whenAsyncPostThenReturn(Mono.just(resp));
}