Tie XACML REST Decision 12/84012/6
authorPamela Dragosh <pdragosh@research.att.com>
Tue, 2 Apr 2019 21:48:38 +0000 (14:48 -0700)
committerPamela Dragosh <pdragosh@research.att.com>
Thu, 4 Apr 2019 12:18:59 +0000 (08:18 -0400)
Ties the decision API to the applications. Adds a static
application manager class to manager the applications.

Added applicationPath as a parameter to be supported in
the Json parameter group.

Issue-ID: POLICY-1440
Change-Id: I43cb44b3e308aadcf258fd987f3b53944c2edb72
Signed-off-by: Pamela Dragosh <pdragosh@research.att.com>
16 files changed:
main/src/main/java/org/onap/policy/pdpx/main/parameters/RestServerBuilder.java
main/src/main/java/org/onap/policy/pdpx/main/parameters/XacmlPdpParameterGroup.java
main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java [new file with mode: 0644]
main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestController.java
main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java
main/src/main/java/org/onap/policy/pdpx/main/rest/model/Decision.java [deleted file]
main/src/main/java/org/onap/policy/pdpx/main/rest/provider/DecisionProvider.java
main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java
main/src/test/java/org/onap/policy/pdpx/main/parameters/TestXacmlPdpParameterGroup.java
main/src/test/java/org/onap/policy/pdpx/main/parameters/TestXacmlPdpParameterHandler.java
main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java [new file with mode: 0644]
main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpRestServer.java
main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpStatistics.java
main/src/test/resources/parameters/MinimumParameters.json
main/src/test/resources/parameters/XacmlPdpConfigParameters.json
main/src/test/resources/parameters/XacmlPdpConfigParameters_Https.json

index 90bc09f..6c729f2 100644 (file)
@@ -28,7 +28,6 @@ public class RestServerBuilder {
     private boolean https;
     private boolean aaf;
 
-
     public String getHost() {
         return host;
     }
index 2c97264..e442a08 100644 (file)
@@ -30,17 +30,22 @@ import org.onap.policy.common.utils.validation.ParameterValidationUtils;
  *
  */
 public class XacmlPdpParameterGroup implements ParameterGroup {
+    private static final String PARAM_REST_SERVER = "restServerParameters";
+    private static final String PARAM_APPLICATION_PATH = "applicationPath";
     private String name;
     private RestServerParameters restServerParameters;
+    private String applicationPath;
 
     /**
      * Create the xacml pdp parameter group.
      *
      * @param name the parameter group name
      */
-    public XacmlPdpParameterGroup(final String name, final RestServerParameters restServerParameters) {
+    public XacmlPdpParameterGroup(final String name, final RestServerParameters restServerParameters,
+            final String applicationPath) {
         this.name = name;
         this.restServerParameters = restServerParameters;
+        this.applicationPath = applicationPath;
     }
 
     /**
@@ -72,6 +77,15 @@ public class XacmlPdpParameterGroup implements ParameterGroup {
         return restServerParameters;
     }
 
+    /**
+     * Returns the path where applications will store their data.
+     *
+     * @return String to the path
+     */
+    public String getApplicationPath() {
+        return applicationPath;
+    }
+
     /**
      * Validate the parameter group.
      *
@@ -84,10 +98,17 @@ public class XacmlPdpParameterGroup implements ParameterGroup {
             validationResult.setResult("name", ValidationStatus.INVALID, "must be a non-blank string");
         }
         if (restServerParameters == null) {
-            validationResult.setResult("restServerParameters", ValidationStatus.INVALID,
+            validationResult.setResult(PARAM_REST_SERVER, ValidationStatus.INVALID,
                     "must have restServerParameters to configure xacml pdp rest server");
         } else {
-            validationResult.setResult("restServerParameters", restServerParameters.validate());
+            validationResult.setResult(PARAM_REST_SERVER, restServerParameters.validate());
+        }
+        //
+        // Validate the application path directory
+        //
+        if (applicationPath == null || applicationPath.isEmpty()) {
+            validationResult.setResult(PARAM_APPLICATION_PATH, ValidationStatus.INVALID,
+                    "must have application path for applications to store policies and data.");
         }
         return validationResult;
     }
diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpApplicationManager.java
new file mode 100644 (file)
index 0000000..c97166c
--- /dev/null
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.policy.pdpx.main.rest;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class XacmlPdpApplicationManager {
+    private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpApplicationManager.class);
+
+    private static boolean needsInit = true;
+    private static ServiceLoader<XacmlApplicationServiceProvider> applicationLoader;
+    private static Map<String, XacmlApplicationServiceProvider> providerActionMap = new HashMap<>();
+
+    private XacmlPdpApplicationManager() {
+        super();
+    }
+
+    /**
+     * One time to initialize the applications upon startup.
+     */
+    public static void initializeApplications(Path applicationPath) {
+        //
+        // If we have already done this
+        //
+        if (! needsInit) {
+            LOGGER.error("Already initialized the applications");
+            return;
+        }
+        //
+        // Load service
+        //
+        applicationLoader = ServiceLoader.load(XacmlApplicationServiceProvider.class);
+        //
+        // Iterate through them
+        //
+        Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
+        while (iterator.hasNext()) {
+            //
+            // Get the application
+            //
+            XacmlApplicationServiceProvider application = iterator.next();
+            LOGGER.info("Application {} supports {}", application.applicationName(),
+                    application.supportedPolicyTypes());
+            //
+            // Iterate each application
+            //
+            int pathCount = 1;
+            for (String action : application.actionDecisionsSupported()) {
+                //
+                // Save the actions that it supports
+                //
+                providerActionMap.put(action, application);
+                //
+                // Create a unique path for the application to store its data
+                // May need to scan this name to remove unsafe characters etc.
+                // But for debugging purposes, its good to use the application name
+                //
+                //
+                Path path = Paths.get(applicationPath.toAbsolutePath().toString(),
+                        application.applicationName(), Integer.toString(pathCount++));
+                //
+                // Have the application initialize
+                //
+                application.initialize(path);
+            }
+        }
+        //
+        // we have initialized
+        //
+        needsInit = false;
+    }
+
+    public static XacmlApplicationServiceProvider findApplication(DecisionRequest request) {
+        return providerActionMap.get(request.getAction());
+    }
+
+    /**
+     * Returns the current count of policy types supported. This could be misleading a bit
+     * as some applications can support wildcard of policy types. Eg. onap.Monitoring.* as
+     * well as individual types/versions. Nevertheless useful for debugging and testing.
+     *
+     * @return Total count added from all applications
+     */
+    public static long getPolicyTypeCount() {
+        Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
+        long types = 0;
+        while (iterator.hasNext()) {
+            XacmlApplicationServiceProvider application = iterator.next();
+            types += application.supportedPolicyTypes().size();
+        }
+        return types;
+    }
+
+}
index 965753a..c61bef2 100644 (file)
@@ -33,7 +33,9 @@ import io.swagger.annotations.Info;
 import io.swagger.annotations.ResponseHeader;
 import io.swagger.annotations.SecurityDefinition;
 import io.swagger.annotations.SwaggerDefinition;
+
 import java.util.UUID;
+
 import javax.ws.rs.Consumes;
 import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
@@ -43,8 +45,12 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.ResponseBuilder;
+
 import org.onap.policy.common.endpoints.report.HealthCheckReport;
-import org.onap.policy.pdpx.main.rest.model.Decision;
+import org.onap.policy.models.decisions.concepts.DecisionException;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+import org.onap.policy.models.errors.concepts.ErrorResponse;
 import org.onap.policy.pdpx.main.rest.model.StatisticsReport;
 import org.onap.policy.pdpx.main.rest.provider.DecisionProvider;
 import org.onap.policy.pdpx.main.rest.provider.HealthCheckProvider;
@@ -129,10 +135,17 @@ public class XacmlPdpRestController {
                 .entity(new StatisticsProvider().fetchCurrentStatistics()).build();
     }
 
+    /**
+     * Our decision entry point.
+     *
+     * @param body Should be a DecisionRequest object
+     * @param requestId Unique request id
+     * @return DecisionResponse or ErrorResponse object
+     */
     @POST
     @Path("/decision")
     @ApiOperation(value = "Fetch the decision using specified decision parameters",
-            notes = "Returns the policy decision from Policy Xacml PDP", response = Decision.class,
+            notes = "Returns the policy decision from Policy Xacml PDP", response = DecisionResponse.class,
             responseHeaders = {
                     @ResponseHeader(name = "X-MinorVersion",
                             description = "Used to request or communicate a MINOR version back from the client"
@@ -152,14 +165,20 @@ public class XacmlPdpRestController {
             extensions = {@Extension(name = "interface info",
                     properties = {@ExtensionProperty(name = "pdpx-version", value = "1.0.0"),
                             @ExtensionProperty(name = "last-mod-release", value = "Dublin")})})
-    @ApiResponses(value = {@ApiResponse(code = 400, message = "Bad Request"),
+    @ApiResponses(value = {@ApiResponse(code = 400, message = "Bad Request", response = ErrorResponse.class),
             @ApiResponse(code = 401, message = "Authentication Error"),
             @ApiResponse(code = 403, message = "Authorization Error"),
             @ApiResponse(code = 500, message = "Internal Server Error")})
-    public Response decision(Decision body,
+    public Response decision(DecisionRequest body,
             @HeaderParam("X-ONAP-RequestID") @ApiParam("RequestID for http transaction") UUID requestId) {
-        return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
-                .entity(new DecisionProvider().fetchDecision()).build();
+        try {
+            return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
+                    .entity(new DecisionProvider().fetchDecision(body)).build();
+        } catch (DecisionException e) {
+            return addLoggingHeaders(
+                    addVersionControlHeaders(Response.status((e.getErrorResponse().getResponseCode()))), requestId)
+                    .entity(e.getErrorResponse()).build();
+        }
     }
 
     private ResponseBuilder addVersionControlHeaders(ResponseBuilder rb) {
index f3b7a54..67bbcca 100644 (file)
 
 package org.onap.policy.pdpx.main.rest;
 
+import java.nio.file.Paths;
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Properties;
-import java.util.ServiceLoader;
 
 import org.onap.policy.common.capabilities.Startable;
 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
-import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
 import org.onap.policy.pdpx.main.parameters.RestServerParameters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,16 +45,16 @@ public class XacmlPdpRestServer implements Startable {
     private List<HttpServletServer> servers = new ArrayList<>();
 
     private RestServerParameters restServerParameters;
-
-    private ServiceLoader<XacmlApplicationServiceProvider> applicationLoader;
+    private String applicationPath;
 
     /**
      * Constructor for instantiating XacmlPdpRestServer.
      *
      * @param restServerParameters the rest server parameters
      */
-    public XacmlPdpRestServer(final RestServerParameters restServerParameters) {
+    public XacmlPdpRestServer(final RestServerParameters restServerParameters, final String applicationPath) {
         this.restServerParameters = restServerParameters;
+        this.applicationPath = applicationPath;
     }
 
     /**
@@ -65,9 +64,13 @@ public class XacmlPdpRestServer implements Startable {
     public boolean start() {
         try {
             //
-            // Look for existing policy types loaded into the system
+            // Initialize the applications - SEND PROPERTIES
+            //
+            XacmlPdpApplicationManager.initializeApplications(Paths.get(applicationPath));
+            //
+            // Update statistics manager on the policy types
             //
-            locateExistingPolicyTypes();
+            XacmlPdpStatisticsManager.setTotalPolicyTypesCount(XacmlPdpApplicationManager.getPolicyTypeCount());
             //
             // Get the server properties
             //
@@ -112,35 +115,11 @@ public class XacmlPdpRestServer implements Startable {
                 String.valueOf(restServerParameters.isHttps()));
         props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".aaf",
                 String.valueOf(restServerParameters.isAaf()));
+        props.setProperty(HTTP_SERVER_SERVICES + SEPARATOR + restServerParameters.getName() + ".serialization.provider",
+                GsonMessageBodyHandler.class.getName());
         return props;
     }
 
-    private void locateExistingPolicyTypes() {
-        //
-        // Load service
-        //
-        applicationLoader = ServiceLoader.load(XacmlApplicationServiceProvider.class);
-        //
-        // Iterate through them
-        //
-        StringBuilder strDump = new StringBuilder("Loaded applications:" + System.lineSeparator());
-        Iterator<XacmlApplicationServiceProvider> iterator = applicationLoader.iterator();
-        long types = 0;
-        while (iterator.hasNext()) {
-            XacmlApplicationServiceProvider application = iterator.next();
-            strDump.append(application.applicationName());
-            strDump.append(" supports ");
-            strDump.append(application.supportedPolicyTypes());
-            types += application.supportedPolicyTypes().size();
-            strDump.append(System.lineSeparator());
-        }
-        LOGGER.debug("{}", strDump);
-        //
-        // Update statistics manager
-        //
-        XacmlPdpStatisticsManager.setTotalPolicyTypesCount(types);
-    }
-
     /**
      * {@inheritDoc}.
      */
diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/model/Decision.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/model/Decision.java
deleted file mode 100644 (file)
index f5c9a4d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
- * ================================================================================
- * 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.policy.pdpx.main.rest.model;
-
-import java.util.List;
-import java.util.Map;
-
-public class Decision {
-
-    String  onapName;
-
-    String  onapComponent;
-
-    String  onapInstance;
-
-    String  action;
-
-    List<Map<String, Object>> resource;
-}
index 6219004..3317853 100644 (file)
 
 package org.onap.policy.pdpx.main.rest.provider;
 
-import org.onap.policy.pdpx.main.rest.model.Decision;
+import javax.ws.rs.core.Response.Status;
+
+import org.onap.policy.models.decisions.concepts.DecisionException;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+import org.onap.policy.pdp.xacml.application.common.XacmlApplicationServiceProvider;
+import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
 public class DecisionProvider {
+    private static final Logger LOGGER = LoggerFactory.getLogger(DecisionProvider.class);
 
     /**
      * Retrieves the policy decision for the specified parameters.
+     * @param body
      *
      * @return the Decision object
      */
-    public Decision fetchDecision() {
-        // placeholder
-        return new Decision();
+    public DecisionResponse fetchDecision(DecisionRequest request) {
+        LOGGER.debug("Fetching decision {}", request);
+        //
+        // Find application for this decision
+        //
+        XacmlApplicationServiceProvider application = findApplication(request);
+        //
+        // Cannot find application for action
+        //
+        return application.makeDecision(request);
+    }
+
+    private XacmlApplicationServiceProvider findApplication(DecisionRequest request) {
+        XacmlApplicationServiceProvider application = XacmlPdpApplicationManager.findApplication(request);
+        if (application != null) {
+            return application;
+        }
+        throw new DecisionException(Status.BAD_REQUEST, "No application for action " + request.getAction());
     }
 
 }
index d50c4f1..42ad7bb 100644 (file)
@@ -71,7 +71,8 @@ public class XacmlPdpActivator {
      */
     private void startXacmlPdpRestServer() throws PolicyXacmlPdpException {
         xacmlPdpParameterGroup.getRestServerParameters().setName(xacmlPdpParameterGroup.getName());
-        restServer = new XacmlPdpRestServer(xacmlPdpParameterGroup.getRestServerParameters());
+        restServer = new XacmlPdpRestServer(xacmlPdpParameterGroup.getRestServerParameters(),
+                xacmlPdpParameterGroup.getApplicationPath());
         if (!restServer.start()) {
             throw new PolicyXacmlPdpException("Failed to start xacml pdp rest server. Check log for more details...");
         }
index 48606c9..2bf6fd8 100644 (file)
@@ -25,7 +25,13 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import java.io.File;
+import java.io.IOException;
+
+import org.junit.Before;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.onap.policy.common.parameters.GroupValidationResult;
 
 /**
@@ -34,12 +40,23 @@ import org.onap.policy.common.parameters.GroupValidationResult;
  */
 public class TestXacmlPdpParameterGroup {
     CommonTestData commonTestData = new CommonTestData();
+    private static File applicationPath;
+
+    @ClassRule
+    public static final TemporaryFolder applicationFolder = new TemporaryFolder();
+
+    @Before
+    public void setupPath() throws IOException {
+        applicationPath = applicationFolder.newFolder();
+    }
 
     @Test
-    public void testXacmlPdpParameterGroup() {
+    public void testXacmlPdpParameterGroup() throws IOException {
         final RestServerParameters restServerParameters = commonTestData.getRestServerParameters(false);
         final XacmlPdpParameterGroup pdpxParameters =
-                new XacmlPdpParameterGroup(CommonTestData.PDPX_GROUP_NAME, restServerParameters);
+                new XacmlPdpParameterGroup(CommonTestData.PDPX_GROUP_NAME,
+                        restServerParameters,
+                        applicationPath.getAbsolutePath());
         final GroupValidationResult validationResult = pdpxParameters.validate();
         assertTrue(validationResult.isValid());
         assertEquals(restServerParameters.getHost(), pdpxParameters.getRestServerParameters().getHost());
@@ -54,7 +71,8 @@ public class TestXacmlPdpParameterGroup {
     @Test
     public void testXacmlPdpParameterGroup_NullName() {
         final RestServerParameters restServerParameters = commonTestData.getRestServerParameters(false);
-        final XacmlPdpParameterGroup pdpxParameters = new XacmlPdpParameterGroup(null, restServerParameters);
+        final XacmlPdpParameterGroup pdpxParameters = new XacmlPdpParameterGroup(null, restServerParameters,
+                applicationPath.getAbsolutePath());
         final GroupValidationResult validationResult = pdpxParameters.validate();
         assertFalse(validationResult.isValid());
         assertEquals(null, pdpxParameters.getName());
@@ -66,7 +84,8 @@ public class TestXacmlPdpParameterGroup {
     public void testXacmlPdpParameterGroup_EmptyName() {
         final RestServerParameters restServerParameters = commonTestData.getRestServerParameters(false);
 
-        final XacmlPdpParameterGroup pdpxParameters = new XacmlPdpParameterGroup("", restServerParameters);
+        final XacmlPdpParameterGroup pdpxParameters = new XacmlPdpParameterGroup("", restServerParameters,
+                applicationPath.getAbsolutePath());
         final GroupValidationResult validationResult = pdpxParameters.validate();
         assertFalse(validationResult.isValid());
         assertEquals("", pdpxParameters.getName());
@@ -79,7 +98,8 @@ public class TestXacmlPdpParameterGroup {
         final RestServerParameters restServerParameters = commonTestData.getRestServerParameters(true);
 
         final XacmlPdpParameterGroup pdpxParameters =
-                new XacmlPdpParameterGroup(CommonTestData.PDPX_GROUP_NAME, restServerParameters);
+                new XacmlPdpParameterGroup(CommonTestData.PDPX_GROUP_NAME, restServerParameters,
+                        applicationPath.getAbsolutePath());
         final GroupValidationResult validationResult = pdpxParameters.validate();
         assertFalse(validationResult.isValid());
         assertTrue(validationResult.getResult()
index ef85a76..de55282 100644 (file)
@@ -93,11 +93,14 @@ public class TestXacmlPdpParameterHandler {
         noArguments.parse(noArgumentString);
 
         assertThatThrownBy(() -> new XacmlPdpParameterHandler().getParameters(noArguments))
-                .hasMessage("validation error(s) on parameters from \"parameters/NoParameters.json\"\nparameter group "
-                        + "\"null\" type \"org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup\" INVALID, "
-                        + "parameter group has status INVALID\n"
-                        + "  field \"name\" type \"java.lang.String\" value \"null\" "
-                        + "INVALID, must be a non-blank string\n");
+                .hasMessage("validation error(s) on parameters from \"parameters/NoParameters.json\"\n"
+                        + "parameter group \"null\" type "
+                        + "\"org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup\""
+                        + " INVALID, parameter group has status INVALID\n"
+                        + "  field \"name\" type \"java.lang.String\" value \"null\" INVALID, "
+                        + "must be a non-blank string\n"
+                        + "  field \"applicationPath\" type \"java.lang.String\" value \"null\" INVALID, "
+                        + "must have application path for applications to store policies and data.\n");
     }
 
     @Test
diff --git a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestDecision.java
new file mode 100644 (file)
index 0000000..fe307e4
--- /dev/null
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * 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.policy.pdpx.main.rest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.glassfish.jersey.client.ClientConfig;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams;
+import org.onap.policy.common.endpoints.http.client.HttpClient;
+import org.onap.policy.common.gson.GsonMessageBodyHandler;
+import org.onap.policy.common.utils.network.NetworkUtil;
+import org.onap.policy.models.decisions.concepts.DecisionRequest;
+import org.onap.policy.models.decisions.concepts.DecisionResponse;
+import org.onap.policy.models.errors.concepts.ErrorResponse;
+import org.onap.policy.pdpx.main.PolicyXacmlPdpException;
+import org.onap.policy.pdpx.main.startstop.Main;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestDecision {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(TestDecision.class);
+
+    private static Main main;
+
+    /**
+     * BeforeClass setup environment.
+     */
+    @BeforeClass
+    public static void beforeClass() {
+        System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
+        System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
+        main = startXacmlPdpService();
+    }
+
+    @AfterClass
+    public static void after() throws PolicyXacmlPdpException {
+        stopXacmlPdpService(main);
+    }
+
+    @Test
+    public void testDecision_UnsupportedAction() throws KeyManagementException, NoSuchAlgorithmException,
+        ClassNotFoundException {
+
+        LOGGER.info("Running test testDecision_UnsupportedAction");
+
+        DecisionRequest request = new DecisionRequest();
+        request.setOnapName("DROOLS");
+        request.setAction("foo");
+        Map<String, Object> guard = new HashMap<String, Object>();
+        guard.put("actor", "foo");
+        guard.put("recipe", "bar");
+        guard.put("target", "somevnf");
+        guard.put("clname", "phoneyloop");
+        request.setResource(guard);
+
+        ErrorResponse response = getErrorDecision(request);
+        LOGGER.info("Response {}", response);
+        assertThat(response.getResponseCode()).isEqualTo(Status.BAD_REQUEST);
+        assertThat(response.getErrorMessage()).isEqualToIgnoringCase("No application for action foo");
+    }
+
+    @Test
+    public void testDecision_Guard() throws InterruptedException, IOException {
+        LOGGER.info("Running test testDecision_Guard");
+
+        DecisionRequest request = new DecisionRequest();
+        request.setOnapName("DROOLS");
+        request.setAction("guard");
+        Map<String, Object> guard = new HashMap<String, Object>();
+        guard.put("actor", "foo");
+        guard.put("recipe", "bar");
+        guard.put("target", "somevnf");
+        guard.put("clname", "phoneyloop");
+        request.setResource(guard);
+
+        DecisionResponse response = getDecision(request);
+        LOGGER.info("Response {}", response);
+        //assertThat(response.getErrorMessage()).isEqualToIgnoringCase("No application for action foo");
+    }
+
+    private static Main startXacmlPdpService() {
+        final String[] XacmlPdpConfigParameters = {"-c", "parameters/XacmlPdpConfigParameters.json"};
+        return new Main(XacmlPdpConfigParameters);
+    }
+
+    private static void stopXacmlPdpService(final Main main) throws PolicyXacmlPdpException {
+        main.shutdown();
+    }
+
+    private DecisionResponse getDecision(DecisionRequest request) throws InterruptedException, IOException {
+        final ClientConfig clientConfig = new ClientConfig();
+
+        final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34");
+        clientConfig.register(feature);
+
+        final Client client = ClientBuilder.newClient(clientConfig);
+        final WebTarget webTarget = client.target("http://localhost:6969/policy/pdpx/v1/decision");
+
+        final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON);
+
+        if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 6, 10000L)) {
+            throw new IllegalStateException("Cannot connect to port 6969");
+        }
+
+        return invocationBuilder.post(Entity.json(request), DecisionResponse.class);
+    }
+
+    private ErrorResponse getErrorDecision(DecisionRequest request) throws KeyManagementException,
+        NoSuchAlgorithmException, ClassNotFoundException {
+
+        HttpClient client = getNoAuthHttpClient();
+
+        Entity<DecisionRequest> entityRequest = Entity.entity(request, MediaType.APPLICATION_JSON);
+        Response response = client.post("", entityRequest, Collections.emptyMap());
+
+        assertEquals(400, response.getStatus());
+
+        return HttpClient.getBody(response, ErrorResponse.class);
+    }
+
+    private HttpClient getNoAuthHttpClient()
+            throws KeyManagementException, NoSuchAlgorithmException, ClassNotFoundException {
+        return HttpClient.factory.build(BusTopicParams.builder()
+                .clientName("testDecisionClient")
+                .serializationProvider(GsonMessageBodyHandler.class.getName())
+                .useHttps(false).allowSelfSignedCerts(false).hostname("localhost").port(6969)
+                .basePath("policy/pdpx/v1/decision")
+                .userName("healthcheck").password("zb!XztG34").managed(true).build());
+    }
+
+
+}
\ No newline at end of file
index 316abac..fc3edd7 100644 (file)
@@ -24,6 +24,7 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.File;
 import java.io.IOException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Modifier;
@@ -42,7 +43,9 @@ import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
 import org.junit.After;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.onap.policy.common.endpoints.report.HealthCheckReport;
 import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.pdpx.main.PolicyXacmlPdpException;
@@ -69,15 +72,21 @@ public class TestXacmlPdpRestServer {
     private static String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore";
     private Main main;
     private XacmlPdpRestServer restServer;
+    private static File applicationPath;
+
+    @ClassRule
+    public static final TemporaryFolder applicationFolder = new TemporaryFolder();
 
     /**
      * setup.
+     *
+     * @throws IOException exception if cannot create temporary folder
      */
     @BeforeClass
-    public static void setUp() {
+    public static void setUp() throws IOException {
         System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
         System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
-
+        applicationPath = applicationFolder.newFolder();
     }
 
     /**
@@ -115,7 +124,7 @@ public class TestXacmlPdpRestServer {
     public void testHealthCheckFailure() throws InterruptedException, IOException {
         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
-        restServer = new XacmlPdpRestServer(restServerParams);
+        restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath());
         restServer.start();
         final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT);
         final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class);
@@ -149,7 +158,7 @@ public class TestXacmlPdpRestServer {
     public void testStatistics_500() throws IOException, InterruptedException {
         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
-        restServer = new XacmlPdpRestServer(restServerParams);
+        restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath());
         restServer.start();
         final Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT);
         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
index 595301d..8d2f7ce 100644 (file)
@@ -25,6 +25,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
+import java.io.File;
 import java.io.IOException;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
@@ -33,8 +34,11 @@ import javax.ws.rs.client.WebTarget;
 import javax.ws.rs.core.MediaType;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.junit.Before;
 import org.junit.BeforeClass;
+import org.junit.ClassRule;
 import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
 import org.onap.policy.common.utils.network.NetworkUtil;
 import org.onap.policy.pdpx.main.PolicyXacmlPdpException;
 import org.onap.policy.pdpx.main.parameters.CommonTestData;
@@ -52,11 +56,21 @@ import org.slf4j.LoggerFactory;
 public class TestXacmlPdpStatistics {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(TestXacmlPdpStatistics.class);
+    private static File applicationPath;
 
+    @ClassRule
+    public static final TemporaryFolder applicationFolder = new TemporaryFolder();
+
+    /**
+     * Turn off some debugging and create temporary folder for applications.
+     *
+     * @throws IOException If temporary folder fails
+     */
     @BeforeClass
-    public static void beforeClass() {
+    public static void beforeClass() throws IOException {
         System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog");
         System.setProperty("org.eclipse.jetty.LEVEL", "OFF");
+        applicationPath = applicationFolder.newFolder();
     }
 
     @Test
@@ -81,7 +95,8 @@ public class TestXacmlPdpStatistics {
     public void testXacmlPdpStatistics_500() throws InterruptedException {
         final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false);
         restServerParams.setName(CommonTestData.PDPX_GROUP_NAME);
-        final XacmlPdpRestServer restServer = new XacmlPdpRestServer(restServerParams);
+        final XacmlPdpRestServer restServer = new XacmlPdpRestServer(restServerParams,
+                applicationPath.getAbsolutePath());
 
         try {
             restServer.start();
index 798731a..ab52cc8 100644 (file)
@@ -5,5 +5,6 @@
         "port": 6969,
         "userName": "healthcheck",
         "password": "zb!XztG34"
-    }
+    },
+    "applicationPath": "apps.test"
 }
index 798731a..ab52cc8 100644 (file)
@@ -5,5 +5,6 @@
         "port": 6969,
         "userName": "healthcheck",
         "password": "zb!XztG34"
-    }
+    },
+    "applicationPath": "apps.test"
 }
index b467fe4..92e6e90 100644 (file)
@@ -6,5 +6,6 @@
         "userName":"healthcheck",
         "password":"zb!XztG34",
         "https":true
-    }
+    },
+    "applicationPath": "apps.test"
 }
\ No newline at end of file