Create PolicyExecutor Stub 01/138401/3
authorToineSiebelink <toine.siebelink@est.tech>
Thu, 4 Jul 2024 14:15:36 +0000 (15:15 +0100)
committerToineSiebelink <toine.siebelink@est.tech>
Mon, 8 Jul 2024 16:07:48 +0000 (17:07 +0100)
- Generate interface from OpenApi in RTD docs
- Fixed Content Type in OpenAPI
- Fixed Paths in OpenAPI
- Made Authorization header compulsory in OpenAPI
- All 'enum' values in OpenAPI lowercase (in linr with CPS/NCMP conventions)
- Added impl with some basic functionality
- Added testware
- Pom includes docker image creation
- Docker compose updated to deploy stub

Issue-ID: CPS-2301
Change-Id: I462ad5c70474b2813fc04005c0d20a1b15b574ec
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Signed-off-by: sourabh_sourabh <sourabh.sourabh@est.tech>
cps-parent/pom.xml
docker-compose/docker-compose.yml
docs/api/swagger/policy-executor/openapi.yaml
jacoco-report/pom.xml
policy-executor-stub/pom.xml [new file with mode: 0644]
policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/PolicyExecutorApplication.java [new file with mode: 0644]
policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubController.java [new file with mode: 0644]
policy-executor-stub/src/main/resources/application.yml [new file with mode: 0644]
policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/PolicyExecutorApplicationSpec.groovy [new file with mode: 0644]
policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/controller/PolicyExecutorStubControllerSpec.groovy [new file with mode: 0644]
pom.xml

index 591095a..ba63944 100644 (file)
                         <exclude>org/onap/cps/ncmp/rest/model/*</exclude>
                         <exclude>org/onap/cps/**/*MapperImpl.class</exclude>
                         <exclude>org/onap/cps/ncmp/rest/stub/*</exclude>
+                        <exclude>org/onap/cps/policyexecutor/stub/model/*</exclude>
                     </excludes>
                 </configuration>
                 <executions>
index 5620c4c..81d4d15 100644 (file)
@@ -136,6 +136,15 @@ services:
       - dmi-stub
       - dmi-service
 
+  policy-executor-stub:
+    container_name: policy-executor-stub
+    image: ${DOCKER_REPO:-nexus3.onap.org:10003}/onap/policy-executor-stub:latest
+    ports:
+      - 8785:8080
+    restart: unless-stopped
+    profiles:
+      - policy-executor-stub
+
   prometheus:
     container_name: prometheus-container
     image: prom/prometheus:latest
index 868f2da..5becd9a 100644 (file)
 openapi: 3.0.3
 info:
   title: Policy Executor
-  description: "Allows NCMP to execute a policy defined by a third party implementation before proceeding with an operation"
+  description: "Allows NCMP to execute a policy defined by a third party implementation before proceeding with a CM operation"
   version: 1.0.0
 servers:
-  - url: /policy-executor
+  - url: /policy-executor/api
 tags:
   - name: policy-executor
     description: "Execute all your policies"
 paths:
-  /policy-executor/api/v1/{action}:
+  /v1/{action}:
     post:
       description: "Fire a Policy action"
       operationId: executePolicyAction
       parameters:
+        - $ref: '#/components/parameters/authorizationInHeader'
         - $ref: '#/components/parameters/actionInPath'
       requestBody:
         required: true
         description: "The action request body"
         content:
-          application/3gpp-json-patch+json:
+          application/json:
             schema:
               $ref: '#/components/schemas/PolicyExecutionRequest'
       tags:
@@ -102,12 +103,12 @@ components:
       properties:
         payloadType:
           type: string
-          description: "The type of payload. Currently supported options: 'CM_Write'"
-          example: "CM_Write"
+          description: "The type of payload. Currently supported options: 'cm_write'"
+          example: "cm_write"
         decisionType:
           type: string
-          description: "The type of decision. Currently supported options: 'Allow'"
-          example: "Allow"
+          description: "The type of decision. Currently supported options: 'permit'"
+          example: "permit"
         payload:
           type: array
           items:
@@ -126,8 +127,8 @@ components:
           example: "550e8400-e29b-41d4-a716-446655440000"
         decision:
           type: string
-          description: "The decision outcome. Currently supported values: 'Allow','Deny'"
-          example: "Deny"
+          description: "The decision outcome. Currently supported values: 'permit','deny'"
+          example: "deny"
         message:
           type: string
           description: "Additional information regarding the decision outcome"
@@ -205,10 +206,17 @@ components:
     actionInPath:
       name: action
       in: path
-      description: "The policy action. Currently supported options: 'Execute'"
+      description: "The policy action. Currently supported options: 'execute'"
       required: true
       schema:
         type: string
-        example: "Execute"
+        example: "execute"
+    authorizationInHeader:
+      name: Authorization
+      in: header
+      required: true
+      schema:
+        type: string
+
 security:
   - bearerAuth: []
index 01d47bf..2610ffa 100644 (file)
             <artifactId>integration-test</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>policy-executor-stub</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/policy-executor-stub/pom.xml b/policy-executor-stub/pom.xml
new file mode 100644 (file)
index 0000000..99e621d
--- /dev/null
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.onap.cps</groupId>
+        <artifactId>cps-parent</artifactId>
+        <version>3.5.1-SNAPSHOT</version>
+        <relativePath>../cps-parent/pom.xml</relativePath>
+    </parent>
+
+    <artifactId>policy-executor-stub</artifactId>
+
+    <properties>
+        <app>org.onap.cps.policyexecutor.stub.PolicyExecutorApplication</app>
+        <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+        <base.image>${docker.pull.registry}/onap/integration-java17:12.0.0</base.image>
+        <image.name>policy-executor-stub</image.name>
+        <image.tag>${project.version}-${maven.build.timestamp}</image.tag>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+        <!-- S P R I N G   D E P E N D E N C I E S -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-jetty</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <!-- O P E N   A P I   D E P E N D E N C I E S -->
+        <dependency>
+            <groupId>io.swagger.core.v3</groupId>
+            <artifactId>swagger-annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springdoc</groupId>
+            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
+        </dependency>
+        <!-- T E S T   D E P E N D E N C I E S -->
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.groovy</groupId>
+            <artifactId>groovy-json</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.spockframework</groupId>
+            <artifactId>spock-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.spockframework</groupId>
+            <artifactId>spock-spring</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>com.google.cloud.tools</groupId>
+                    <artifactId>jib-maven-plugin</artifactId>
+                    <configuration>
+                        <container>
+                            <mainClass>${app}</mainClass>
+                            <creationTime>USE_CURRENT_TIMESTAMP</creationTime>
+                        </container>
+                        <from>
+                            <image>${base.image}</image>
+                        </from>
+                        <to>
+                            <tags>
+                                <tag>latest</tag>
+                            </tags>
+                            <image>${docker.push.registry}/onap/${image.name}:${image.tag}</image>
+                        </to>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <phase>package</phase>
+                            <id>build</id>
+                            <goals>
+                                <goal>dockerBuild</goal>
+                            </goals>
+                        </execution>
+                        <execution>
+                            <phase>deploy</phase>
+                            <id>buildAndPush</id>
+                            <goals>
+                                <goal>build</goal>
+                            </goals>
+                        </execution>
+                    </executions>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <!-- Swagger code generation. -->
+            <plugin>
+                <groupId>org.openapitools</groupId>
+                <artifactId>openapi-generator-maven-plugin</artifactId>
+                <version>6.6.0</version>
+                <executions>
+                    <execution>
+                        <id>code-gen</id>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <configuration>
+                            <inputSpec>${project.parent.basedir}/../docs/api/swagger/policy-executor/openapi.yaml</inputSpec>
+                            <modelPackage>org.onap.cps.policyexecutor.stub.model</modelPackage>
+                            <apiPackage>org.onap.cps.policyexecutor.stub.api</apiPackage>
+                            <generatorName>spring</generatorName>
+                            <generateSupportingFiles>false</generateSupportingFiles>
+                            <configOptions>
+                                <sourceFolder>src/gen/java</sourceFolder>
+                                <dateLibrary>java11</dateLibrary>
+                                <interfaceOnly>true</interfaceOnly>
+                                <useSpringBoot3>true</useSpringBoot3>
+                                <useTags>true</useTags>
+                                <openApiNullable>false</openApiNullable>
+                                <skipDefaultInterface>true</skipDefaultInterface>
+                            </configOptions>
+                        </configuration>
+                    </execution>
+                    <execution>
+                        <id>openapi-yaml-gen</id>
+                        <goals>
+                            <goal>generate</goal>
+                        </goals>
+                        <phase>compile</phase>
+                        <configuration>
+                            <inputSpec>${project.parent.basedir}/../docs/api/swagger/policy-executor/openapi.yaml</inputSpec>
+                            <generatorName>openapi-yaml</generatorName>
+                            <configOptions>
+                                <outputFile>openapi.yaml</outputFile>
+                            </configOptions>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>docker</id>
+            <activation>
+                <activeByDefault>true</activeByDefault>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>com.google.cloud.tools</groupId>
+                        <artifactId>jib-maven-plugin</artifactId>
+                        <version>3.3.2</version>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+
+</project>
diff --git a/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/PolicyExecutorApplication.java b/policy-executor-stub/src/main/java/org/onap/cps/policyexecutor/stub/PolicyExecutorApplication.java
new file mode 100644 (file)
index 0000000..367a470
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2024 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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.policyexecutor.stub;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class PolicyExecutorApplication {
+    public static void main(final String[] args) {
+        SpringApplication.run(PolicyExecutorApplication.class, args);
+    }
+}
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
new file mode 100644 (file)
index 0000000..7989c3f
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2024 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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.policyexecutor.stub.controller;
+
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.onap.cps.policyexecutor.stub.api.PolicyExecutorApi;
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionRequest;
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionResponse;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.HttpStatusCode;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("${rest.api.policy-executor-base-path}")
+public class PolicyExecutorStubController implements PolicyExecutorApi {
+
+    private final Pattern errorCodePattern = Pattern.compile("(\\d{3})");
+    private int decisionCounter = 0;
+
+    @Override
+    public ResponseEntity<PolicyExecutionResponse> executePolicyAction(
+                                                     final String authorization,
+                                                     final String action,
+                                                     final PolicyExecutionRequest policyExecutionRequest) {
+        if (policyExecutionRequest.getPayload().isEmpty()) {
+            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+        }
+
+        final String firstTargetFdn = policyExecutionRequest.getPayload().iterator().next().getTargetFdn();
+
+        final Matcher matcher = errorCodePattern.matcher(firstTargetFdn);
+        if (matcher.find()) {
+            final int errorCode = Integer.parseInt(matcher.group(1));
+            return new ResponseEntity<>(HttpStatusCode.valueOf(errorCode));
+        }
+
+        final PolicyExecutionResponse policyExecutionResponse = new PolicyExecutionResponse();
+        policyExecutionResponse.setDecisionId(String.valueOf(++decisionCounter));
+
+        if (firstTargetFdn.toLowerCase(Locale.getDefault()).contains("cps-is-great")) {
+            policyExecutionResponse.setDecision("permit");
+        } else {
+            policyExecutionResponse.setDecision("deny");
+            policyExecutionResponse.setMessage("Only FDNs containing 'cps-is-great' are permitted");
+        }
+        return ResponseEntity.ok(policyExecutionResponse);
+    }
+}
diff --git a/policy-executor-stub/src/main/resources/application.yml b/policy-executor-stub/src/main/resources/application.yml
new file mode 100644 (file)
index 0000000..f713a15
--- /dev/null
@@ -0,0 +1,20 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2024 Nordix
+# ================================================================================
+# 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.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#  ============LICENSE_END=========================================================
+
+rest:
+    api:
+        policy-executor-base-path: /policy-executor/api
diff --git a/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/PolicyExecutorApplicationSpec.groovy b/policy-executor-stub/src/test/groovy/org/onap/cps/policyexecutor/stub/PolicyExecutorApplicationSpec.groovy
new file mode 100644 (file)
index 0000000..565932d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2024 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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.policyexecutor.stub
+
+import spock.lang.Specification
+
+class PolicyExecutorApplicationSpec extends Specification {
+
+    def 'Execute Policy Action.'() {
+        when: 'Starting the application (for coverage)'
+            PolicyExecutorApplication.main()
+        then: 'all goes well'
+            noExceptionThrown()
+    }
+
+}
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
new file mode 100644 (file)
index 0000000..593394f
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2024 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.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+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.PolicyExecutionRequest
+import org.onap.cps.policyexecutor.stub.model.PolicyExecutionResponse
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
+import org.springframework.http.HttpStatus
+import org.springframework.http.MediaType
+import org.springframework.test.web.servlet.MockMvc
+import spock.lang.Specification
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
+
+@WebMvcTest(PolicyExecutorStubController)
+class PolicyExecutorStubControllerSpec extends Specification {
+
+    @Autowired
+    MockMvc mockMvc
+
+    @Autowired
+    ObjectMapper objectMapper
+
+    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)
+        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 Ok'
+            assert response.status == HttpStatus.OK.value()
+        and: 'the response body has the expected decision details'
+            def responseBody = response.contentAsString
+            def policyExecutionResponse = objectMapper.readValue(responseBody, PolicyExecutionResponse.class)
+            assert policyExecutionResponse.decisionId == expectedDecsisonId
+            assert policyExecutionResponse.decision == expectedDecsison
+            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'          | null
+    }
+
+    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)
+        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 the same error code as in target fdn'
+            assert response.status == 418
+    }
+
+    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)
+        when: 'request is posted without authorization header'
+            def response = mockMvc.perform(post(url)
+                .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 Empty Payload.'() {
+        given: 'a policy execution request with empty payload list'
+            def policyExecutionRequest = new PolicyExecutionRequest('some payload type','some decision type', [])
+            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 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 requestBody = objectMapper.writeValueAsString(policyExecutionRequest)
+        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
+    }
+
+}
diff --git a/pom.xml b/pom.xml
index fcead19..9a06b7b 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -67,6 +67,7 @@
         <module>spotbugs</module>\r
         <module>cps-application</module>\r
         <module>jacoco-report</module>\r
+        <module>policy-executor-stub</module>\r
     </modules>\r
 \r
     <build>\r