summaryrefslogtreecommitdiffstats
path: root/policy-executor-stub
diff options
context:
space:
mode:
authorToineSiebelink <toine.siebelink@est.tech>2024-07-29 17:45:52 +0100
committerToineSiebelink <toine.siebelink@est.tech>2024-07-31 17:18:58 +0100
commit53375821fa2d156785a92ef57ef7948389260cc1 (patch)
treef7b63a0db182791f3fa2b73ea97355e692939e41 /policy-executor-stub
parent9d8e6852b2ebfffca8204557a005aba27c1fc581 (diff)
Refactor OpenAPI Policy Executor
- replace payload with request(s) - replace payloadType with schema (one schema for each operation) - include conflict error response in OpenAPI - introduce 4 schemas in NCMP (doc module) for create, update, patch & delete - udpate stub & test to follow new API and use one schema for testign purposes Issue-ID: CPS-2335 Change-Id: Ifc40062ae83429a9ffba350ec3bcc28cb7147293 Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Diffstat (limited to 'policy-executor-stub')
-rw-r--r--policy-executor-stub/pom.xml19
-rw-r--r--policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java47
-rw-r--r--policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy82
3 files changed, 109 insertions, 39 deletions
diff --git a/policy-executor-stub/pom.xml b/policy-executor-stub/pom.xml
index f076a2c55c..afdc1c7d3b 100644
--- a/policy-executor-stub/pom.xml
+++ b/policy-executor-stub/pom.xml
@@ -22,6 +22,11 @@
</properties>
<dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <scope>provided</scope>
+ </dependency>
<!-- S P R I N G D E P E N D E N C I E S -->
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -163,6 +168,20 @@
</execution>
</executions>
</plugin>
+
+ <plugin>
+ <groupId>org.jsonschema2pojo</groupId>
+ <artifactId>jsonschema2pojo-maven-plugin</artifactId>
+ <configuration>
+ <useJakartaValidation>true</useJakartaValidation>
+ <sourceDirectory>${project.parent.basedir}/../docs/schemas/policy-executor</sourceDirectory>
+ <targetPackage>org.onap.cps.policyexecutor.stub.model</targetPackage>
+ <generateBuilders>true</generateBuilders>
+ <serializable>true</serializable>
+ <includeJsr303Annotations>true</includeJsr303Annotations>
+ </configuration>
+ </plugin>
+
</plugins>
</build>
diff --git a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java
index a5ec6dcac9..5b3a9931a0 100644
--- a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java
+++ b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java
@@ -20,12 +20,17 @@
package org.onap.cps.policyexecutor.stub.controller;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import lombok.RequiredArgsConstructor;
import org.onap.cps.policyexecutor.stub.api.PolicyExecutorApi;
+import org.onap.cps.policyexecutor.stub.model.NcmpDelete;
import org.onap.cps.policyexecutor.stub.model.PolicyExecutionRequest;
import org.onap.cps.policyexecutor.stub.model.PolicyExecutionResponse;
+import org.onap.cps.policyexecutor.stub.model.Request;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.ResponseEntity;
@@ -34,9 +39,13 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("${rest.api.policy-executor-base-path}")
+@RequiredArgsConstructor
public class PolicyExecutorStubController implements PolicyExecutorApi {
- private final Pattern errorCodePattern = Pattern.compile("(\\d{3})");
+ private final ObjectMapper objectMapper;
+
+ private static final Pattern ERROR_CODE_PATTERN = Pattern.compile("(\\d{3})");
+
private int decisionCounter = 0;
@Override
@@ -44,31 +53,55 @@ public class PolicyExecutorStubController implements PolicyExecutorApi {
final String action,
final PolicyExecutionRequest policyExecutionRequest,
final String authorization) {
- if (policyExecutionRequest.getPayload().isEmpty()) {
+ if (policyExecutionRequest.getRequests().isEmpty()) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+ final Request firstRequest = policyExecutionRequest.getRequests().iterator().next();
+ if ("ncmp-delete-schema:1.0.0".equals(firstRequest.getSchema())) {
+ return handleNcmpDeleteSchema(firstRequest);
+ }
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
+
+ private ResponseEntity<PolicyExecutionResponse> handleNcmpDeleteSchema(final Request request) {
+ final NcmpDelete ncmpDelete;
+ try {
+ ncmpDelete = objectMapper.readValue((String) request.getData(), NcmpDelete.class);
+ } catch (final JsonProcessingException e) {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
- final String firstTargetFdn = policyExecutionRequest.getPayload().iterator().next().getTargetFdn();
+ final String targetIdentifier = ncmpDelete.getTargetIdentifier();
+ if (targetIdentifier == null) {
+ return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+ }
- final Matcher matcher = errorCodePattern.matcher(firstTargetFdn);
+ final Matcher matcher = ERROR_CODE_PATTERN.matcher(targetIdentifier);
if (matcher.find()) {
final int errorCode = Integer.parseInt(matcher.group(1));
return new ResponseEntity<>(HttpStatusCode.valueOf(errorCode));
}
+ return createPolicyExecutionResponse(targetIdentifier);
+ }
+
+ private ResponseEntity<PolicyExecutionResponse> createPolicyExecutionResponse(final String targetIdentifier) {
final String decisionId = String.valueOf(++decisionCounter);
final String decision;
final String message;
- if (firstTargetFdn.toLowerCase(Locale.getDefault()).contains("cps-is-great")) {
- decision = "permit";
+ if (targetIdentifier.toLowerCase(Locale.getDefault()).contains("cps-is-great")) {
+ decision = "allow";
message = "All good";
} else {
decision = "deny";
- message = "Only FDNs containing 'cps-is-great' are permitted";
+ message = "Only FDNs containing 'cps-is-great' are allowed";
}
+
final PolicyExecutionResponse policyExecutionResponse =
new PolicyExecutionResponse(decisionId, decision, message);
+
return ResponseEntity.ok(policyExecutionResponse);
}
+
}
diff --git a/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy
index 871db81ac8..efb12ac619 100644
--- a/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy
+++ b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy
@@ -21,9 +21,10 @@
package org.onap.cps.policyexecutor.stub.controller
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.policyexecutor.stub.model.Payload
+import org.onap.cps.policyexecutor.stub.model.NcmpDelete
import org.onap.cps.policyexecutor.stub.model.PolicyExecutionRequest
import org.onap.cps.policyexecutor.stub.model.PolicyExecutionResponse
+import org.onap.cps.policyexecutor.stub.model.Request
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
import org.springframework.http.HttpStatus
@@ -44,11 +45,9 @@ class PolicyExecutorStubControllerSpec extends Specification {
def url = '/policy-executor/api/v1/some-action'
- def 'Execute Policy Actions.'() {
- given: 'a policy execution request with target fdn: #targetFdn'
- def payload = new Payload(targetFdn, 'some change request')
- def policyExecutionRequest = new PolicyExecutionRequest('some payload type','some decision type', [payload])
- def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
+ def 'Execute policy action.'() {
+ given: 'a policy execution request with target: #targetIdentifier'
+ def requestBody = createRequestBody(targetIdentifier)
when: 'request is posted'
def response = mockMvc.perform(post(url)
.header('Authorization','some string')
@@ -61,19 +60,17 @@ class PolicyExecutorStubControllerSpec extends Specification {
def responseBody = response.contentAsString
def policyExecutionResponse = objectMapper.readValue(responseBody, PolicyExecutionResponse.class)
assert policyExecutionResponse.decisionId == expectedDecsisonId
- assert policyExecutionResponse.decision == expectedDecsison
+ assert policyExecutionResponse.decision == expectedDecision
assert policyExecutionResponse.message == expectedMessage
where: 'the following targets are used'
- targetFdn || expectedDecsisonId | expectedDecsison | expectedMessage
- 'some fdn' || '1' | 'deny' | "Only FDNs containing 'cps-is-great' are permitted"
- 'fdn with cps-is-great' || '2' | 'permit' | "All good"
+ targetIdentifier || expectedDecsisonId | expectedDecision | expectedMessage
+ 'some fdn' || '1' | 'deny' | "Only FDNs containing 'cps-is-great' are allowed"
+ 'fdn with cps-is-great' || '2' | 'allow' | 'All good'
}
- def 'Execute Policy Action with a HTTP Error Code.'() {
+ def 'Execute policy action with a HTTP error code.'() {
given: 'a policy execution request with a target fdn with a 3-digit error code'
- def payload = new Payload('fdn with error code 418', 'some change request')
- def policyExecutionRequest = new PolicyExecutionRequest('some payload type','some decision type', [payload])
- def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
+ def requestBody = createRequestBody('target with error code 418')
when: 'request is posted'
def response = mockMvc.perform(post(url)
.header('Authorization','some string')
@@ -84,11 +81,9 @@ class PolicyExecutorStubControllerSpec extends Specification {
assert response.status == 418
}
- def 'Execute Policy Action without Authorization Header.'() {
+ def 'Execute policy action without authorization header.'() {
given: 'a valid policy execution request'
- def payload = new Payload('some fdn', 'some change request')
- def policyExecutionRequest = new PolicyExecutionRequest('some payload type','some decision type', [payload])
- def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
+ def requestBody = createRequestBody('some target')
when: 'request is posted without authorization header'
def response = mockMvc.perform(post(url)
.contentType(MediaType.APPLICATION_JSON)
@@ -98,9 +93,9 @@ class PolicyExecutorStubControllerSpec extends Specification {
assert response.status == HttpStatus.OK.value()
}
- def 'Execute Policy Action with Empty Payload.'() {
- given: 'a policy execution request with empty payload list'
- def policyExecutionRequest = new PolicyExecutionRequest('some payload type','some decision type', [])
+ def 'Execute policy action with no requests.'() {
+ given: 'a policy execution request'
+ def policyExecutionRequest = new PolicyExecutionRequest('some decision type', [])
def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
when: 'request is posted'
def response = mockMvc.perform(post(url)
@@ -112,26 +107,49 @@ class PolicyExecutorStubControllerSpec extends Specification {
assert response.status == HttpStatus.BAD_REQUEST.value()
}
- def 'Execute Policy Action without other required attributes.'() {
- given: 'a policy execution request with payloadType=#payloadType, decisionType=decisionType, targetFdn=#targetFdn, changeRequest=#changeRequest'
- def payload = new Payload(targetFdn, changeRequest)
- def policyExecutionRequest = new PolicyExecutionRequest(payloadType, decisionType, [payload])
+ def 'Execute policy action with invalid json for request data.'() {
+ given: 'a policy execution request'
+ def request = new Request('ncmp-delete-schema:1.0.0', 'invalid json')
+ def policyExecutionRequest = new PolicyExecutionRequest('some decision type', [request])
def requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
when: 'request is posted'
def response = mockMvc.perform(post(url)
+ .header('Authorization','some string')
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestBody))
+ .andReturn().response
+ then: 'response status is Bad Request'
+ assert response.status == HttpStatus.BAD_REQUEST.value()
+ }
+
+ def 'Execute policy action with missing or invalid attributes.'() {
+ given: 'a policy execution request with decisionType=#decisionType, schema=#schema, targetIdentifier=#targetIdentifier'
+ def requestBody = createRequestBody(decisionType, schema, targetIdentifier)
+ when: 'request is posted'
+ def response = mockMvc.perform(post(url)
.header('Authorization','something')
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody))
.andReturn().response
then: 'response status as expected'
assert response.status == expectedStatus.value()
- where: 'following parameters are populated or not'
- payloadType | decisionType | targetFdn | changeRequest || expectedStatus
- 'something' | 'something' | 'something' | 'something' || HttpStatus.OK
- null | 'something' | 'something' | 'something' || HttpStatus.BAD_REQUEST
- 'something' | null | 'something' | 'something' || HttpStatus.BAD_REQUEST
- 'something' | 'something' | null | 'something' || HttpStatus.BAD_REQUEST
- 'something' | 'something' | 'something' | null || HttpStatus.BAD_REQUEST
+ where: 'following parameters are used'
+ decisionType | schema | targetIdentifier || expectedStatus
+ 'something' | 'ncmp-delete-schema:1.0.0' | 'something' || HttpStatus.OK
+ null | 'ncmp-delete-schema:1.0.0' | 'something' || HttpStatus.BAD_REQUEST
+ 'something' | 'other schema' | 'something' || HttpStatus.BAD_REQUEST
+ 'something' | 'ncmp-delete-schema:1.0.0' | null || HttpStatus.BAD_REQUEST
+ }
+
+ def createRequestBody(decisionType, schema, targetIdentifier) {
+ def ncmpDelete = new NcmpDelete(targetIdentifier: targetIdentifier)
+ def request = new Request(schema, objectMapper.writeValueAsString(ncmpDelete))
+ def policyExecutionRequest = new PolicyExecutionRequest(decisionType, [request])
+ return objectMapper.writeValueAsString(policyExecutionRequest)
+ }
+
+ def createRequestBody(targetIdentifier) {
+ return createRequestBody('some decision type', 'ncmp-delete-schema:1.0.0', targetIdentifier)
}
}