aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src/main
diff options
context:
space:
mode:
authorToineSiebelink <toine.siebelink@est.tech>2024-09-19 17:23:58 +0100
committerToine Siebelink <toine.siebelink@est.tech>2024-09-25 08:18:46 +0000
commit2bcccff7e2891f708cedc08cdbf969025d63019e (patch)
treec0300990499012dd7b87d62d3f5c4cc78d068e41 /cps-ncmp-service/src/main
parent39e4eef51e44b73569fe82e214afab04edc5bba0 (diff)
Policy Executor: handle errors
- configurable default answer - apply default answer upon non 2xx response - delayed default webclient read timeout - add custom timeout method with original read timeout in seconds - apply default answer upon timeout - add integration test with short timeout error scenario Issue-ID: CPS-2412 Change-Id: I62527a27e426c2f01fda2182ebd2513242c29ac1 Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Diffstat (limited to 'cps-ncmp-service/src/main')
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java6
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java73
2 files changed, 58 insertions, 21 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java
index 0903c671b5..30e7cd5e0b 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/PolicyExecutorHttpClientConfig.java
@@ -20,6 +20,7 @@
package org.onap.cps.ncmp.config;
+import jakarta.annotation.PostConstruct;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -38,4 +39,9 @@ public class PolicyExecutorHttpClientConfig {
public static class AllServices extends ServiceConfig {
private String connectionProviderName = "policyExecutorConfig";
}
+
+ @PostConstruct
+ public void increaseReadTimeoutOfWebClient() {
+ allServices.setReadTimeoutInSeconds(allServices.getReadTimeoutInSeconds() + 10);
+ }
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java
index 96771e30f1..caed28a648 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/policyexecutor/PolicyExecutor.java
@@ -23,16 +23,18 @@ package org.onap.cps.ncmp.impl.data.policyexecutor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
+import java.time.Duration;
+import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeoutException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.data.models.OperationType;
import org.onap.cps.ncmp.api.exceptions.NcmpException;
import org.onap.cps.ncmp.api.exceptions.PolicyExecutorException;
-import org.onap.cps.ncmp.api.exceptions.ServerNcmpException;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
import org.onap.cps.ncmp.impl.utils.http.RestServiceUrlTemplateBuilder;
import org.onap.cps.ncmp.impl.utils.http.UrlTemplateParameters;
@@ -52,12 +54,18 @@ public class PolicyExecutor {
@Value("${ncmp.policy-executor.enabled:false}")
private boolean enabled;
+ @Value("${ncmp.policy-executor.defaultDecision:deny}")
+ private String defaultDecision;
+
@Value("${ncmp.policy-executor.server.address:http://policy-executor}")
private String serverAddress;
@Value("${ncmp.policy-executor.server.port:8080}")
private String serverPort;
+ @Value("${ncmp.policy-executor.httpclient.all-services.readTimeoutInSeconds:30}")
+ private long readTimeoutInSeconds;
+
@Qualifier("policyExecutorWebClient")
private final WebClient policyExecutorWebClient;
@@ -80,26 +88,26 @@ public class PolicyExecutor {
final String changeRequestAsJson) {
log.trace("Policy Executor Enabled: {}", enabled);
if (enabled) {
- final ResponseEntity<JsonNode> responseEntity =
- getPolicyExecutorResponse(yangModelCmHandle, operationType, authorization, resourceIdentifier,
- changeRequestAsJson);
-
+ ResponseEntity<JsonNode> responseEntity = null;
+ try {
+ responseEntity =
+ getPolicyExecutorResponse(yangModelCmHandle, operationType, authorization, resourceIdentifier,
+ changeRequestAsJson);
+ } catch (final RuntimeException runtimeException) {
+ processException(runtimeException);
+ }
if (responseEntity == null) {
- log.warn("No valid response from policy, ignored");
+ log.warn("No valid response from Policy Executor, ignored");
return;
}
-
if (responseEntity.getStatusCode().is2xxSuccessful()) {
if (responseEntity.getBody() == null) {
- log.warn("No valid response body from policy, ignored");
+ log.warn("No valid response body from Policy Executor, ignored");
return;
}
- processResponse(responseEntity.getBody());
+ processSuccessResponse(responseEntity.getBody());
} else {
- log.warn("Policy Executor invocation failed with status {}",
- responseEntity.getStatusCode().value());
- throw new ServerNcmpException("Policy Executor invocation failed", "HTTP status code: "
- + responseEntity.getStatusCode().value());
+ processNon2xxResponse(responseEntity.getStatusCode().value());
}
}
}
@@ -143,8 +151,6 @@ public class PolicyExecutor {
final String authorization,
final String resourceIdentifier,
final String changeRequestAsJson) {
-
-
final Map<String, Object> requestAsMap = getSingleRequestAsMap(yangModelCmHandle,
operationType,
resourceIdentifier,
@@ -163,21 +169,46 @@ public class PolicyExecutor {
.body(BodyInserters.fromValue(bodyAsObject))
.retrieve()
.toEntity(JsonNode.class)
+ .timeout(Duration.of(readTimeoutInSeconds, ChronoUnit.SECONDS))
.block();
}
- private static void processResponse(final JsonNode responseBody) {
+ private void processNon2xxResponse(final int httpStatusCode) {
+ processFallbackResponse("Policy Executor returned HTTP Status code " + httpStatusCode + ".");
+ }
+
+ private void processException(final RuntimeException runtimeException) {
+ if (runtimeException.getCause() instanceof TimeoutException) {
+ processFallbackResponse("Policy Executor request timed out.");
+ } else {
+ log.warn("Request to Policy Executor failed with unexpected exception", runtimeException);
+ throw runtimeException;
+ }
+ }
+
+ private void processFallbackResponse(final String message) {
+ final String decisionId = "N/A";
+ final String decision = defaultDecision;
+ final String warning = message + " Falling back to configured default decision: " + defaultDecision;
+ log.warn(warning);
+ processDecision(decisionId, decision, warning);
+ }
+
+ private static void processSuccessResponse(final JsonNode responseBody) {
final String decisionId = responseBody.path("decisionId").asText("unknown id");
- log.trace("Policy Executor Decision ID: {} ", decisionId);
final String decision = responseBody.path("decision").asText("unknown");
+ final String messageFromPolicyExecutor = responseBody.path("message").asText();
+ processDecision(decisionId, decision, messageFromPolicyExecutor);
+ }
+
+ private static void processDecision(final String decisionId, final String decision, final String details) {
+ log.trace("Policy Executor decision id: {} ", decisionId);
if ("allow".equals(decision)) {
- log.trace("Policy Executor allows the operation");
+ log.trace("Operation allowed.");
} else {
log.warn("Policy Executor decision: {}", decision);
- final String details = responseBody.path("message").asText();
log.warn("Policy Executor message: {}", details);
- final String message = "Policy Executor did not allow request. Decision #"
- + decisionId + " : " + decision;
+ final String message = "Operation not allowed. Decision id " + decisionId + " : " + decision;
throw new PolicyExecutorException(message, details);
}
}