From 05045cd36ad264b5d7b674155699b2cccee71165 Mon Sep 17 00:00:00 2001 From: jh7358 Date: Thu, 25 Apr 2019 20:15:28 -0400 Subject: Refactor xacml-pdp to remove various statics Refactored xacml-pdp to eliminate a number of static fields. Modified junit tests to allocate new ports for each test. Also modified XacmlPolicyUtilsTest to convert path names to match the file system so that the junit will work in OSs other than linux. Replaced logback.xml with a copy of the one from PAP to resolve some issues. Don't print entire message when discarding, as each PDP receives messages for ALL PDPs. Remove shutdown class from Main - just invoke this.shutdown() directly. Added additional comments to CommonRest. Also modified port test parameters. Change-Id: Id8bf7216cdcb59a1a2cb4cb957fa44f640315cfe Issue-ID: POLICY-1645 Signed-off-by: Jim Hahn --- .../java/org/onap/policy/pdpx/main/XacmlState.java | 142 ++++++++++++ .../pdpx/main/comm/XacmlPdpHearbeatPublisher.java | 76 +++++-- .../policy/pdpx/main/comm/XacmlPdpMessage.java | 114 ---------- .../pdpx/main/comm/XacmlPdpUpdatePublisher.java | 61 ++--- .../listeners/XacmlPdpStateChangeListener.java | 43 ++-- .../comm/listeners/XacmlPdpUpdateListener.java | 36 +-- .../pdpx/main/rest/XacmlPdpApplicationManager.java | 49 ++-- .../pdpx/main/rest/XacmlPdpRestController.java | 2 +- .../policy/pdpx/main/rest/XacmlPdpRestServer.java | 17 +- .../pdpx/main/rest/XacmlPdpStatisticsManager.java | 56 ++--- .../pdpx/main/rest/provider/DecisionProvider.java | 10 +- .../main/rest/provider/StatisticsProvider.java | 16 +- .../org/onap/policy/pdpx/main/startstop/Main.java | 97 ++------ .../pdpx/main/startstop/XacmlPdpActivator.java | 139 ++++-------- .../java/org/onap/policy/pdpx/main/CommonRest.java | 216 ++++++++++++++++++ .../onap/policy/pdpx/main/rest/TestDecision.java | 17 +- .../pdpx/main/rest/TestXacmlPdpRestServer.java | 251 ++++----------------- .../pdpx/main/rest/TestXacmlPdpStatistics.java | 123 ++-------- .../onap/policy/pdpx/main/startstop/TestMain.java | 72 +++--- .../pdpx/main/startstop/TestXacmlPdpActivator.java | 40 ++-- .../parameters/XacmlPdpConfigParameters_Https.json | 11 - .../parameters/XacmlPdpConfigParameters_Std.json | 11 + 22 files changed, 773 insertions(+), 826 deletions(-) create mode 100644 main/src/main/java/org/onap/policy/pdpx/main/XacmlState.java delete mode 100644 main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java create mode 100644 main/src/test/java/org/onap/policy/pdpx/main/CommonRest.java delete mode 100644 main/src/test/resources/parameters/XacmlPdpConfigParameters_Https.json create mode 100644 main/src/test/resources/parameters/XacmlPdpConfigParameters_Std.json (limited to 'main/src') diff --git a/main/src/main/java/org/onap/policy/pdpx/main/XacmlState.java b/main/src/main/java/org/onap/policy/pdpx/main/XacmlState.java new file mode 100644 index 00000000..521413c8 --- /dev/null +++ b/main/src/main/java/org/onap/policy/pdpx/main/XacmlState.java @@ -0,0 +1,142 @@ +/*- + * ============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; + +import java.util.Collections; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.models.pdp.concepts.PdpMessage; +import org.onap.policy.models.pdp.concepts.PdpResponseDetails; +import org.onap.policy.models.pdp.concepts.PdpStateChange; +import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.models.pdp.concepts.PdpUpdate; +import org.onap.policy.models.pdp.enums.PdpHealthStatus; +import org.onap.policy.models.pdp.enums.PdpResponseStatus; +import org.onap.policy.models.pdp.enums.PdpState; +import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; +import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator; + +/** + * Current state of this XACML PDP. + */ +public class XacmlState { + + /** + * The application manager. + */ + private final XacmlPdpApplicationManager appManager; + + /** + * Records the current state of this PDP. + */ + private final PdpStatus status; + + + /** + * Constructs the object, initializing the state. + */ + public XacmlState(XacmlPdpApplicationManager appManager) { + this.appManager = appManager; + + this.status = new PdpStatus(); + this.status.setName(NetworkUtil.getHostname()); + this.status.setPdpType("xacml"); + this.status.setState(PdpState.PASSIVE); + this.status.setSupportedPolicyTypes(appManager.getToscaPolicyTypeIdents()); + this.status.setPolicies(Collections.emptyList()); + } + + /** + * Determines if this PDP should handle the given message. + * + * @param message message of interest + * @return {@code true} if this PDP should handle the message, {@code false} otherwise + */ + public boolean shouldHandle(PdpMessage message) { + return message.appliesTo(status.getName(), status.getPdpGroup(), status.getPdpSubgroup()); + } + + /** + * Generates a new heart beat message. + * + * @return a new heart beat message + */ + public PdpStatus genHeartbeat() { + // first, update status fields + status.setHealthy(XacmlPdpActivator.getCurrent().isAlive() ? PdpHealthStatus.HEALTHY + : PdpHealthStatus.NOT_HEALTHY); + + return new PdpStatus(status); + } + + /** + * Updates the internal state based on the given message. + * + * @param message message from which to update the internal state + * @return a response to the message + */ + public PdpStatus updateInternalState(PdpStateChange message) { + status.setState(message.getState()); + + /* + * NOTE: Do NOT update group & subgroup as state-change requests do not set those + * fields to indicate new values; they only set them to do broadcasts to all PDPs + * within a group/subgroup. + */ + + PdpStatus status2 = makeResponse(message); + + // these fields aren't needed in the response, so clear them out to avoid sending + status2.setPolicies(null); + + return status2; + } + + /** + * Updates the internal state based on the given message. Assumes that the policies + * have already been updated within the application manager. + * + * @param message message from which to update the internal state + * @return a response to the message + */ + public PdpStatus updateInternalState(PdpUpdate message) { + status.setPdpGroup(message.getPdpGroup()); + status.setPdpSubgroup(message.getPdpSubgroup()); + status.setPolicies(appManager.getToscaPolicyIdentifiers()); + + return makeResponse(message); + } + + /** + * Makes a response to the given message, based on the current state. + * + * @param message message for which the response should be made + * @return a new response + */ + private PdpStatus makeResponse(PdpMessage message) { + PdpResponseDetails resp = new PdpResponseDetails(); + resp.setResponseStatus(PdpResponseStatus.SUCCESS); + resp.setResponseTo(message.getRequestId()); + + PdpStatus status2 = new PdpStatus(status); + status2.setResponse(resp); + return status2; + } +} diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java index 8ffccbef..29044744 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpHearbeatPublisher.java @@ -23,6 +23,8 @@ package org.onap.policy.pdpx.main.comm; import java.util.Timer; import java.util.TimerTask; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; +import org.onap.policy.models.pdp.concepts.PdpStatus; +import org.onap.policy.pdpx.main.XacmlState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,45 +32,75 @@ public class XacmlPdpHearbeatPublisher extends TimerTask { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpHearbeatPublisher.class); - private Timer timer; - private XacmlPdpMessage heartbeatMessage; - private static TopicSinkClient topicSinkClient; - private static volatile boolean alive = false; + private final TopicSinkClient topicSinkClient; + + /** + * Tracks the state of this PDP. + */ + private final XacmlState currentState; + + /** + * Current timer interval, in milliseconds. + */ + private long intervalMs = 60000; + + private Timer timer = null; + /** * Constructor for instantiating XacmlPdpPublisher. * - * @param message of the PDP - * @param topicSinkClient used to send heartbeat message + * @param topicSinkClient used to send heart beat message + * @param state tracks the state of this PDP */ - public XacmlPdpHearbeatPublisher(TopicSinkClient topicSinkClient, XacmlPdpMessage message ) { + public XacmlPdpHearbeatPublisher(TopicSinkClient topicSinkClient, XacmlState state) { this.topicSinkClient = topicSinkClient; - this.heartbeatMessage = message; - timer = new Timer(false); - timer.scheduleAtFixedRate(this, 0, 60000); // time interval temp hard coded now but will be parameterized - setAlive(true); + this.currentState = state; } @Override public void run() { - topicSinkClient.send(heartbeatMessage.formatPdpStatusMessage()); - LOGGER.info("Sending Xacml PDP heartbeat to the PAP"); + PdpStatus message = currentState.genHeartbeat(); + LOGGER.info("Sending Xacml PDP heartbeat to the PAP - {}", message); + + topicSinkClient.send(message); } /** - * Method to terminate the heartbeat. + * Method to terminate the heart beat. */ - public void terminate() { - timer.cancel(); - timer.purge(); - setAlive(false); + public synchronized void terminate() { + if (timer != null) { + timer.cancel(); + timer.purge(); + timer = null; + } } - public static boolean isAlive() { - return alive; + /** + * Restarts the timer if the interval has changed. If the timer is not currently + * running, then it updates the interval, but does not start the timer. + * + * @param intervalMs desired interval, or {@code null} to leave it unchanged + */ + public synchronized void restart(Long intervalMs) { + if (intervalMs != null && intervalMs > 0 && intervalMs != this.intervalMs) { + this.intervalMs = intervalMs; + + if (timer != null) { + terminate(); + start(); + } + } } - public void setAlive(boolean alive) { - this.alive = alive; + /** + * Starts the timer. + */ + public synchronized void start() { + if (timer == null) { + timer = new Timer(true); + timer.scheduleAtFixedRate(this, 0, this.intervalMs); + } } } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java deleted file mode 100644 index 066e3f23..00000000 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpMessage.java +++ /dev/null @@ -1,114 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * ONAP - * ================================================================================ - * 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.comm; - -import lombok.Getter; -import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.models.pdp.concepts.PdpStateChange; -import org.onap.policy.models.pdp.concepts.PdpStatus; -import org.onap.policy.models.pdp.concepts.PdpUpdate; -import org.onap.policy.models.pdp.enums.PdpHealthStatus; -import org.onap.policy.models.pdp.enums.PdpState; -import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; -import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Getter -public class XacmlPdpMessage { - - // The logger for this class - private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpMessage.class); - private String pdpGroup; - private String pdpSubGroup; - private PdpState pdpState; - private String pdpName = NetworkUtil.getHostname(); - - /** - * Method used to format the initial registration status message. - * - * @param state of the PDP - * @return status message of the PDP - */ - public PdpStatus formatInitialStatusMessage(PdpState state) { - PdpStatus status = new PdpStatus(); - status.setName(pdpName); - - if (XacmlPdpActivator.getCurrent().isAlive()) { - status.setHealthy(PdpHealthStatus.HEALTHY); - } else { - status.setHealthy(PdpHealthStatus.NOT_HEALTHY); - } - - status.setPdpType("xacml"); - status.setState(state); - status.setSupportedPolicyTypes(XacmlPdpApplicationManager.getToscaPolicyTypeIdents()); - - LOGGER.debug("formatStatusMessage state {} status{}", state, status); - - return status; - - } - - /** - * Method used to format the PdpStatus message for heartbeat and PDP Updates. - * - * @return status message of the PDP - */ - public PdpStatus formatPdpStatusMessage() { - PdpStatus status = new PdpStatus(); - status.setName(pdpName); - - if (XacmlPdpActivator.getCurrent() != null && XacmlPdpActivator.getCurrent().isAlive()) { - status.setHealthy(PdpHealthStatus.HEALTHY); - } else { - status.setHealthy(PdpHealthStatus.NOT_HEALTHY); - } - - status.setPdpType("xacml"); - status.setState(pdpState); - status.setPdpGroup(pdpGroup); - status.setPdpSubgroup(pdpSubGroup); - status.setSupportedPolicyTypes(XacmlPdpApplicationManager.getToscaPolicyTypeIdents()); - status.setPolicies(XacmlPdpApplicationManager.getToscaPolicyIdentifiers()); - - return status; - } - - /** - * Method used to update PDP status attributes from PdpStateChange. - */ - public void updateInternalStatus(PdpStateChange message) { - pdpGroup = message.getPdpGroup(); - pdpSubGroup = message.getPdpSubgroup(); - pdpState = message.getState(); - } - - /** - * Method used to update PDP status attributes from PdpUpdate. - */ - public void updateInternalStatus(PdpUpdate message) { - pdpGroup = message.getPdpGroup(); - pdpSubGroup = message.getPdpSubgroup(); - } -} diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java index 54d9cf65..a26f4b11 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/XacmlPdpUpdatePublisher.java @@ -20,12 +20,14 @@ package org.onap.policy.pdpx.main.comm; +import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; import org.onap.policy.models.pdp.concepts.PdpStatus; import org.onap.policy.models.pdp.concepts.PdpUpdate; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.pdpx.main.XacmlState; import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,49 +36,54 @@ public class XacmlPdpUpdatePublisher { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpUpdatePublisher.class); - private XacmlPdpUpdatePublisher() { - throw new IllegalStateException("Please do not create private instance of XacmlPdpUpdatePublisher"); + private final TopicSinkClient client; + private final XacmlState state; + private final XacmlPdpApplicationManager appManager; + + /** + * Constructs the object. + * @param client messages are published to this client + * @param state tracks the state of this PDP + * @param appManager application manager + */ + public XacmlPdpUpdatePublisher(TopicSinkClient client, XacmlState state, XacmlPdpApplicationManager appManager) { + this.client = client; + this.state = state; + this.appManager = appManager; } /** * Handle the PDP Update message. * * @param message Incoming message - * @param client TopicSinkClient */ - public static void handlePdpUpdate(PdpUpdate message, TopicSinkClient client, - XacmlPdpMessage updatePdpMessage) { + public void handlePdpUpdate(PdpUpdate message) { - if (!message.getPolicies().isEmpty() || message.getPolicies() != null) { + Set incomingPolicies = + new HashSet<>(message.getPolicies() == null ? Collections.emptyList() : message.getPolicies()); + Set deployedPolicies = + new HashSet<>(appManager.getToscaPolicies().keySet()); - Set incomingPolicies = - new HashSet<>(message.getPolicies()); - Set deployedPolicies = - new HashSet<>(XacmlPdpApplicationManager.getToscaPolicies().keySet()); - - // Undeploy a policy - // if incoming policies do not contain the deployed policy then remove it from PDP - for (ToscaPolicy policy : deployedPolicies) { - if (!incomingPolicies.contains(policy)) { - XacmlPdpApplicationManager.removeUndeployedPolicy(policy); - } + // Undeploy a policy + // if incoming policies do not contain the deployed policy then remove it from PDP + for (ToscaPolicy policy : deployedPolicies) { + if (!incomingPolicies.contains(policy)) { + appManager.removeUndeployedPolicy(policy); } + } - // Deploy a policy - // if deployed policies do not contain the incoming policy load it - for (ToscaPolicy policy : incomingPolicies) { - if (!deployedPolicies.contains(policy)) { - XacmlPdpApplicationManager.loadDeployedPolicy(policy); - } + // Deploy a policy + // if deployed policies do not contain the incoming policy load it + for (ToscaPolicy policy : incomingPolicies) { + if (!deployedPolicies.contains(policy)) { + appManager.loadDeployedPolicy(policy); } } - updatePdpMessage.updateInternalStatus(message); - PdpStatus statusMessage = updatePdpMessage.formatPdpStatusMessage(); - sendPdpUpdate(statusMessage, client); + sendPdpUpdate(state.updateInternalState(message)); } - private static void sendPdpUpdate(PdpStatus status, TopicSinkClient client) { + private void sendPdpUpdate(PdpStatus status) { // Send PdpStatus Change to PAP if (!client.send(status)) { LOGGER.error("failed to send to topic sink {}", client.getTopic()); diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListener.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListener.java index 3102edb1..98f6d0e1 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListener.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpStateChangeListener.java @@ -27,9 +27,7 @@ import org.onap.policy.common.endpoints.listeners.ScoListener; import org.onap.policy.common.utils.coder.StandardCoderObject; import org.onap.policy.models.pdp.concepts.PdpStateChange; import org.onap.policy.models.pdp.concepts.PdpStatus; -import org.onap.policy.models.pdp.enums.PdpState; -import org.onap.policy.pdpx.main.comm.XacmlPdpHearbeatPublisher; -import org.onap.policy.pdpx.main.comm.XacmlPdpMessage; +import org.onap.policy.pdpx.main.XacmlState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,47 +35,40 @@ public class XacmlPdpStateChangeListener extends ScoListener { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpStateChangeListener.class); - private TopicSinkClient client; + private final TopicSinkClient client; - private XacmlPdpHearbeatPublisher heartbeat; - private XacmlPdpMessage pdpInternalStatus; + private final XacmlState state; /** * Constructs the object. * * @param client used to send back response after receiving state change message + * @param state tracks the state of this PDP */ - public XacmlPdpStateChangeListener(TopicSinkClient client, XacmlPdpMessage pdpStatusMessage) { + public XacmlPdpStateChangeListener(TopicSinkClient client, XacmlState state) { super(PdpStateChange.class); - PdpStateChange message = new PdpStateChange(); - message.setState(PdpState.PASSIVE); - this.pdpInternalStatus = pdpStatusMessage; this.client = client; - this.heartbeat = new XacmlPdpHearbeatPublisher(client, pdpStatusMessage); + this.state = state; } @Override public void onTopicEvent(CommInfrastructure infra, String topic, StandardCoderObject sco, PdpStateChange message) { try { + if (!state.shouldHandle(message)) { + LOGGER.debug("PDP State Change message discarded - {}", message); + return; + } - if (message.appliesTo(pdpInternalStatus.getPdpName(), pdpInternalStatus.getPdpGroup(), - pdpInternalStatus.getPdpSubGroup())) { - - pdpInternalStatus.updateInternalStatus(message); - PdpStatus newStatus = pdpInternalStatus.formatPdpStatusMessage(); - - // Send State Change Status to PAP - if (!client.send(newStatus)) { - LOGGER.error("failed to send to topic sink {}", client.getTopic()); - throw new TopicSinkClientException("failed to send to topic sink " + client.getTopic()); - } + LOGGER.info("PDP State Change message has been received from the PAP - {}", message); + PdpStatus newStatus = state.updateInternalState(message); - // Starte new heartbeat if publisher is NOT alive - if (!XacmlPdpHearbeatPublisher.isAlive()) { - heartbeat = new XacmlPdpHearbeatPublisher(client, pdpInternalStatus); - } + // Send State Change Status to PAP + if (!client.send(newStatus)) { + LOGGER.error("failed to send to topic sink {}", client.getTopic()); + throw new TopicSinkClientException("failed to send to topic sink " + client.getTopic()); } + } catch (final Exception e) { LOGGER.error("failed to handle the PDP State Change message.", e); } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java b/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java index 01d19160..2a8ef99f 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/comm/listeners/XacmlPdpUpdateListener.java @@ -25,8 +25,10 @@ import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; import org.onap.policy.common.endpoints.listeners.ScoListener; import org.onap.policy.common.utils.coder.StandardCoderObject; import org.onap.policy.models.pdp.concepts.PdpUpdate; -import org.onap.policy.pdpx.main.comm.XacmlPdpMessage; +import org.onap.policy.pdpx.main.XacmlState; +import org.onap.policy.pdpx.main.comm.XacmlPdpHearbeatPublisher; import org.onap.policy.pdpx.main.comm.XacmlPdpUpdatePublisher; +import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,33 +36,41 @@ public class XacmlPdpUpdateListener extends ScoListener { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpStateChangeListener.class); - private TopicSinkClient client; - private XacmlPdpMessage pdpInternalStatus; + private final XacmlState state; + + private final XacmlPdpHearbeatPublisher heartbeat; + + private final XacmlPdpUpdatePublisher publisher; /** * Constructs the object. * * @param client used to send back response after receiving state change message + * @param state tracks the state of this PDP + * @param heartbeat heart beat publisher + * @param appManager application manager */ - public XacmlPdpUpdateListener(TopicSinkClient client, XacmlPdpMessage pdpStatusMessage) { + public XacmlPdpUpdateListener(TopicSinkClient client, XacmlState state, XacmlPdpHearbeatPublisher heartbeat, + XacmlPdpApplicationManager appManager) { super(PdpUpdate.class); - this.client = client; - this.pdpInternalStatus = pdpStatusMessage; + this.state = state; + this.heartbeat = heartbeat; + this.publisher = new XacmlPdpUpdatePublisher(client, state, appManager); } @Override public void onTopicEvent(CommInfrastructure infra, String topic, StandardCoderObject sco, PdpUpdate message) { try { - - LOGGER.info("PDP update message has been received from the PAP - {}", message.toString()); - - if (message.appliesTo(pdpInternalStatus.getPdpName(), pdpInternalStatus.getPdpGroup(), - pdpInternalStatus.getPdpSubGroup())) { - - XacmlPdpUpdatePublisher.handlePdpUpdate(message, client, pdpInternalStatus); + if (!state.shouldHandle(message)) { + LOGGER.debug("PDP update message discarded - {}:{}", message.getName(), message.getRequestId()); + return; } + LOGGER.info("PDP update message has been received from the PAP - {}", message); + publisher.handlePdpUpdate(message); + heartbeat.restart(message.getPdpHeartbeatIntervalMs()); + } catch (final Exception e) { LOGGER.error("failed to handle the PDP Update message.", e); } 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 index db2ce553..6a5555be 100644 --- 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 @@ -30,6 +30,8 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; import java.util.stream.Collectors; +import lombok.Getter; +import lombok.Setter; import org.onap.policy.models.decisions.concepts.DecisionRequest; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyIdentifier; @@ -42,37 +44,24 @@ import org.slf4j.LoggerFactory; public class XacmlPdpApplicationManager { private static final Logger LOGGER = LoggerFactory.getLogger(XacmlPdpApplicationManager.class); - private static boolean needsInit = true; - private static ServiceLoader applicationLoader; - private static Map providerActionMap = new HashMap<>(); - private static List toscaPolicyTypeIdents = new ArrayList<>(); - private static Map mapLoadedPolicies = new HashMap<>(); + @Getter + @Setter + private static XacmlPdpApplicationManager current; + private ServiceLoader applicationLoader; + private Map providerActionMap = new HashMap<>(); + private List toscaPolicyTypeIdents = new ArrayList<>(); + private Map mapLoadedPolicies = new HashMap<>(); - private XacmlPdpApplicationManager() { - super(); - } /** * One time to initialize the applications upon startup. */ - public static void initializeApplications(Path applicationPath) { + public XacmlPdpApplicationManager(Path applicationPath) { if (LOGGER.isInfoEnabled()) { LOGGER.info("Initialization applications {}", applicationPath.toAbsolutePath()); } // - // If we have already done this - // - if (! needsInit) { - LOGGER.warn("Already initialized the applications {}", providerActionMap); - // - // I had to remove this because the JUnits kept failing - although I probably can - // add it back. The main() is hanging around during JUnits and initialization will - // fail. - // - // return - } - // // Load service // applicationLoader = ServiceLoader.load(XacmlApplicationServiceProvider.class); @@ -120,12 +109,11 @@ public class XacmlPdpApplicationManager { // // we have initialized // - needsInit = false; LOGGER.info("Finished applications initialization {}", providerActionMap); } - public static XacmlApplicationServiceProvider findApplication(DecisionRequest request) { + public XacmlApplicationServiceProvider findApplication(DecisionRequest request) { return providerActionMap.get(request.getAction()); } @@ -134,7 +122,7 @@ public class XacmlPdpApplicationManager { * * @return the map containing ToscaPolicies */ - public static Map getToscaPolicies() { + public Map getToscaPolicies() { return mapLoadedPolicies; } @@ -143,14 +131,14 @@ public class XacmlPdpApplicationManager { * * @return list of ToscaPolicyIdentifier */ - public static List getToscaPolicyIdentifiers() { + public List getToscaPolicyIdentifiers() { // // converting map to return List of ToscaPolicyIdentiers // return mapLoadedPolicies.keySet().stream().map(ToscaPolicy::getIdentifier).collect(Collectors.toList()); } - public static List getToscaPolicyTypeIdents() { + public List getToscaPolicyTypeIdents() { return toscaPolicyTypeIdents; } @@ -159,7 +147,7 @@ public class XacmlPdpApplicationManager { * * @param policy Incoming policy */ - public static void removeUndeployedPolicy(ToscaPolicy policy) { + public void removeUndeployedPolicy(ToscaPolicy policy) { for (XacmlApplicationServiceProvider application : applicationLoader) { try { @@ -184,7 +172,7 @@ public class XacmlPdpApplicationManager { * * @param policy Incoming policy */ - public static void loadDeployedPolicy(ToscaPolicy policy) { + public void loadDeployedPolicy(ToscaPolicy policy) { for (XacmlApplicationServiceProvider application : applicationLoader) { try { @@ -216,7 +204,7 @@ public class XacmlPdpApplicationManager { * * @return Total count added from all applications */ - public static long getPolicyTypeCount() { + public long getPolicyTypeCount() { long types = 0; for (XacmlApplicationServiceProvider application : applicationLoader) { types += application.supportedPolicyTypes().size(); @@ -224,7 +212,7 @@ public class XacmlPdpApplicationManager { return types; } - private static void initializeApplicationPath(Path basePath, XacmlApplicationServiceProvider application) + private void initializeApplicationPath(Path basePath, XacmlApplicationServiceProvider application) throws XacmlApplicationException { // // Making an assumption that all application names are unique, and @@ -255,5 +243,4 @@ public class XacmlPdpApplicationManager { // application.initialize(path); } - } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestController.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestController.java index 37bab8ec..265dd686 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestController.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestController.java @@ -175,7 +175,7 @@ public class XacmlPdpRestController { return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) .entity(new DecisionProvider().fetchDecision(body)).build(); } catch (DecisionException e) { - XacmlPdpStatisticsManager.updateErrorCount(); + XacmlPdpStatisticsManager.getCurrent().updateErrorCount(); return addLoggingHeaders( addVersionControlHeaders(Response.status((e.getErrorResponse().getResponseCode()))), requestId) .entity(e.getErrorResponse()).build(); diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java index eee9717a..a64953bd 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpRestServer.java @@ -20,11 +20,9 @@ package org.onap.policy.pdpx.main.rest; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; import java.util.Properties; - import org.onap.policy.common.capabilities.Startable; import org.onap.policy.common.endpoints.http.server.HttpServletServer; import org.onap.policy.common.gson.GsonMessageBodyHandler; @@ -44,17 +42,15 @@ public class XacmlPdpRestServer implements Startable { private List servers = new ArrayList<>(); - private RestServerParameters restServerParameters; - private String applicationPath; + private final RestServerParameters restServerParameters; /** * Constructor for instantiating XacmlPdpRestServer. * * @param restServerParameters the rest server parameters */ - public XacmlPdpRestServer(final RestServerParameters restServerParameters, final String applicationPath) { + public XacmlPdpRestServer(final RestServerParameters restServerParameters) { this.restServerParameters = restServerParameters; - this.applicationPath = applicationPath; } /** @@ -64,15 +60,6 @@ public class XacmlPdpRestServer implements Startable { public boolean start() { try { LOGGER.info("Starting XacmlPdpRestServer..."); - // - // Initialize the applications - SEND PROPERTIES - // - XacmlPdpApplicationManager.initializeApplications(Paths.get(applicationPath)); - - // - // Update statistics manager on the policy types - // - XacmlPdpStatisticsManager.setTotalPolicyTypesCount(XacmlPdpApplicationManager.getPolicyTypeCount()); // // Get the server properties diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpStatisticsManager.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpStatisticsManager.java index d209c09c..6d043052 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpStatisticsManager.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpStatisticsManager.java @@ -20,23 +20,25 @@ package org.onap.policy.pdpx.main.rest; +import lombok.Getter; +import lombok.Setter; + /** * Class to hold statistical data for xacmlPdp component. * */ public class XacmlPdpStatisticsManager { - - private static long totalPolicyTypesCount; - private static long totalPoliciesCount; - private static long errorsCount; - private static long permitDecisionsCount; - private static long denyDecisionsCount; - private static long indeterminantDecisionsCount; - private static long notApplicableDecisionsCount; - - private XacmlPdpStatisticsManager() { - throw new IllegalStateException("Instantiation of the class is not allowed"); - } + @Getter + @Setter + private static XacmlPdpStatisticsManager current = null; + + private long totalPolicyTypesCount; + private long totalPoliciesCount; + private long errorsCount; + private long permitDecisionsCount; + private long denyDecisionsCount; + private long indeterminantDecisionsCount; + private long notApplicableDecisionsCount; /** * Method to set the xacml pdp total policy types count. This @@ -45,7 +47,7 @@ public class XacmlPdpStatisticsManager { * * @return the total */ - public static long setTotalPolicyTypesCount(long newCount) { + public long setTotalPolicyTypesCount(long newCount) { totalPolicyTypesCount = newCount; return totalPolicyTypesCount; } @@ -55,7 +57,7 @@ public class XacmlPdpStatisticsManager { * * @return the total */ - public static long updateTotalPoliciesCount() { + public long updateTotalPoliciesCount() { return ++totalPoliciesCount; } @@ -64,7 +66,7 @@ public class XacmlPdpStatisticsManager { * * @return the errorDecisionsCount */ - public static long updateErrorCount() { + public long updateErrorCount() { return ++errorsCount; } @@ -73,7 +75,7 @@ public class XacmlPdpStatisticsManager { * * @return the permitDecisionsCount */ - public static long updatePermitDecisionsCount() { + public long updatePermitDecisionsCount() { return ++permitDecisionsCount; } @@ -82,7 +84,7 @@ public class XacmlPdpStatisticsManager { * * @return the denyDecisionsCount */ - public static long updateDenyDecisionsCount() { + public long updateDenyDecisionsCount() { return ++denyDecisionsCount; } @@ -91,7 +93,7 @@ public class XacmlPdpStatisticsManager { * * @return the indeterminantDecisionsCount */ - public static long updateIndeterminantDecisionsCount() { + public long updateIndeterminantDecisionsCount() { return ++indeterminantDecisionsCount; } @@ -100,7 +102,7 @@ public class XacmlPdpStatisticsManager { * * @return the notApplicableDecisionsCount */ - public static long updateNotApplicableDecisionsCount() { + public long updateNotApplicableDecisionsCount() { return ++notApplicableDecisionsCount; } @@ -109,7 +111,7 @@ public class XacmlPdpStatisticsManager { * @return the totalPolicyTypesCount */ - public static long getTotalPolicyTypesCount() { + public long getTotalPolicyTypesCount() { return totalPolicyTypesCount; } @@ -118,7 +120,7 @@ public class XacmlPdpStatisticsManager { * @return the totalPoliciesCount */ - public static long getTotalPoliciesCount() { + public long getTotalPoliciesCount() { return totalPoliciesCount; } @@ -127,7 +129,7 @@ public class XacmlPdpStatisticsManager { * @return the permitDecisionsCount */ - public static long getErrorCount() { + public long getErrorCount() { return errorsCount; } @@ -136,7 +138,7 @@ public class XacmlPdpStatisticsManager { * @return the permitDecisionsCount */ - public static long getPermitDecisionsCount() { + public long getPermitDecisionsCount() { return permitDecisionsCount; } @@ -145,7 +147,7 @@ public class XacmlPdpStatisticsManager { * @return the denyDecisionsCount */ - public static long getDenyDecisionsCount() { + public long getDenyDecisionsCount() { return denyDecisionsCount; } @@ -154,7 +156,7 @@ public class XacmlPdpStatisticsManager { * @return the indeterminantDecisionsCount */ - public static long getIndeterminantDecisionsCount() { + public long getIndeterminantDecisionsCount() { return indeterminantDecisionsCount; } @@ -163,14 +165,14 @@ public class XacmlPdpStatisticsManager { * @return the notApplicableDecisionsCount */ - public static long getNotApplicableDecisionsCount() { + public long getNotApplicableDecisionsCount() { return notApplicableDecisionsCount; } /** * Reset all the statistics counts to 0. */ - public static void resetAllStatistics() { + public void resetAllStatistics() { totalPolicyTypesCount = 0L; totalPoliciesCount = 0L; errorsCount = 0L; diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/DecisionProvider.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/DecisionProvider.java index 9cfb8a47..67e696aa 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/DecisionProvider.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/DecisionProvider.java @@ -70,7 +70,7 @@ public class DecisionProvider { } private XacmlApplicationServiceProvider findApplication(DecisionRequest request) { - XacmlApplicationServiceProvider application = XacmlPdpApplicationManager.findApplication(request); + XacmlApplicationServiceProvider application = XacmlPdpApplicationManager.getCurrent().findApplication(request); if (application != null) { return application; } @@ -83,22 +83,22 @@ public class DecisionProvider { for (Result result : xacmlResponse.getResults()) { switch (result.getDecision()) { case PERMIT: - XacmlPdpStatisticsManager.updatePermitDecisionsCount(); + XacmlPdpStatisticsManager.getCurrent().updatePermitDecisionsCount(); break; case DENY: - XacmlPdpStatisticsManager.updateDenyDecisionsCount(); + XacmlPdpStatisticsManager.getCurrent().updateDenyDecisionsCount(); break; case INDETERMINATE: case INDETERMINATE_DENY: case INDETERMINATE_DENYPERMIT: case INDETERMINATE_PERMIT: - XacmlPdpStatisticsManager.updateIndeterminantDecisionsCount(); + XacmlPdpStatisticsManager.getCurrent().updateIndeterminantDecisionsCount(); break; case NOTAPPLICABLE: - XacmlPdpStatisticsManager.updateNotApplicableDecisionsCount(); + XacmlPdpStatisticsManager.getCurrent().updateNotApplicableDecisionsCount(); break; default: diff --git a/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/StatisticsProvider.java b/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/StatisticsProvider.java index 95d67a67..cf2fd608 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/StatisticsProvider.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/rest/provider/StatisticsProvider.java @@ -38,13 +38,15 @@ public class StatisticsProvider { public StatisticsReport fetchCurrentStatistics() { final StatisticsReport report = new StatisticsReport(); report.setCode(XacmlPdpActivator.getCurrent().isAlive() ? 200 : 500); - report.setTotalPolicyTypesCount(XacmlPdpStatisticsManager.getTotalPolicyTypesCount()); - report.setTotalPoliciesCount(XacmlPdpStatisticsManager.getTotalPoliciesCount()); - report.setTotalErrorCount(XacmlPdpStatisticsManager.getErrorCount()); - report.setPermitDecisionsCount(XacmlPdpStatisticsManager.getPermitDecisionsCount()); - report.setDenyDecisionsCount(XacmlPdpStatisticsManager.getDenyDecisionsCount()); - report.setIndeterminantDecisionsCount(XacmlPdpStatisticsManager.getIndeterminantDecisionsCount()); - report.setNotApplicableDecisionsCount(XacmlPdpStatisticsManager.getNotApplicableDecisionsCount()); + + XacmlPdpStatisticsManager stats = XacmlPdpStatisticsManager.getCurrent(); + report.setTotalPolicyTypesCount(stats.getTotalPolicyTypesCount()); + report.setTotalPoliciesCount(stats.getTotalPoliciesCount()); + report.setTotalErrorCount(stats.getErrorCount()); + report.setPermitDecisionsCount(stats.getPermitDecisionsCount()); + report.setDenyDecisionsCount(stats.getDenyDecisionsCount()); + report.setIndeterminantDecisionsCount(stats.getIndeterminantDecisionsCount()); + report.setNotApplicableDecisionsCount(stats.getNotApplicableDecisionsCount()); return report; } } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/startstop/Main.java b/main/src/main/java/org/onap/policy/pdpx/main/startstop/Main.java index 62cdc34a..020bfcbf 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/startstop/Main.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/startstop/Main.java @@ -23,7 +23,7 @@ package org.onap.policy.pdpx.main.startstop; import java.io.FileInputStream; import java.util.Arrays; import java.util.Properties; - +import lombok.Getter; import org.onap.policy.pdpx.main.PolicyXacmlPdpException; import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup; import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterHandler; @@ -41,45 +41,34 @@ public class Main { // The policy xacml pdp Activator that activates the policy xacml pdp service private XacmlPdpActivator activator; - // The parameters read in from JSON - private XacmlPdpParameterGroup parameterGroup; - - // The argument message for some args that return a message + @Getter private String argumentMessage = null; /** * Instantiates the policy xacml pdp service. * * @param args the command line arguments + * @throws PolicyXacmlPdpException if an error occurs */ - public Main(final String[] args) { + public Main(final String[] args) throws PolicyXacmlPdpException { final String argumentString = Arrays.toString(args); LOGGER.info("Starting policy xacml pdp service with arguments - {}", argumentString); // Check the arguments final XacmlPdpCommandLineArguments arguments = new XacmlPdpCommandLineArguments(); - try { - // The arguments return a string if there is a message to print and we should exit - argumentMessage = arguments.parse(args); - if (argumentMessage != null) { - LOGGER.info(argumentMessage); - return; - } - // Validate that the arguments are sane - arguments.validate(); - } catch (final PolicyXacmlPdpException e) { - LOGGER.error("start of policy xacml pdp service failed", e); + // The arguments return a string if there is a message to print and we should exit + argumentMessage = arguments.parse(args); + if (argumentMessage != null) { + LOGGER.info(argumentMessage); return; } + // Validate that the arguments are sane + arguments.validate(); + // Read the parameters - try { - parameterGroup = new XacmlPdpParameterHandler().getParameters(arguments); - } catch (final Exception e) { - LOGGER.error("start of policy xacml pdp service failed", e); - return; - } + XacmlPdpParameterGroup parameterGroup = new XacmlPdpParameterHandler().getParameters(arguments); // Read the properties Properties props = new Properties(); @@ -89,73 +78,31 @@ public class Main { props.load(stream); } } catch (final Exception e) { - LOGGER.error("start of xacml pdp service failed", e); - return; + throw new PolicyXacmlPdpException("cannot load property file", e); } // Now, create the activator for the policy xacml pdp service activator = new XacmlPdpActivator(parameterGroup, props); + XacmlPdpActivator.setCurrent(activator); // Start the activator - try { - activator.start(); - } catch (final RuntimeException e) { - LOGGER.error("start of policy xacml pdp service failed, used parameters are " + Arrays.toString(args), e); - return; - } + activator.start(); // Add a shutdown hook to shut everything down in an orderly manner - Runtime.getRuntime().addShutdownHook(new PolicyXacmlPdpShutdownHookClass()); + Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown)); LOGGER.info("Started policy xacml pdp service"); } - /** - * Get the parameters specified in JSON. - * - * @return the parameters - */ - public XacmlPdpParameterGroup getParameters() { - return parameterGroup; - } - - /** - * Get the argumentMessage string. - * - * @return the argumentMessage - */ - public String getArgumentMessage() { - return argumentMessage; - } - /** * Shut down Execution. * * @throws PolicyXacmlPdpException on shutdown errors */ - public void shutdown() { - // clear the parameterGroup variable - parameterGroup = null; - + public synchronized void shutdown() { // clear the xacml pdp activator - if (activator != null) { - activator.stop(); - } - } - - /** - * The Class PolicyXacmlPdpShutdownHookClass terminates the policy xacml pdp service when its run - * method is called. - */ - private class PolicyXacmlPdpShutdownHookClass extends Thread { - /* - * (non-Javadoc) - * - * @see java.lang.Runnable#run() - */ - @Override - public void run() { - // Shutdown the policy xacml pdp service and wait for everything to stop + if (activator != null && activator.isAlive()) { activator.stop(); + activator = null; } } @@ -165,6 +112,10 @@ public class Main { * @param args the arguments */ public static void main(final String[] args) { - new Main(args); + try { + new Main(args); + } catch (RuntimeException | PolicyXacmlPdpException e) { + LOGGER.error("start of policy xacml pdp service failed", e); + } } } diff --git a/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java b/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java index 4db11d0f..2a881d45 100644 --- a/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java +++ b/main/src/main/java/org/onap/policy/pdpx/main/startstop/XacmlPdpActivator.java @@ -20,9 +20,11 @@ package org.onap.policy.pdpx.main.startstop; +import java.nio.file.Paths; import java.util.Arrays; import java.util.Properties; - +import lombok.Getter; +import lombok.Setter; import org.onap.policy.common.endpoints.event.comm.TopicEndpoint; import org.onap.policy.common.endpoints.event.comm.TopicSource; import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient; @@ -31,16 +33,16 @@ import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; import org.onap.policy.common.parameters.ParameterService; import org.onap.policy.common.utils.services.ServiceManagerContainer; import org.onap.policy.models.pdp.concepts.PdpStatus; -import org.onap.policy.models.pdp.concepts.PdpUpdate; import org.onap.policy.models.pdp.enums.PdpMessageType; -import org.onap.policy.models.pdp.enums.PdpState; import org.onap.policy.pdpx.main.PolicyXacmlPdpRuntimeException; -import org.onap.policy.pdpx.main.comm.XacmlPdpMessage; -import org.onap.policy.pdpx.main.comm.XacmlPdpPapRegistration; +import org.onap.policy.pdpx.main.XacmlState; +import org.onap.policy.pdpx.main.comm.XacmlPdpHearbeatPublisher; import org.onap.policy.pdpx.main.comm.listeners.XacmlPdpStateChangeListener; import org.onap.policy.pdpx.main.comm.listeners.XacmlPdpUpdateListener; import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup; +import org.onap.policy.pdpx.main.rest.XacmlPdpApplicationManager; import org.onap.policy.pdpx.main.rest.XacmlPdpRestServer; +import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,6 +58,10 @@ public class XacmlPdpActivator extends ServiceManagerContainer { private static final String[] MSG_TYPE_NAMES = {"messageName"}; private static final String TOPIC = "POLICY-PDP-PAP"; + @Getter + @Setter + private static XacmlPdpActivator current = null; + // The parameters of this policy xacml pdp activator private final XacmlPdpParameterGroup xacmlPdpParameterGroup; @@ -70,27 +76,6 @@ public class XacmlPdpActivator extends ServiceManagerContainer { */ private final MessageTypeDispatcher msgDispatcher; - /** - * Listens for {@link PdpStateChange} messages from the PAP. - */ - private final XacmlPdpStateChangeListener pdpStateChangeListener; - - /** - * Listens for {@link PdpUpdate} messages from the PAP. - */ - private final XacmlPdpUpdateListener pdpUpdateListener; - - /** - * The current activator. - */ - private static XacmlPdpActivator current = null; - - private volatile boolean alive = false; - - private XacmlPdpPapRegistration register; - - private XacmlPdpMessage message; - /** * Instantiate the activator for policy xacml pdp as a complete service. * @@ -103,14 +88,34 @@ public class XacmlPdpActivator extends ServiceManagerContainer { TopicEndpoint.manager.addTopicSinks(topicProperties); TopicEndpoint.manager.addTopicSources(topicProperties); + XacmlPdpHearbeatPublisher heartbeat; + try { - final TopicSinkClient sinkClient = new TopicSinkClient(TOPIC); - this.message = new XacmlPdpMessage(); + XacmlPdpApplicationManager appmgr = + new XacmlPdpApplicationManager(Paths.get(xacmlPdpParameterGroup.getApplicationPath())); + XacmlPdpApplicationManager.setCurrent(appmgr); + + XacmlPdpStatisticsManager stats = new XacmlPdpStatisticsManager(); + XacmlPdpStatisticsManager.setCurrent(stats); + stats.setTotalPolicyTypesCount(appmgr.getPolicyTypeCount()); + + XacmlState state = new XacmlState(appmgr); + this.xacmlPdpParameterGroup = xacmlPdpParameterGroup; this.msgDispatcher = new MessageTypeDispatcher(MSG_TYPE_NAMES); - this.pdpStateChangeListener = new XacmlPdpStateChangeListener(sinkClient, message); - this.pdpUpdateListener = new XacmlPdpUpdateListener(sinkClient, message); - this.register = new XacmlPdpPapRegistration(sinkClient); + + TopicSinkClient sinkClient = new TopicSinkClient(TOPIC); + heartbeat = new XacmlPdpHearbeatPublisher(sinkClient, state); + + /* + * since the dispatcher isn't registered with the topic yet, we can go ahead + * and register the listeners with it. + */ + msgDispatcher.register(PdpMessageType.PDP_STATE_CHANGE.name(), + new XacmlPdpStateChangeListener(sinkClient, state)); + msgDispatcher.register(PdpMessageType.PDP_UPDATE.name(), + new XacmlPdpUpdateListener(sinkClient, state, heartbeat, appmgr)); + } catch (RuntimeException | TopicSinkClientException e) { throw new PolicyXacmlPdpRuntimeException(e.getMessage(), e); } @@ -118,50 +123,31 @@ public class XacmlPdpActivator extends ServiceManagerContainer { xacmlPdpParameterGroup.getRestServerParameters().setName(xacmlPdpParameterGroup.getName()); // @formatter:off - addAction("XACML PDP parameters", () -> ParameterService.register(xacmlPdpParameterGroup), + addAction("XACML PDP parameters", + () -> ParameterService.register(xacmlPdpParameterGroup), () -> ParameterService.deregister(xacmlPdpParameterGroup.getName())); - addAction("PdpStateChange Dispatcher", - () -> msgDispatcher.register(PdpMessageType.PDP_STATE_CHANGE.name(), this.pdpStateChangeListener), - () -> msgDispatcher.unregister(PdpMessageType.PDP_STATE_CHANGE.name())); - - addAction("PdpUpdate Dispatcher", - () -> msgDispatcher.register(PdpMessageType.PDP_UPDATE.name(), this.pdpUpdateListener), - () -> msgDispatcher.unregister(PdpMessageType.PDP_UPDATE.name())); - addAction("Message Dispatcher", - () -> registerMsgDispatcher(), - () -> unregisterMsgDispatcher()); + this::registerMsgDispatcher, + this::unregisterMsgDispatcher); addAction("topics", - () -> TopicEndpoint.manager.start(), - () -> TopicEndpoint.manager.shutdown()); + TopicEndpoint.manager::start, + TopicEndpoint.manager::shutdown); + + // initial heart beats act as registration messages + addAction("Heartbeat Publisher", + heartbeat::start, + heartbeat::terminate); addAction("Create REST server", - () -> { - restServer = new XacmlPdpRestServer(xacmlPdpParameterGroup.getRestServerParameters(), - xacmlPdpParameterGroup.getApplicationPath()); - }, - () -> { - restServer = null; - }); + () -> restServer = new XacmlPdpRestServer(xacmlPdpParameterGroup.getRestServerParameters()), + () -> restServer = null); addAction("REST server", () -> restServer.start(), () -> restServer.stop()); - - addAction("set alive", () -> setAlive(true), () -> setAlive(false)); - - addAction("Initial Registration with PAP", - () -> { - register.pdpRegistration(message.formatInitialStatusMessage(PdpState.PASSIVE)); - }, - () -> { - register.pdpRegistration(message.formatInitialStatusMessage(PdpState.TERMINATED)); - }); // @formatter:on - - current = this; } /** @@ -208,31 +194,4 @@ public class XacmlPdpActivator extends ServiceManagerContainer { source.unregister(msgDispatcher); } } - - /** - * Returns the alive status of xacml pdp service. - * - * @return the alive - */ - @Override - public boolean isAlive() { - return alive; - } - - /** - * Change the alive status of xacml pdp service. - * - * @param status the status - */ - private void setAlive(final boolean status) { - alive = status; - } - - public static XacmlPdpActivator getCurrent() { - return current; - } - - public static void setCurrent(XacmlPdpActivator current) { - XacmlPdpActivator.current = current; - } } diff --git a/main/src/test/java/org/onap/policy/pdpx/main/CommonRest.java b/main/src/test/java/org/onap/policy/pdpx/main/CommonRest.java new file mode 100644 index 00000000..0c84419f --- /dev/null +++ b/main/src/test/java/org/onap/policy/pdpx/main/CommonRest.java @@ -0,0 +1,216 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * 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; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.SecureRandom; +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager; +import org.onap.policy.pdpx.main.startstop.Main; +import org.onap.policy.pdpx.main.startstop.XacmlPdpActivator; +import org.powermock.reflect.Whitebox; + +/** + * Common base class for REST service tests. + */ +public class CommonRest { + private static final String KEYSTORE = System.getProperty("user.dir") + "/src/test/resources/ssl/policy-keystore"; + + /** + * Full path to the config file. + */ + public static final String CONFIG_FILE; + + /** + * Path corresponding to {@link #CONFIG_FILE}. + */ + private static final Path CONFIG_PATH; + + /** + * Contents read from the "standard" config file, which still contains ${xxx} + * place-holders. + */ + private static final String STD_CONFIG; + + /** + * Port that was last allocated for the server. + */ + protected static int port; + + /** + * "Main" that was last started. + */ + private static Main main; + + /** + * Records the "alive" state of the activator while it's temporarily updated by + * various junit tests. The {@link #tearDown()} method restores the "alive" state back + * to this value. + */ + private boolean activatorWasAlive; + + static { + try { + File file = new File(ResourceUtils.getFilePath4Resource("parameters/XacmlPdpConfigParameters_Std.json")); + STD_CONFIG = new String(Files.readAllBytes(file.toPath()), StandardCharsets.UTF_8); + + file = new File(file.getParentFile(), "Test_XacmlPdpConfigParameters.json"); + file.deleteOnExit(); + + CONFIG_FILE = file.getAbsolutePath(); + CONFIG_PATH = new File(CONFIG_FILE).toPath(); + + } catch (IOException e) { + throw new ExceptionInInitializerError(e); + } + } + + /** + * Configures system properties and creates a JSON config file. + * + * @throws Exception if an error occurs + */ + @BeforeClass + public static void setUpBeforeClass() throws Exception { + System.setProperty("javax.net.ssl.keyStore", KEYSTORE); + System.setProperty("javax.net.ssl.keyStorePassword", "Pol1cy_0nap"); + + System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog"); + System.setProperty("org.eclipse.jetty.LEVEL", "OFF"); + + writeJsonConfig(); + + final String[] xacmlPdpConfigParameters = {"-c", CommonRest.CONFIG_FILE, "-p", "parameters/topic.properties"}; + main = new Main(xacmlPdpConfigParameters); + + if (!NetworkUtil.isTcpPortOpen("localhost", port, 20, 1000L)) { + throw new IllegalStateException("server is not listening on port " + port); + } + } + + /** + * Stops the "Main". + */ + @AfterClass + public static void tearDownAfterClass() { + stopMain(); + } + + /** + * Resets the statistics. + */ + @Before + public void setUp() { + activatorWasAlive = XacmlPdpActivator.getCurrent().isAlive(); + XacmlPdpStatisticsManager.getCurrent().resetAllStatistics(); + } + + /** + * Restores the "alive" status of the activator. + */ + @After + public void tearDown() { + markActivator(activatorWasAlive); + } + + /** + * Stops the "main". + */ + protected static void stopMain() { + main.shutdown(); + } + + /** + * Writes a JSON config file, substituting an allocated port number for occurrences of + * "${port}". + * + * @return the allocated server port + * @throws IOException if the config file cannot be created + */ + public static int writeJsonConfig() throws IOException { + port = NetworkUtil.allocPort(); + + String config = STD_CONFIG.replace("${port}", String.valueOf(port)); + Files.write(CONFIG_PATH, config.getBytes(StandardCharsets.UTF_8)); + + return port; + } + + /** + * Sends an HTTPS request to an endpoint of the PDP's REST API. + * + * @param endpoint target endpoint + * @return a request builder + * @throws Exception if an error occurs + */ + protected Invocation.Builder sendHttpsRequest(final String endpoint) throws Exception { + // always trust the certificate + final SSLContext sc = SSLContext.getInstance("TLSv1.2"); + sc.init(null, NetworkUtil.getAlwaysTrustingManager(), new SecureRandom()); + + // always trust the host name + final ClientBuilder clientBuilder = + ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true); + + final Client client = clientBuilder.build(); + final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34"); + client.register(feature); + + final WebTarget webTarget = client.target("https://localhost:" + port + "/policy/pdpx/v1/" + endpoint); + + return webTarget.request(MediaType.APPLICATION_JSON); + } + + /** + * Mark the activator as dead, but leave its REST server running. + */ + protected void markActivatorDead() { + markActivator(false); + } + + /** + * Changes the internal "alive" status of the activator to a new value. + * + * @param newAlive the new "alive" status + */ + private void markActivator(boolean newAlive) { + Object manager = Whitebox.getInternalState(XacmlPdpActivator.getCurrent(), "serviceManager"); + Whitebox.setInternalState(manager, "running", newAlive); + } +} 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 index 3a1e98b1..5f7eb78c 100644 --- 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 @@ -67,6 +67,7 @@ public class TestDecision { private static final Logger LOGGER = LoggerFactory.getLogger(TestDecision.class); + private static int port; private static Main main; private static HttpClient client; @@ -82,6 +83,9 @@ public class TestDecision { public static void beforeClass() throws Exception { System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog"); System.setProperty("org.eclipse.jetty.LEVEL", "OFF"); + + port = NetworkUtil.allocPort(); + // // Copy test directory over of the application directories // @@ -94,7 +98,7 @@ public class TestDecision { // Get the parameters file correct. // RestServerParameters rest = new RestServerParameters(new RestServerBuilder() - .setHost("0.0.0.0").setPort(6969).setUserName("healthcheck").setPassword("zb!XztG34")); + .setHost("0.0.0.0").setPort(port).setUserName("healthcheck").setPassword("zb!XztG34")); XacmlPdpParameterGroup params = new XacmlPdpParameterGroup("XacmlPdpGroup", rest, apps.getAbsolutePath()); final Gson gson = new GsonBuilder().create(); File fileParams = appsFolder.newFile("params.json"); @@ -108,8 +112,8 @@ public class TestDecision { // // Make sure it is running // - if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 20, 1000L)) { - throw new IllegalStateException("Cannot connect to port 6969"); + if (!NetworkUtil.isTcpPortOpen("localhost", port, 20, 1000L)) { + throw new IllegalStateException("Cannot connect to port " + port); } // // Create a client @@ -123,8 +127,7 @@ public class TestDecision { } @Test - public void testDecision_UnsupportedAction() throws KeyManagementException, NoSuchAlgorithmException, - ClassNotFoundException { + public void testDecision_UnsupportedAction() throws Exception { LOGGER.info("Running test testDecision_UnsupportedAction"); @@ -165,7 +168,7 @@ public class TestDecision { assertThat(response.getStatus()).isEqualTo("Permit"); } - private static Main startXacmlPdpService(File params) { + private static Main startXacmlPdpService(File params) throws PolicyXacmlPdpException { final String[] XacmlPdpConfigParameters = {"-c", params.getAbsolutePath(), "-p", "parameters/topic.properties"}; return new Main(XacmlPdpConfigParameters); @@ -200,7 +203,7 @@ public class TestDecision { return HttpClient.factory.build(BusTopicParams.builder() .clientName("testDecisionClient") .serializationProvider(GsonMessageBodyHandler.class.getName()) - .useHttps(false).allowSelfSignedCerts(false).hostname("localhost").port(6969) + .useHttps(false).allowSelfSignedCerts(false).hostname("localhost").port(port) .basePath("policy/pdpx/v1/decision") .userName("healthcheck").password("zb!XztG34").managed(true).build()); } diff --git a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpRestServer.java b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpRestServer.java index f9f2abf3..ba8f0044 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpRestServer.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpRestServer.java @@ -21,41 +21,12 @@ package org.onap.policy.pdpx.main.rest; 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; -import java.security.SecureRandom; -import java.security.cert.X509Certificate; -import java.util.Properties; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Invocation; -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.After; -import org.junit.BeforeClass; -import org.junit.ClassRule; -import org.junit.FixMethodOrder; import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runners.MethodSorters; -import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException; import org.onap.policy.common.endpoints.report.HealthCheckReport; -import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.pdpx.main.PolicyXacmlPdpException; -import org.onap.policy.pdpx.main.parameters.CommonTestData; -import org.onap.policy.pdpx.main.parameters.RestServerParameters; +import org.onap.policy.pdpx.main.CommonRest; import org.onap.policy.pdpx.main.rest.model.StatisticsReport; -import org.onap.policy.pdpx.main.startstop.Main; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,8 +34,7 @@ import org.slf4j.LoggerFactory; * Class to perform unit test of {@link XacmlPdpRestServer}. * */ -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class TestXacmlPdpRestServer { +public class TestXacmlPdpRestServer extends CommonRest { private static final Logger LOGGER = LoggerFactory.getLogger(TestXacmlPdpRestServer.class); private static final String NOT_ALIVE = "not alive"; @@ -73,224 +43,79 @@ public class TestXacmlPdpRestServer { private static final String NAME = "Policy Xacml PDP"; private static final String HEALTHCHECK_ENDPOINT = "healthcheck"; private static final String STATISTICS_ENDPOINT = "statistics"; - 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() 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(); - } - - /** - * Method for cleanup after each test. - */ - @After - public void teardown() { - try { - if (NetworkUtil.isTcpPortOpen("localhost", 6969, 1, 1000L)) { - if (main != null) { - stopXacmlPdpService(main); - main = null; - } - - if (restServer != null) { - restServer.stop(); - restServer = null; - } - } - } catch (IOException | PolicyXacmlPdpException e) { - LOGGER.error("teardown failed", e); - } catch (InterruptedException ie) { - Thread.interrupted(); - LOGGER.error("teardown failed", ie); - } - } @Test - public void test1HealthCheckSuccess() throws IOException, InterruptedException, TopicSinkClientException { - LOGGER.info("***************************** Running test1HealthCheckSuccess *****************************"); - main = startXacmlPdpService(true); - final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT); + public void testHealthCheckSuccess() throws Exception { + LOGGER.info("***************************** Running testHealthCheckSuccess *****************************"); + final Invocation.Builder invocationBuilder = sendHttpsRequest(HEALTHCHECK_ENDPOINT); final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class); LOGGER.info("test1HealthCheckSuccess health report {}", report); validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report); } @Test - public void test7HealthCheckFailure() throws InterruptedException, IOException { - LOGGER.info("***************************** Running test7HealthCheckFailure *****************************"); - final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false); - restServerParams.setName(CommonTestData.PDPX_GROUP_NAME); - restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath()); - restServer.start(); - final Invocation.Builder invocationBuilder = sendHttpRequest(HEALTHCHECK_ENDPOINT); + public void testHealthCheckFailure() throws Exception { + LOGGER.info("***************************** Running testHealthCheckFailure *****************************"); + + markActivatorDead(); + + final Invocation.Builder invocationBuilder = sendHttpsRequest(HEALTHCHECK_ENDPOINT); final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class); - LOGGER.info("test7HealthCheckFailure health report {}", report); + LOGGER.info("testHealthCheckFailure health report {}", report); validateHealthCheckReport(NAME, SELF, false, 500, NOT_ALIVE, report); - assertTrue(restServer.isAlive()); - assertTrue(restServer.toString().startsWith("XacmlPdpRestServer [servers=")); } @Test - public void test2HttpsHealthCheckSuccess() throws Exception { - LOGGER.info("**************************** Running test2HttpsHealthCheckSuccess ****************************"); - main = startXacmlPdpService(false); + public void testHttpsHealthCheckSuccess() throws Exception { + LOGGER.info("***************************** Running testHttpsHealthCheckSuccess *****************************"); final Invocation.Builder invocationBuilder = sendHttpsRequest(HEALTHCHECK_ENDPOINT); final HealthCheckReport report = invocationBuilder.get(HealthCheckReport.class); - LOGGER.info("test2HttpsHealthCheckSuccess health report {}", report); + LOGGER.info("testHttpsHealthCheckSuccess health report {}", report); validateHealthCheckReport(NAME, SELF, true, 200, ALIVE, report); } @Test - public void test4Statistics_200() throws IOException, InterruptedException, TopicSinkClientException { - LOGGER.info("***************************** Running test4Statistics_200 *****************************"); - XacmlPdpStatisticsManager.resetAllStatistics(); - main = startXacmlPdpService(true); - Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT); + public void testStatistics_200() throws Exception { + LOGGER.info("***************************** Running testStatistics_200 *****************************"); + Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT); StatisticsReport report = invocationBuilder.get(StatisticsReport.class); - LOGGER.info("test4Statistics_200 health report {}", report); + LOGGER.info("testStatistics_200 health report {}", report); validateStatisticsReport(report, 0, 200); updateXacmlPdpStatistics(); - invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT); + invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT); report = invocationBuilder.get(StatisticsReport.class); - LOGGER.info("test4Statistics_200 health report {}", report); + LOGGER.info("testStatistics_200 health report {}", report); validateStatisticsReport(report, 1, 200); - XacmlPdpStatisticsManager.resetAllStatistics(); } @Test - public void test5Statistics_500() throws IOException, InterruptedException { - LOGGER.info("***************************** Running test5Statistics_500 *****************************"); - final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false); - restServerParams.setName(CommonTestData.PDPX_GROUP_NAME); - restServer = new XacmlPdpRestServer(restServerParams, applicationPath.getAbsolutePath()); - restServer.start(); - final Invocation.Builder invocationBuilder = sendHttpRequest(STATISTICS_ENDPOINT); + public void testStatistics_500() throws Exception { + LOGGER.info("***************************** Running testStatistics_500 *****************************"); + + markActivatorDead(); + + final Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT); final StatisticsReport report = invocationBuilder.get(StatisticsReport.class); - LOGGER.info("test5Statistics_500 health report {}", report); + LOGGER.info("testStatistics_500 health report {}", report); validateStatisticsReport(report, 0, 500); - XacmlPdpStatisticsManager.resetAllStatistics(); } @Test - public void test6HttpsStatistic() throws Exception { - LOGGER.info("***************************** Running test6HttpsStatistic *****************************"); - main = startXacmlPdpService(false); + public void testHttpsStatistic() throws Exception { + LOGGER.info("***************************** Running testHttpsStatistic *****************************"); final Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT); final StatisticsReport report = invocationBuilder.get(StatisticsReport.class); - LOGGER.info("test6HttpsStatistic health report {}", report); + LOGGER.info("testHttpsStatistic health report {}", report); validateStatisticsReport(report, 0, 200); } - @Test - public void test3StatisticsConstructorIsPrivate() { - LOGGER.info("************************* Running test3StatisticsConstructorIsPrivate *************************"); - try { - final Constructor constructor = - XacmlPdpStatisticsManager.class.getDeclaredConstructor(); - assertTrue(Modifier.isPrivate(constructor.getModifiers())); - constructor.setAccessible(true); - constructor.newInstance(); - fail("Expected an InstantiationException to be thrown"); - } catch (final Exception exp) { - assertTrue(exp.getCause().toString().contains("Instantiation of the class is not allowed")); - } - } - - private Main startXacmlPdpService(final boolean http) throws TopicSinkClientException { - final String[] xacmlPdpConfigParameters = new String[4]; - if (http) { - xacmlPdpConfigParameters[0] = "-c"; - xacmlPdpConfigParameters[1] = "parameters/XacmlPdpConfigParameters.json"; - xacmlPdpConfigParameters[2] = "-p"; - xacmlPdpConfigParameters[3] = "parameters/topic.properties"; - } else { - final Properties systemProps = System.getProperties(); - systemProps.put("javax.net.ssl.keyStore", KEYSTORE); - systemProps.put("javax.net.ssl.keyStorePassword", "Pol1cy_0nap"); - System.setProperties(systemProps); - xacmlPdpConfigParameters[0] = "-c"; - xacmlPdpConfigParameters[1] = "parameters/XacmlPdpConfigParameters_Https.json"; - xacmlPdpConfigParameters[2] = "-p"; - xacmlPdpConfigParameters[3] = "parameters/topic.properties"; - } - return new Main(xacmlPdpConfigParameters); - } - - private void stopXacmlPdpService(final Main main) throws PolicyXacmlPdpException { - main.shutdown(); - } - - private Invocation.Builder sendHttpRequest(final String endpoint) throws IOException, InterruptedException { - 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/" + endpoint); - - final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); - - if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 20, 1000L)) { - throw new IllegalStateException("Cannot connect to port 6969"); - } - - return invocationBuilder; - } - - private Invocation.Builder sendHttpsRequest(final String endpoint) throws Exception { - - final TrustManager[] noopTrustManager = new TrustManager[] {new X509TrustManager() { - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void checkClientTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {} - - @Override - public void checkServerTrusted(final java.security.cert.X509Certificate[] certs, final String authType) {} - } }; - - final SSLContext sc = SSLContext.getInstance("TLSv1.2"); - sc.init(null, noopTrustManager, new SecureRandom()); - final ClientBuilder clientBuilder = - ClientBuilder.newBuilder().sslContext(sc).hostnameVerifier((host, session) -> true); - final Client client = clientBuilder.build(); - final HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("healthcheck", "zb!XztG34"); - client.register(feature); - - final WebTarget webTarget = client.target("https://localhost:6969/policy/pdpx/v1/" + endpoint); - - 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; - } - private void updateXacmlPdpStatistics() { - XacmlPdpStatisticsManager.updateTotalPoliciesCount(); - XacmlPdpStatisticsManager.updatePermitDecisionsCount(); - XacmlPdpStatisticsManager.updateDenyDecisionsCount(); - XacmlPdpStatisticsManager.updateIndeterminantDecisionsCount(); - XacmlPdpStatisticsManager.updateNotApplicableDecisionsCount(); + XacmlPdpStatisticsManager stats = XacmlPdpStatisticsManager.getCurrent(); + stats.updateTotalPoliciesCount(); + stats.updatePermitDecisionsCount(); + stats.updateDenyDecisionsCount(); + stats.updateIndeterminantDecisionsCount(); + stats.updateNotApplicableDecisionsCount(); } private void validateStatisticsReport(final StatisticsReport report, final int count, final int code) { @@ -303,7 +128,7 @@ public class TestXacmlPdpRestServer { } private void validateHealthCheckReport(final String name, final String url, final boolean healthy, final int code, - final String message, final HealthCheckReport report) { + final String message, final HealthCheckReport report) { assertEquals(name, report.getName()); assertEquals(url, report.getUrl()); assertEquals(healthy, report.isHealthy()); diff --git a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpStatistics.java b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpStatistics.java index 6a762924..250f21e6 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpStatistics.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpStatistics.java @@ -21,31 +21,11 @@ package org.onap.policy.pdpx.main.rest; -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; -import javax.ws.rs.client.Invocation; -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.BeforeClass; -import org.junit.ClassRule; import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException; -import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.pdpx.main.PolicyXacmlPdpException; -import org.onap.policy.pdpx.main.parameters.CommonTestData; -import org.onap.policy.pdpx.main.parameters.RestServerParameters; -import org.onap.policy.pdpx.main.rest.XacmlPdpStatisticsManager; +import org.onap.policy.pdpx.main.CommonRest; import org.onap.policy.pdpx.main.rest.model.StatisticsReport; -import org.onap.policy.pdpx.main.startstop.Main; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,101 +33,42 @@ import org.slf4j.LoggerFactory; * Class to perform unit test of {@link XacmlPdpRestController}. * */ -public class TestXacmlPdpStatistics { +public class TestXacmlPdpStatistics extends CommonRest { 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() 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 - public void testXacmlPdpStatistics_200() throws PolicyXacmlPdpException, InterruptedException { - try { - LOGGER.info("*************************** Running testXacmlPdpStatistics_200 ***************************"); - final Main main = startXacmlPdpService(); - StatisticsReport report = getXacmlPdpStatistics(); - validateReport(report, 0, 200); - assertThat(report.getTotalPolicyTypesCount()).isGreaterThan(0); - updateXacmlPdpStatistics(); - report = getXacmlPdpStatistics(); - validateReport(report, 1, 200); - stopXacmlPdpService(main); - XacmlPdpStatisticsManager.resetAllStatistics(); - } catch (final Exception e) { - LOGGER.error("testApiStatistics_200 failed", e); - fail("Test should not throw an exception"); - } + public void testXacmlPdpStatistics_200() throws Exception { + LOGGER.info("*************************** Running testXacmlPdpStatistics_200 ***************************"); + StatisticsReport report = getXacmlPdpStatistics(); + validateReport(report, 0, 200); + updateXacmlPdpStatistics(); + report = getXacmlPdpStatistics(); + validateReport(report, 1, 200); } @Test - public void testXacmlPdpStatistics_500() throws InterruptedException { + public void testXacmlPdpStatistics_500() throws Exception { LOGGER.info("***************************** Running testXacmlPdpStatistics_500 *****************************"); - final RestServerParameters restServerParams = new CommonTestData().getRestServerParameters(false); - restServerParams.setName(CommonTestData.PDPX_GROUP_NAME); - final XacmlPdpRestServer restServer = new XacmlPdpRestServer(restServerParams, - applicationPath.getAbsolutePath()); - try { - restServer.start(); - final StatisticsReport report = getXacmlPdpStatistics(); - validateReport(report, 0, 500); - restServer.shutdown(); - XacmlPdpStatisticsManager.resetAllStatistics(); - } catch (final Exception e) { - LOGGER.error("testApiStatistics_500 failed", e); - fail("Test should not throw an exception"); - } - } - - - private Main startXacmlPdpService() throws TopicSinkClientException { - final String[] XacmlPdpConfigParameters = {"-c", "parameters/XacmlPdpConfigParameters.json", "-p", - "parameters/topic.properties"}; - return new Main(XacmlPdpConfigParameters); - } + markActivatorDead(); - private void stopXacmlPdpService(final Main main) throws PolicyXacmlPdpException { - main.shutdown(); + final StatisticsReport report = getXacmlPdpStatistics(); + validateReport(report, 0, 500); } - private StatisticsReport getXacmlPdpStatistics() 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/statistics"); - - final Invocation.Builder invocationBuilder = webTarget.request(MediaType.APPLICATION_JSON); - - if (!NetworkUtil.isTcpPortOpen("localhost", 6969, 20, 1000L)) { - throw new IllegalStateException("Cannot connect to port 6969"); - } - - return invocationBuilder.get(StatisticsReport.class); + private StatisticsReport getXacmlPdpStatistics() throws Exception { + return sendHttpsRequest("statistics").get(StatisticsReport.class); } private void updateXacmlPdpStatistics() { - XacmlPdpStatisticsManager.updateTotalPoliciesCount(); - XacmlPdpStatisticsManager.updatePermitDecisionsCount(); - XacmlPdpStatisticsManager.updateDenyDecisionsCount(); - XacmlPdpStatisticsManager.updateIndeterminantDecisionsCount(); - XacmlPdpStatisticsManager.updateNotApplicableDecisionsCount(); + XacmlPdpStatisticsManager stats = XacmlPdpStatisticsManager.getCurrent(); + + stats.updateTotalPoliciesCount(); + stats.updatePermitDecisionsCount(); + stats.updateDenyDecisionsCount(); + stats.updateIndeterminantDecisionsCount(); + stats.updateNotApplicableDecisionsCount(); } private void validateReport(final StatisticsReport report, final int count, final int code) { diff --git a/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestMain.java b/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestMain.java index 80ee95f6..e8448ab2 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestMain.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestMain.java @@ -20,70 +20,84 @@ package org.onap.policy.pdpx.main.startstop; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import org.junit.After; import org.junit.Assert; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException; +import org.onap.policy.pdpx.main.CommonRest; import org.onap.policy.pdpx.main.PolicyXacmlPdpException; -import org.onap.policy.pdpx.main.parameters.CommonTestData; /** * Class to perform unit test of Main. * */ -public class TestMain { +public class TestMain extends CommonRest { + + private Main main; /** - * setup. + * Sets up properties and configuration. + * @throws Exception if an error occurs */ @BeforeClass - public static void setUp() { - System.setProperty("org.eclipse.jetty.util.log.class", "org.eclipse.jetty.util.log.StdErrLog"); - System.setProperty("org.eclipse.jetty.LEVEL", "OFF"); + public static void setUpBeforeClass() throws Exception { + CommonRest.setUpBeforeClass(); + + // don't want the common "main" running + CommonRest.stopMain(); + } + + @Before + public void setUp() { + main = null; + } + /** + * Shuts "main" down. + */ + @After + public void tearDown() { + if (main != null) { + main.shutdown(); + } } @Test - public void testMain() throws PolicyXacmlPdpException, TopicSinkClientException { - final String[] xacmlPdpConfigParameters = {"-c", "parameters/XacmlPdpConfigParameters.json"}; - final Main main = new Main(xacmlPdpConfigParameters); - assertTrue(main.getParameters().isValid()); - assertEquals(CommonTestData.PDPX_GROUP_NAME, main.getParameters().getName()); + public void testMain() throws PolicyXacmlPdpException { + final String[] xacmlPdpConfigParameters = {"-c", CONFIG_FILE, "-p", "parameters/topic.properties"}; + main = new Main(xacmlPdpConfigParameters); main.shutdown(); + main = null; } @Test - public void testMain_NoArguments() throws PolicyXacmlPdpException, TopicSinkClientException { + public void testMain_NoArguments() { final String[] xacmlPdpConfigParameters = {}; - final Main main = new Main(xacmlPdpConfigParameters); - assertNull(main.getParameters()); - main.shutdown(); + assertThatThrownBy(() -> new Main(xacmlPdpConfigParameters)).isInstanceOf(PolicyXacmlPdpException.class) + .hasMessage("policy xacml pdp configuration file was not specified as an argument"); } @Test - public void testMain_InvalidArguments() throws TopicSinkClientException { + public void testMain_InvalidArguments() { final String[] xacmlPdpConfigParameters = {"parameters/XacmlPdpConfigParameters.json"}; - final Main main = new Main(xacmlPdpConfigParameters); - assertNull(main.getParameters()); + assertThatThrownBy(() -> new Main(xacmlPdpConfigParameters)).isInstanceOf(PolicyXacmlPdpException.class) + .hasMessage("too many command line arguments specified : [parameters/XacmlPdpConfigParameters.json]"); } @Test - public void testMain_Help() throws TopicSinkClientException { + public void testMain_Help() throws PolicyXacmlPdpException { final String[] xacmlPdpConfigParameters = {"-h"}; - final Main main = new Main(xacmlPdpConfigParameters); - final String message = "-h,--help outputs the usage of this command"; - Assert.assertTrue(main.getArgumentMessage().contains(message)); + Assert.assertTrue(new Main(xacmlPdpConfigParameters).getArgumentMessage().contains("-h,--help")); } @Test - public void testMain_InvalidParameters() throws TopicSinkClientException { + public void testMain_InvalidParameters() { final String[] xacmlPdpConfigParameters = {"-c", "parameters/XacmlPdpConfigParameters_InvalidName.json"}; - final Main main = new Main(xacmlPdpConfigParameters); - assertNull(main.getParameters()); + assertThatThrownBy(() -> new Main(xacmlPdpConfigParameters)).isInstanceOf(PolicyXacmlPdpException.class) + .hasMessageContaining("validation error"); } } diff --git a/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestXacmlPdpActivator.java b/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestXacmlPdpActivator.java index 5930dd5e..b60f4589 100644 --- a/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestXacmlPdpActivator.java +++ b/main/src/test/java/org/onap/policy/pdpx/main/startstop/TestXacmlPdpActivator.java @@ -26,13 +26,12 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.io.FileInputStream; -import java.net.UnknownHostException; import java.util.Properties; - import org.junit.After; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; -import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClientException; +import org.onap.policy.pdpx.main.CommonRest; import org.onap.policy.pdpx.main.PolicyXacmlPdpException; import org.onap.policy.pdpx.main.parameters.CommonTestData; import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterGroup; @@ -43,30 +42,44 @@ import org.onap.policy.pdpx.main.parameters.XacmlPdpParameterHandler; * Class to perform unit test of XacmlPdpActivator. * */ -public class TestXacmlPdpActivator { - private static XacmlPdpActivator activator = null; +public class TestXacmlPdpActivator extends CommonRest { + private static XacmlPdpParameterGroup parGroup; + private static Properties props; + + private XacmlPdpActivator activator = null; /** - * Setup the tests. + * Loads properties. */ @BeforeClass - public static void setup() throws Exception { + public static void setUpBeforeClass() throws Exception { + CommonRest.setUpBeforeClass(); + final String[] xacmlPdpConfigParameters = - {"-c", "parameters/XacmlPdpConfigParameters.json", "-p", "parameters/topic.properties"}; + {"-c", CommonRest.CONFIG_FILE, "-p", "parameters/topic.properties"}; final XacmlPdpCommandLineArguments arguments = new XacmlPdpCommandLineArguments(xacmlPdpConfigParameters); - final XacmlPdpParameterGroup parGroup = new XacmlPdpParameterHandler().getParameters(arguments); + parGroup = new XacmlPdpParameterHandler().getParameters(arguments); - Properties props = new Properties(); + props = new Properties(); String propFile = arguments.getFullPropertyFilePath(); try (FileInputStream stream = new FileInputStream(propFile)) { props.load(stream); } + // don't want the common "main" running + CommonRest.stopMain(); + } + + /** + * Creates the activator. + */ + @Before + public void setUp() { activator = new XacmlPdpActivator(parGroup, props); } @Test - public void testXacmlPdpActivator() throws PolicyXacmlPdpException, TopicSinkClientException, UnknownHostException { + public void testXacmlPdpActivator() throws Exception { assertFalse(activator.isAlive()); activator.start(); assertTrue(activator.isAlive()); @@ -77,14 +90,13 @@ public class TestXacmlPdpActivator { @Test public void testGetCurrent_testSetCurrent() { + XacmlPdpActivator.setCurrent(activator); assertSame(activator, XacmlPdpActivator.getCurrent()); } @Test public void testTerminate() throws Exception { - if (!activator.isAlive()) { - activator.start(); - } + activator.start(); activator.stop(); assertFalse(activator.isAlive()); } diff --git a/main/src/test/resources/parameters/XacmlPdpConfigParameters_Https.json b/main/src/test/resources/parameters/XacmlPdpConfigParameters_Https.json deleted file mode 100644 index ae5e1cbd..00000000 --- a/main/src/test/resources/parameters/XacmlPdpConfigParameters_Https.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name":"XacmlPdpGroup", - "restServerParameters":{ - "host":"0.0.0.0", - "port":6969, - "userName":"healthcheck", - "password":"zb!XztG34", - "https":true - }, - "applicationPath": "src/test/resources/apps" -} \ No newline at end of file diff --git a/main/src/test/resources/parameters/XacmlPdpConfigParameters_Std.json b/main/src/test/resources/parameters/XacmlPdpConfigParameters_Std.json new file mode 100644 index 00000000..5b6586a3 --- /dev/null +++ b/main/src/test/resources/parameters/XacmlPdpConfigParameters_Std.json @@ -0,0 +1,11 @@ +{ + "name":"XacmlPdpGroup", + "restServerParameters":{ + "host":"0.0.0.0", + "port":${port}, + "userName":"healthcheck", + "password":"zb!XztG34", + "https":true + }, + "applicationPath": "src/test/resources/apps" +} \ No newline at end of file -- cgit 1.2.3-korg