From 77d088a607c33c236bc41c58d9567e10299357a5 Mon Sep 17 00:00:00 2001 From: jhh Date: Fri, 15 Jan 2021 16:51:47 -0600 Subject: sync policies when native artifact policies added interoperability between native and non-native policies present several difficulties. The code submitted operates in deltas where deploy and undeploy operations are performed on the deltas of the updates. In order to support interoperability, policies not part of a delta update may need to be reapplied. For example, in the case when the delta is just a new native controller artifact, we should go through the set of already deployed policies and reapply non-native policies as long as the policy types that the native artifact policy supports. Issue-ID: POLICY-2762 Signed-off-by: jhh Change-Id: Ieb8e5e17862e9d607433a1d4e86a026725d73498 Signed-off-by: jhh --- .../policy/drools/lifecycle/LifecycleFeature.java | 16 +- .../onap/policy/drools/lifecycle/LifecycleFsm.java | 52 +- .../drools/lifecycle/LifecycleStatePassive.java | 5 +- .../drools/lifecycle/LifecycleStateRunning.java | 186 ++++++- .../lifecycle/PolicyTypeDroolsController.java | 29 +- .../server/restful/RestLifecycleManager.java | 64 +-- .../policy/drools/lifecycle/ControllerSupport.java | 47 +- .../policy/drools/lifecycle/LifecycleFsmTest.java | 29 +- .../drools/lifecycle/LifecycleFsmUpdateTest.java | 585 +++++++++++++++++++++ .../lifecycle/LifecycleStatePassiveTest.java | 17 +- .../lifecycle/PolicyTypeDroolsControllerTest.java | 32 +- .../server/restful/RestLifecycleManagerTest.java | 11 +- feature-lifecycle/src/test/resources/echo.drl | 35 ++ feature-lifecycle/src/test/resources/echo.kmodule | 27 + feature-lifecycle/src/test/resources/echo.pom | 31 ++ .../tosca-policy-native-artifact-foo.json | 2 +- 16 files changed, 1055 insertions(+), 113 deletions(-) create mode 100644 feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java create mode 100644 feature-lifecycle/src/test/resources/echo.drl create mode 100644 feature-lifecycle/src/test/resources/echo.kmodule create mode 100644 feature-lifecycle/src/test/resources/echo.pom (limited to 'feature-lifecycle') diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java index 003740c1..27d845b5 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 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. @@ -20,6 +20,7 @@ package org.onap.policy.drools.lifecycle; +import lombok.Getter; import org.onap.policy.drools.features.DroolsControllerFeatureApi; import org.onap.policy.drools.features.PolicyControllerFeatureApi; import org.onap.policy.drools.features.PolicyEngineFeatureApi; @@ -35,6 +36,7 @@ public class LifecycleFeature /** * Lifecycle FSM. */ + @Getter public static final LifecycleFsm fsm = new LifecycleFsm(); @Override @@ -90,32 +92,32 @@ public class LifecycleFeature } private boolean fsmStart() { - fsm.start(); + getFsm().start(); return false; } private boolean fsmStart(PolicyController controller) { - fsm.start(controller); + getFsm().start(controller); return false; } private boolean fsmStop() { - fsm.stop(); + getFsm().stop(); return false; } private boolean fsmStop(PolicyController controller) { - fsm.stop(controller); + getFsm().stop(controller); return false; } private boolean fsmPatch(PolicyController controller) { - fsm.patch(controller); + getFsm().patch(controller); return false; } private boolean fsmShutdown() { - fsm.shutdown(); + getFsm().shutdown(); return false; } } diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java index 5478136f..d56e06e9 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java @@ -156,9 +156,7 @@ public class LifecycleFsm implements Startable { String commaSeparatedPolicyTypes = this.properties.getProperty(MANDATORY_POLICY_TYPES); if (!StringUtils.isBlank(commaSeparatedPolicyTypes)) { - for (String mpt: commaSeparatedPolicyTypes.split("\\s*,\\s*")) { - this.mandatoryPolicyTypes.add(mpt); - } + Collections.addAll(this.mandatoryPolicyTypes, commaSeparatedPolicyTypes.split("\\s*,\\s*")); } logger.info("The mandatory Policy Types are {}. Compliance is {}", @@ -347,7 +345,7 @@ public class LifecycleFsm implements Startable { protected List getDeployablePoliciesAction(@NonNull List policies) { List deployPolicies = new ArrayList<>(policies); - deployPolicies.removeAll(policiesMap.values()); + deployPolicies.removeAll(getActivePolicies()); // Ensure that the sequence of policy deployments is sane to minimize potential errors, // First policies to deploy are the controller related ones, those that affect the lifecycle of @@ -359,13 +357,12 @@ public class LifecycleFsm implements Startable { Map> policyTypeGroups = groupPoliciesByPolicyType(deployPolicies); // place native controller policies at the start of the list - List orderedDeployableList = - new ArrayList<>(policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName(), - Collections.EMPTY_LIST)); + List orderedDeployableList = new ArrayList<>( + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName(), Collections.emptyList())); // add to the working list the native controller policies orderedDeployableList.addAll( - policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_RULES.getName(), Collections.EMPTY_LIST)); + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_RULES.getName(), Collections.emptyList())); // place non-native policies to place at the end of the list orderedDeployableList.addAll(getNonNativePolicies(policyTypeGroups)); @@ -374,7 +371,7 @@ public class LifecycleFsm implements Startable { } protected List getUndeployablePoliciesAction(@NonNull List policies) { - List undeployPolicies = new ArrayList<>(policiesMap.values()); + List undeployPolicies = new ArrayList<>(getActivePolicies()); undeployPolicies.removeAll(policies); if (undeployPolicies.isEmpty()) { return undeployPolicies; @@ -396,11 +393,11 @@ public class LifecycleFsm implements Startable { // add to the working list the native rules policies if any orderedUndeployableList.addAll( - policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_RULES.getName(), Collections.EMPTY_LIST)); + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_RULES.getName(), Collections.emptyList())); // finally add to the working list native controller policies if any orderedUndeployableList.addAll( - policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName(), Collections.EMPTY_LIST)); + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName(), Collections.emptyList())); return orderedUndeployableList; } @@ -414,13 +411,13 @@ public class LifecycleFsm implements Startable { } protected List resetPoliciesAction() { - List policies = new ArrayList<>(policiesMap.values()); + List policies = new ArrayList<>(getActivePolicies()); policiesMap.clear(); return policies; } - protected boolean updatePoliciesAction(List toscaPolicies) { - return (this.scheduler.submit(() -> state.updatePolicies(toscaPolicies)) != null); + protected void updatePoliciesAction(List toscaPolicies) { + this.scheduler.submit(() -> state.updatePolicies(toscaPolicies)); } protected PolicyTypeController getController(ToscaConceptIdentifier policyType) { @@ -428,7 +425,9 @@ public class LifecycleFsm implements Startable { } protected Map> groupPoliciesByPolicyType(List deployPolicies) { - return deployPolicies.stream().collect(Collectors.groupingBy(policy -> policy.getTypeIdentifier().getName())); + return deployPolicies.stream() + .distinct() + .collect(Collectors.groupingBy(policy -> policy.getTypeIdentifier().getName())); } protected List getNonNativePolicies(@NonNull Map> policyTypeGroups) { @@ -438,6 +437,25 @@ public class LifecycleFsm implements Startable { .flatMap(entry -> entry.getValue().stream()).collect(Collectors.toList()); } + protected List getNativeArtifactPolicies(@NonNull Map> policyTypeGroups) { + return policyTypeGroups.entrySet().stream() + .filter(entry -> entry.getKey().equals(POLICY_TYPE_DROOLS_NATIVE_RULES.getName())) + .flatMap(entry -> entry.getValue().stream()).collect(Collectors.toList()); + } + + protected List getNativeControllerPolicies(@NonNull Map> policyTypeGroups) { + return policyTypeGroups.entrySet().stream() + .filter(entry -> entry.getKey().equals(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName())) + .flatMap(entry -> entry.getValue().stream()).collect(Collectors.toList()); + } + + protected String getPolicyIdsMessage(List policies) { + return policies.stream() + .distinct() + .map(ToscaPolicy::getIdentifier).collect(Collectors.toList()) + .toString(); + } + /** * Do I support the mandatory policy types?. */ @@ -450,6 +468,10 @@ public class LifecycleFsm implements Startable { .map(ToscaConceptIdentifier::getName).collect(Collectors.toSet()); } + protected List getActivePolicies() { + return new ArrayList<>(policiesMap.values()); + } + /* ** Action Helpers ** */ private boolean startIo() { diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java index 438dc577..e085e622 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 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. @@ -45,7 +45,8 @@ public class LifecycleStatePassive extends LifecycleStateRunning { protected boolean stateChangeToActive(@NonNull PdpStateChange change) { fsm.transitionToAction(new LifecycleStateActive(fsm)); fsm.statusAction(response(change.getRequestId(), PdpResponseStatus.SUCCESS, null)); - return fsm.updatePoliciesAction(fsm.resetPoliciesAction()); + fsm.updatePoliciesAction(fsm.resetPoliciesAction()); + return true; } @Override diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java index 86540093..77850824 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2019 Bell Canada. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ @@ -22,9 +22,15 @@ package org.onap.policy.drools.lifecycle; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.function.BiPredicate; import lombok.NonNull; +import org.apache.commons.lang3.tuple.Pair; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.drools.domain.models.artifact.NativeArtifactPolicy; import org.onap.policy.drools.policies.DomainMaker; import org.onap.policy.models.pdp.concepts.PdpResponseDetails; import org.onap.policy.models.pdp.concepts.PdpStateChange; @@ -124,21 +130,57 @@ public abstract class LifecycleStateRunning extends LifecycleStateDefault { return false; } + // update subgroup if applicable per update message + fsm.setSubGroupAction(update.getPdpSubgroup()); - if (!updatePolicies(update.getPolicies())) { - fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.FAIL, "cannot process policies")); - return false; - } + // snapshot the active policies previous to apply the new set of active + // policies as given by the PAP in the update message + + List activePoliciesPreUpdate = fsm.getActivePolicies(); + + // update policies with the current set of active policies + + Pair, List> results = updatePoliciesWithResults(update.getPolicies()); + + // summary message to return in the update response to the PAP - return fsm.statusAction(response(update.getRequestId(), PdpResponseStatus.SUCCESS, null)); + List failedPolicies = new ArrayList<>(results.getLeft()); + failedPolicies.addAll(results.getRight()); + + // If there are *new* native controller policies deployed, there may + // existing native artifact policies (previous to the update event + // processing) that would need to be reapplied. This requires + // going through the list of those native artifact policies that + // were neither deployed or undeployed and re-apply them on top + // of the controllers. + + failedPolicies.addAll(reapplyNativeArtifactPolicies(activePoliciesPreUpdate)); + + // If there are *new* native artifact policies deployed, there may be existing + // non-native policies (previous to the update event processing) + // that will need to be reapplied as the new controllers don't know about them. + // This requires going through the list of those non-native policies + // which neither were undeployed or deployed and re-apply them on top of the + // new "brained" controllers. + + failedPolicies.addAll(reapplyNonNativePolicies(activePoliciesPreUpdate)); + + return fsm.statusAction(response(update.getRequestId(), + (failedPolicies.isEmpty()) ? PdpResponseStatus.SUCCESS : PdpResponseStatus.FAIL, + fsm.getPolicyIdsMessage(failedPolicies))) && failedPolicies.isEmpty(); } } @Override public boolean updatePolicies(List policies) { + Pair, List> results = updatePoliciesWithResults(policies); + return results.getLeft().isEmpty() && results.getRight().isEmpty(); + } + + protected Pair, List> updatePoliciesWithResults(List policies) { if (policies == null) { - return true; + return Pair.of(Collections.emptyList(), Collections.emptyList()); } // Note that PAP sends the list of all ACTIVE policies with every @@ -148,40 +190,148 @@ public abstract class LifecycleStateRunning extends LifecycleStateDefault { // we will deploy those policies that are not installed but // included in this list. - boolean success = undeployPolicies(policies); - return deployPolicies(policies) && success; + List failedUndeployPolicies = undeployPolicies(policies); + if (!failedUndeployPolicies.isEmpty()) { + logger.warn("update-policies: undeployment failures: {}", fsm.getPolicyIdsMessage(failedUndeployPolicies)); + failedUndeployPolicies.stream().forEach(fsm::undeployedPolicyAction); + } + + List failedDeployPolicies = deployPolicies(policies); + if (!failedDeployPolicies.isEmpty()) { + logger.warn("update-policies: deployment failures: {}", fsm.getPolicyIdsMessage(failedDeployPolicies)); + } + + return Pair.of(failedUndeployPolicies, failedDeployPolicies); } - protected boolean deployPolicies(List policies) { + protected List reapplyNonNativePolicies(List preActivePolicies) { + // only need to re-apply non native policies if there are new native artifact policies + + Map> activePoliciesByType = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); + List activeNativeArtifactPolicies = fsm.getNativeArtifactPolicies(activePoliciesByType); + + Map> prePoliciesByType = fsm.groupPoliciesByPolicyType(preActivePolicies); + activeNativeArtifactPolicies.removeAll(fsm.getNativeArtifactPolicies(prePoliciesByType)); + if (activeNativeArtifactPolicies.isEmpty()) { + logger.info("reapply-non-native-policies: nothing to reapply, no new native artifact policies"); + return Collections.emptyList(); + } + + // need to re-apply non native policies + + // get the non-native policies to be reapplied, this is just the intersection of + // the original active set, and the new active set (i.e policies that have not changed, + // or in other words, have not been neither deployed or undeployed. + + List preNonNativePolicies = fsm.getNonNativePolicies(prePoliciesByType); + preNonNativePolicies.retainAll(fsm.getNonNativePolicies(activePoliciesByType)); + + logger.info("re-applying non-native policies {} because new native artifact policies have been found: {}", + fsm.getPolicyIdsMessage(preNonNativePolicies), fsm.getPolicyIdsMessage(activeNativeArtifactPolicies)); + + List failedPolicies = syncPolicies(preNonNativePolicies, this::deployPolicy); + logger.info("re-applying non-native policies failures: {}", fsm.getPolicyIdsMessage(failedPolicies)); + + return failedPolicies; + } + + protected List reapplyNativeArtifactPolicies(List preActivePolicies) { + // only need to re-apply native artifact policies if there are new native controller policies + + Map> activePoliciesByType = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); + List activeNativeControllerPolicies = fsm.getNativeControllerPolicies(activePoliciesByType); + + Map> prePoliciesByType = fsm.groupPoliciesByPolicyType(preActivePolicies); + activeNativeControllerPolicies.removeAll(fsm.getNativeControllerPolicies(prePoliciesByType)); + if (activeNativeControllerPolicies.isEmpty()) { + logger.info("reapply-native-artifact-policies: nothing to reapply, no new native controller policies"); + return Collections.emptyList(); + } + + // need to re-apply native artifact policies + + // get the native artifact policies to be reapplied, this is just the intersection of + // the original active set, and the new active set (i.e policies that have not changed, + // or in other words, have not been neither deployed or undeployed. + + List preNativeArtifactPolicies = fsm.getNativeArtifactPolicies(prePoliciesByType); + preNativeArtifactPolicies.retainAll(fsm.getNativeArtifactPolicies(activePoliciesByType)); + + logger.info("reapply candidate native artifact policies {} as new native controller policies {} were found", + fsm.getPolicyIdsMessage(preNativeArtifactPolicies), + fsm.getPolicyIdsMessage(activeNativeControllerPolicies)); + + // from the intersection, only need to reapply those for which there is a new native + // controller policy + + List preNativeArtifactPoliciesToApply = new ArrayList<>(); + for (ToscaPolicy preNativeArtifactPolicy : preNativeArtifactPolicies) { + NativeArtifactPolicy nativeArtifactPolicy; + try { + nativeArtifactPolicy = + fsm.getDomainMaker().convertTo(preNativeArtifactPolicy, NativeArtifactPolicy.class); + } catch (CoderException | RuntimeException ex) { + logger.warn("reapply-native-artifact-policy {}: (unexpected) non conformant: ignoring", + preNativeArtifactPolicy.getIdentifier(), ex); + continue; + } + + String controllerName = nativeArtifactPolicy.getProperties().getController().getName(); + for (ToscaPolicy policy : activeNativeControllerPolicies) { + if (controllerName.equals(policy.getProperties().get("controllerName"))) { + preNativeArtifactPoliciesToApply.add(preNativeArtifactPolicy); + } + } + } + + logger.info("reapply set of native artifact policies {} as new native controller policies {} were found", + fsm.getPolicyIdsMessage(preNativeArtifactPoliciesToApply), + fsm.getPolicyIdsMessage(activeNativeControllerPolicies)); + + List failedPolicies = syncPolicies(preNativeArtifactPoliciesToApply, this::deployPolicy); + logger.info("re-applying native artifact policies failures: {}", fsm.getPolicyIdsMessage(failedPolicies)); + + // since we want non-native policies to be reapplied when a new native artifact policy has been + // reapplied here, remove it from the preActivePolicies, so it is detected as new. + + preActivePolicies.removeAll(preNativeArtifactPoliciesToApply); + + return failedPolicies; + } + + protected List deployPolicies(List policies) { return syncPolicies(fsm.getDeployablePoliciesAction(policies), this::deployPolicy); } - protected boolean undeployPolicies(List policies) { + protected List undeployPolicies(List policies) { return syncPolicies(fsm.getUndeployablePoliciesAction(policies), this::undeployPolicy); } - protected boolean syncPolicies(List policies, + protected List syncPolicies(List policies, BiPredicate sync) { - boolean success = true; + List failedPolicies = new ArrayList<>(); DomainMaker domain = fsm.getDomainMaker(); for (ToscaPolicy policy : policies) { ToscaConceptIdentifier policyType = policy.getTypeIdentifier(); PolicyTypeController controller = fsm.getController(policyType); if (controller == null) { logger.warn("no controller found for {}", policyType); - success = false; + failedPolicies.add(policy); continue; } if (domain.isRegistered(policy.getTypeIdentifier())) { - success = domain.isConformant(policy) && sync.test(controller, policy) && success; + if (!domain.isConformant(policy) || !sync.test(controller, policy)) { + failedPolicies.add(policy); + } } else { logger.info("no validator registered for policy type {}", policy.getTypeIdentifier()); - success = sync.test(controller, policy) && success; + if (!sync.test(controller, policy)) { + failedPolicies.add(policy); + } } } - - return success; + return failedPolicies; } private void invalidStateChange(PdpStateChange change) { diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java index cdf9f147..41d75878 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -70,7 +70,18 @@ public class PolicyTypeDroolsController implements PolicyTypeController { @Override public boolean deploy(@NonNull ToscaPolicy policy) { - return perform(policy, (PolicyController controller) -> controller.offer(policy)); + return perform(policy, controller -> { + if (!controller.getDrools().exists(policy)) { + return controller.offer(policy); + } + + logger.warn("policy {} is not deployed into {} as it already exists", + policy.getIdentifier(), controller.getName()); + + // provided that the presence of the given policy is the + // desired final state of the operation, return success + return true; + }); } /** @@ -93,7 +104,17 @@ public class PolicyTypeDroolsController implements PolicyTypeController { @Override public boolean undeploy(@NonNull ToscaPolicy policy) { - return perform(policy, (PolicyController controller) -> controller.getDrools().delete(policy)); + return perform(policy, (PolicyController controller) -> { + if (controller.getDrools().exists(policy)) { + return controller.getDrools().delete(policy); + } + logger.warn("policy {} is not undeployed from {} as it does not exist", + policy.getIdentifier(), controller.getName()); + + // provided that the no presence of the policy is the + // desired final state of the operation, return success + return true; + }); } /** @@ -134,7 +155,7 @@ public class PolicyTypeDroolsController implements PolicyTypeController { try { return operation.test(controller); } catch (RuntimeException r) { - logger.warn("invalid offer to controller: {}", controller); + logger.warn("invalid operation {} applied to controller: {}", operation, controller); return false; } } diff --git a/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java b/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java index b28f06e1..c1b0aab0 100644 --- a/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java +++ b/feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -75,7 +75,7 @@ public class RestLifecycleManager { @ApiOperation(value = "Retrieves the Lifecycle group", notes = "Lifecycle Group", response = String.class) public Response group() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getGroup()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getGroup()).build(); } /** @@ -88,8 +88,8 @@ public class RestLifecycleManager { notes = "Lifecycle Group", response = String.class) public Response updateGroup( @ApiParam(value = "Group", required = true) @PathParam("group") String group) { - LifecycleFeature.fsm.setGroup(group); - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getGroup()).build(); + LifecycleFeature.getFsm().setGroup(group); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getGroup()).build(); } /** @@ -101,7 +101,7 @@ public class RestLifecycleManager { @ApiOperation(value = "Retrieves the Lifecycle subgroup", notes = "Lifecycle Subgroup", response = String.class) public Response subgroup() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getSubgroup()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getSubgroup()).build(); } /** @@ -114,8 +114,8 @@ public class RestLifecycleManager { notes = "Lifecycle Subgroup", response = String.class) public Response subgroup( @ApiParam(value = "Subgroup", required = true) @PathParam("subgroup") String subgroup) { - LifecycleFeature.fsm.setSubgroup(subgroup); - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getSubgroup()).build(); + LifecycleFeature.getFsm().setSubgroup(subgroup); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getSubgroup()).build(); } /** @@ -127,7 +127,7 @@ public class RestLifecycleManager { @ApiOperation(value = "Retrieves the Lifecycle properties", notes = "Lifecycle Properties", response = Properties.class) public Response properties() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getProperties()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getProperties()).build(); } /** @@ -138,7 +138,7 @@ public class RestLifecycleManager { @Path("state") @ApiOperation(value = "Retrieves the Lifecycle state", notes = "Lifecycle State", response = PdpState.class) public Response state() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.state()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().state()).build(); } /** @@ -152,12 +152,12 @@ public class RestLifecycleManager { @ApiParam(value = "state", required = true) @PathParam("state") String state) { PdpStateChange change = new PdpStateChange(); - change.setPdpGroup(LifecycleFeature.fsm.getGroup()); - change.setPdpSubgroup(LifecycleFeature.fsm.getSubgroup()); + change.setPdpGroup(LifecycleFeature.getFsm().getGroup()); + change.setPdpSubgroup(LifecycleFeature.getFsm().getSubgroup()); change.setState(PdpState.valueOf(state)); - change.setName(LifecycleFeature.fsm.getName()); + change.setName(LifecycleFeature.getFsm().getName()); - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.stateChange(change)).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().stateChange(change)).build(); } /** @@ -169,7 +169,7 @@ public class RestLifecycleManager { @ApiOperation(value = "Retrieves the Lifecycle topic source", notes = "Lifecycle Topic Source", response = TopicSource.class) public Response source() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getSource()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getSource()).build(); } /** @@ -181,7 +181,7 @@ public class RestLifecycleManager { @ApiOperation(value = "Retrieves the Lifecycle topic sink", notes = "Lifecycle Topic Sink", response = TopicSink.class) public Response sink() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getClient()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getClient()).build(); } /** @@ -193,7 +193,7 @@ public class RestLifecycleManager { @ApiOperation(value = "Retrieves the Lifecycle Status Timer Interval in seconds", notes = "Lifecycle Status Timer Interval in seconds", response = Long.class) public Response updateStatusTimer() { - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getStatusTimerSeconds()).build(); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getStatusTimerSeconds()).build(); } /** @@ -206,8 +206,8 @@ public class RestLifecycleManager { notes = "Lifecycle Status Timer Interval in seconds", response = Long.class) public Response statusTimer( @ApiParam(value = "timeout", required = true) @PathParam("timeout") Long timeout) { - LifecycleFeature.fsm.setStatusTimerSeconds(timeout); - return Response.status(Response.Status.OK).entity(LifecycleFeature.fsm.getStatusTimerSeconds()).build(); + LifecycleFeature.getFsm().setStatusTimerSeconds(timeout); + return Response.status(Response.Status.OK).entity(LifecycleFeature.getFsm().getStatusTimerSeconds()).build(); } /** @@ -220,7 +220,7 @@ public class RestLifecycleManager { notes = "Lifecycle Policy Types", responseContainer = "List") public Response policyTypes() { return Response.status(Response.Status.OK) - .entity(LifecycleFeature.fsm.getPolicyTypesMap().keySet()) + .entity(LifecycleFeature.getFsm().getPolicyTypesMap().keySet()) .build(); } @@ -238,7 +238,7 @@ public class RestLifecycleManager { @ApiParam(value = "Policy Type Version", required = true) @PathParam("policyTypeVersion") String policyTypeVersion) { PolicyTypeController typeController = - LifecycleFeature.fsm.getPolicyTypesMap() + LifecycleFeature.getFsm().getPolicyTypesMap() .get(new ToscaConceptIdentifier(policyType, policyTypeVersion)); if (typeController == null) { return Response.status(Response.Status.NOT_FOUND).build(); @@ -258,7 +258,7 @@ public class RestLifecycleManager { @ApiOperation(value = "List of policies", responseContainer = "List") public Response policies() { return Response.status(Response.Status.OK) - .entity(LifecycleFeature.fsm.getPoliciesMap().keySet()) + .entity(LifecycleFeature.getFsm().getPoliciesMap().keySet()) .build(); } @@ -284,10 +284,10 @@ public class RestLifecycleManager { } List policies = - LifecycleFeature.fsm.getPoliciesMap().values().stream().collect(Collectors.toList()); + LifecycleFeature.getFsm().getPoliciesMap().values().stream().collect(Collectors.toList()); policies.add(toscaPolicy); - boolean updateResult = LifecycleFeature.fsm.update(getPolicyUpdate(policies)); + boolean updateResult = LifecycleFeature.getFsm().update(getPolicyUpdate(policies)); return Response.status((updateResult ? Response.Status.OK : Response.Status.NOT_ACCEPTABLE)) .entity(updateResult) .build(); @@ -307,7 +307,7 @@ public class RestLifecycleManager { ToscaPolicy policy; try { policy = - LifecycleFeature.fsm.getPoliciesMap().get(new ToscaConceptIdentifier(policyName, policyVersion)); + LifecycleFeature.getFsm().getPoliciesMap().get(new ToscaConceptIdentifier(policyName, policyVersion)); } catch (RuntimeException r) { logger.debug("policy {}:{} has not been found", policyName, policyVersion, r); return Response.status(Response.Status.NOT_FOUND).build(); @@ -334,7 +334,7 @@ public class RestLifecycleManager { ToscaPolicy policy; try { policy = - LifecycleFeature.fsm.getPoliciesMap().get(new ToscaConceptIdentifier(policyName, policyVersion)); + LifecycleFeature.getFsm().getPoliciesMap().get(new ToscaConceptIdentifier(policyName, policyVersion)); } catch (RuntimeException r) { logger.debug("policy {}:{} has not been found", policyName, policyVersion, r); return Response.status(Response.Status.NOT_FOUND).build(); @@ -345,10 +345,10 @@ public class RestLifecycleManager { } List policies = - LifecycleFeature.fsm.getPoliciesMap().values().stream().collect(Collectors.toList()); + LifecycleFeature.getFsm().getPoliciesMap().values().stream().collect(Collectors.toList()); policies.removeIf(otherPolicy -> policy.getIdentifier().equals(otherPolicy.getIdentifier())); return Response.status(Response.Status.OK) - .entity(LifecycleFeature.fsm.update(getPolicyUpdate(policies))) + .entity(LifecycleFeature.getFsm().update(getPolicyUpdate(policies))) .build(); } @@ -399,7 +399,7 @@ public class RestLifecycleManager { } try { - LifecycleFeature.fsm.getDomainMaker().conformance(toscaPolicy); + LifecycleFeature.getFsm().getDomainMaker().conformance(toscaPolicy); } catch (ValidationFailedException v) { logger.trace("policy {} validation errors: {}", toscaPolicy, v.getMessage(), v); return Response.status(Response.Status.NOT_ACCEPTABLE).entity(v.getFailures()).build(); @@ -433,14 +433,14 @@ public class RestLifecycleManager { } private PolicyTypeController getPolicyTypeController(ToscaPolicy policy) { - return LifecycleFeature.fsm.getPolicyTypesMap().get(policy.getTypeIdentifier()); + return LifecycleFeature.getFsm().getPolicyTypesMap().get(policy.getTypeIdentifier()); } private PdpUpdate getPolicyUpdate(List policies) { PdpUpdate update = new PdpUpdate(); - update.setName(LifecycleFeature.fsm.getName()); - update.setPdpGroup(LifecycleFeature.fsm.getGroup()); - update.setPdpSubgroup(LifecycleFeature.fsm.getSubgroup()); + update.setName(LifecycleFeature.getFsm().getName()); + update.setPdpGroup(LifecycleFeature.getFsm().getGroup()); + update.setPdpSubgroup(LifecycleFeature.getFsm().getSubgroup()); update.setPolicies(policies); return update; } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java index 9c30b3f9..4c1830b8 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019, 2021 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. @@ -20,7 +20,10 @@ package org.onap.policy.drools.lifecycle; +import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.nio.file.Paths; import java.util.List; import java.util.Properties; @@ -64,8 +67,8 @@ public class ControllerSupport { PolicyController controller = getController(); controller.getDrools().delete(ToscaPolicy.class); return controller; - } catch (IllegalArgumentException e) { - ; + } catch (IllegalArgumentException ignored) { // NOSONAR + ; // checkstyle } ReleaseId coordinates = installArtifact(); @@ -80,15 +83,22 @@ public class ControllerSupport { return PolicyControllerConstants.getFactory().build(name, controllerProps); } + /** + * Install a maven artifact. + */ + public static ReleaseId installArtifact(File kmodule, File pom, + String drlKjarPath, List drls) throws IOException { + return KieUtils.installArtifact(kmodule, pom, drlKjarPath, drls); + } + /** * install artifact. */ public ReleaseId installArtifact() throws IOException { - return - KieUtils.installArtifact(Paths.get(JUNIT_KMODULE_PATH).toFile(), + return ControllerSupport.installArtifact(Paths.get(JUNIT_KMODULE_PATH).toFile(), Paths.get(JUNIT_KMODULE_POM_PATH).toFile(), - JUNIT_KJAR_DRL_PATH, - Paths.get(JUNIT_KMODULE_DRL_PATH).toFile()); + JUNIT_KJAR_DRL_PATH, + List.of(Paths.get(JUNIT_KMODULE_DRL_PATH).toFile())); } /** @@ -120,4 +130,27 @@ public class ControllerSupport { .getDrools() .facts(SESSION_NAME, clazz); } + + /** + * Change final marker in static field. + */ + public static Field unsetFinalStaticAccess(Class clazz, String fieldName) + throws NoSuchFieldException, IllegalAccessException { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + return field; + } + + /* + * Reassign static field. + */ + public static void setStaticField(Class clazz, String fieldName, E newValue) + throws NoSuchFieldException, IllegalAccessException { + unsetFinalStaticAccess(clazz, fieldName).set(null, newValue); + } } diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java index b5c4f1b5..0e3680dc 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java @@ -27,6 +27,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.concurrent.ScheduledExecutorService; import org.junit.Before; import org.junit.Test; @@ -139,6 +140,26 @@ public class LifecycleFsmTest { @Test public void testGetUndeployableActions() { + deployAllPolicies(); + List expectedUndeployOrder = + List.of(opPolicy, op2Policy, unvalPolicy, valPolicy, artifactPolicy, + artifact2Policy, controller2Policy, controllerPolicy); + + assertEquals(expectedUndeployOrder, fsm.getUndeployablePoliciesAction(Collections.EMPTY_LIST)); + assertEquals(expectedUndeployOrder, fsm.getUndeployablePoliciesAction(Collections.EMPTY_LIST)); + assertEquals(expectedUndeployOrder, fsm.getUndeployablePoliciesAction(Collections.EMPTY_LIST)); + } + + @Test + public void testGetNativeArtifactPolicies() { + deployAllPolicies(); + + Map> deployedPolicies = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); + assertEquals(2, fsm.getNativeArtifactPolicies(deployedPolicies).size()); + assertEquals(List.of(artifactPolicy, artifact2Policy), fsm.getNativeArtifactPolicies(deployedPolicies)); + } + + protected void deployAllPolicies() { fsm.deployedPolicyAction(controllerPolicy); fsm.deployedPolicyAction(controller2Policy); fsm.deployedPolicyAction(artifactPolicy); @@ -147,14 +168,6 @@ public class LifecycleFsmTest { fsm.deployedPolicyAction(valPolicy); fsm.deployedPolicyAction(unvalPolicy); fsm.deployedPolicyAction(op2Policy); - - List expectedUndeployOrder = - List.of(opPolicy, op2Policy, unvalPolicy, valPolicy, artifactPolicy, - artifact2Policy, controller2Policy, controllerPolicy); - - assertEquals(expectedUndeployOrder, fsm.getUndeployablePoliciesAction(Collections.EMPTY_LIST)); - assertEquals(expectedUndeployOrder, fsm.getUndeployablePoliciesAction(Collections.EMPTY_LIST)); - assertEquals(expectedUndeployOrder, fsm.getUndeployablePoliciesAction(Collections.EMPTY_LIST)); } protected ToscaPolicy getPolicyFromFile(String filePath, String policyName) throws CoderException, IOException { diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java new file mode 100644 index 00000000..01500576 --- /dev/null +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java @@ -0,0 +1,585 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.drools.lifecycle; + +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import com.google.common.base.Strings; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ScheduledExecutorService; +import java.util.stream.Collectors; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; +import org.onap.policy.common.endpoints.event.comm.bus.NoopTopicFactories; +import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.common.utils.time.PseudoScheduledExecutorService; +import org.onap.policy.common.utils.time.TestTimeMulti; +import org.onap.policy.drools.domain.models.artifact.NativeArtifactPolicy; +import org.onap.policy.drools.domain.models.controller.ControllerPolicy; +import org.onap.policy.drools.persistence.SystemPersistenceConstants; +import org.onap.policy.drools.system.PolicyControllerConstants; +import org.onap.policy.drools.utils.logging.LoggerUtil; +import org.onap.policy.models.pdp.concepts.PdpStateChange; +import org.onap.policy.models.pdp.concepts.PdpUpdate; +import org.onap.policy.models.pdp.enums.PdpState; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +/** + * Lifecycle FSM Updates Test. + */ +public class LifecycleFsmUpdateTest { + + private static final String EXAMPLE_NATIVE_CONTROLLER_POLICY_NAME = "example.controller"; + private static final String EXAMPLE_NATIVE_CONTROLLER_POLICY_JSON = + "src/test/resources/tosca-policy-native-controller-example.json"; + + private static final String EXAMPLE_NATIVE_ARTIFACT_POLICY_NAME = "example.artifact"; + private static final String EXAMPLE_NATIVE_ARTIFACT_POLICY_JSON = + "src/test/resources/tosca-policy-native-artifact-example.json"; + + private static final String EXAMPLE_OTHER_UNVAL_POLICY_NAME = "other-unvalidated"; + private static final String EXAMPLE_OTHER_UNVAL_POLICY_JSON = + "src/test/resources/tosca-policy-other-unvalidated.json"; + + private static final String EXAMPLE_OTHER_VAL_POLICY_NAME = "other-validated"; + private static final String EXAMPLE_OTHER_VAL_POLICY_JSON = + "src/test/resources/tosca-policy-other-validated.json"; + + private static final String FOO_NATIVE_CONTROLLER_POLICY_NAME = "foo.controller"; + private static final String FOO_NATIVE_CONTROLLER_POLICY_JSON = + "src/test/resources/tosca-policy-native-controller-foo.json"; + + private static final String FOO_NATIVE_ARTIFACT_POLICY_NAME = "foo.artifact"; + private static final String FOO_NATIVE_ARTIFACT_POLICY_JSON = + "src/test/resources/tosca-policy-native-artifact-foo.json"; + + private static final String VCPE_OP_POLICY_NAME = "operational.restart"; + private static final String VCPE_OPERATIONAL_DROOLS_POLICY_JSON = + "policies/vCPE.policy.operational.input.tosca.json"; + + private static final String VFW_OP_POLICY_NAME = "operational.modifyconfig"; + private static final String VFW_OPERATIONAL_DROOLS_POLICY_JSON = + "policies/vFirewall.policy.operational.input.tosca.json"; + + private static final StandardCoder coder = new StandardCoder(); + + protected static LifecycleFsm savedFsm; + protected LifecycleFsm fsm; + + private ToscaPolicy opPolicy; + private ToscaPolicy op2Policy; + private ToscaPolicy valPolicy; + private ToscaPolicy unvalPolicy; + private ToscaPolicy controllerPolicy; + private ToscaPolicy controller2Policy; + private ToscaPolicy artifactPolicy; + private ToscaPolicy artifact2Policy; + + /** + * Set up. + */ + @BeforeClass + public static void setUp() throws IOException { + LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "INFO"); + LoggerUtil.setLevel("org.onap.policy.common.endpoints", "WARN"); + LoggerUtil.setLevel("org.onap.policy.drools", "INFO"); + + SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); + + ControllerSupport.installArtifact( + Paths.get(ControllerSupport.JUNIT_KMODULE_PATH).toFile(), + Paths.get(ControllerSupport.JUNIT_KMODULE_POM_PATH).toFile(), + ControllerSupport.JUNIT_KJAR_DRL_PATH, + List.of(Paths.get(ControllerSupport.JUNIT_KMODULE_DRL_PATH).toFile())); + + ControllerSupport.installArtifact( + Paths.get("src/test/resources/echo.kmodule").toFile(), + Paths.get("src/test/resources/echo.pom").toFile(), + "src/main/resources/kbecho/org/onap/policy/drools/test/", + List.of(Paths.get("src/test/resources/echo.drl").toFile())); + + Properties noopTopicProperties = new Properties(); + noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SOURCE_TOPICS, "DCAE_TOPIC"); + noopTopicProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "APPC-CL"); + TopicEndpointManager.getManager().addTopics(noopTopicProperties); + + savedFsm = LifecycleFeature.fsm; + } + + /** + * Tear Down. + */ + @AfterClass + public static void tearDown() throws NoSuchFieldException, IllegalAccessException { + PolicyControllerConstants.getFactory().destroy(); + + NoopTopicFactories.getSourceFactory().destroy(); + NoopTopicFactories.getSinkFactory().destroy(); + try { + Files.deleteIfExists(Paths.get(SystemPersistenceConstants.getManager().getConfigurationPath().toString(), + "lifecycle-controller.properties.bak")); + Files.deleteIfExists(Paths.get(SystemPersistenceConstants.getManager().getConfigurationPath().toString(), + "foo-controller.properties.bak")); + } catch (IOException ignored) { // NOSONAR + ; // checkstyle + } + + ControllerSupport.setStaticField(LifecycleFeature.class, "fsm", savedFsm); + } + + /** + * Test initialization. + */ + @Before + public void init() throws CoderException, IOException, NoSuchFieldException, IllegalAccessException { + fsm = new LifecycleFsm() { + @Override + protected ScheduledExecutorService makeExecutor() { // NOSONAR + return new PseudoScheduledExecutorService(new TestTimeMulti()); + } + }; + ControllerSupport.setStaticField(LifecycleFeature.class, "fsm", fsm); + + fsm.setStatusTimerSeconds(15); + assertTrue(fsm.start()); + + PdpStateChange change = new PdpStateChange(); + change.setPdpGroup("A"); + change.setPdpSubgroup("a"); + change.setState(PdpState.ACTIVE); + change.setName(fsm.getName()); + + fsm.setSubGroupAction("a"); + fsm.source.offer(new StandardCoder().encode(change)); + + assertEquals(0, fsm.getPoliciesMap().size()); + assertEquals("ACTIVE", fsm.state().toString()); + assertEquals(2, fsm.getPolicyTypesMap().size()); + + opPolicy = getExamplesPolicy(VFW_OPERATIONAL_DROOLS_POLICY_JSON, VFW_OP_POLICY_NAME); + op2Policy = getExamplesPolicy(VCPE_OPERATIONAL_DROOLS_POLICY_JSON, VCPE_OP_POLICY_NAME); + controllerPolicy = + getPolicyFromFile(EXAMPLE_NATIVE_CONTROLLER_POLICY_JSON, EXAMPLE_NATIVE_CONTROLLER_POLICY_NAME); + controller2Policy = getPolicyFromFile(FOO_NATIVE_CONTROLLER_POLICY_JSON, FOO_NATIVE_CONTROLLER_POLICY_NAME); + artifactPolicy = + getPolicyFromFile(EXAMPLE_NATIVE_ARTIFACT_POLICY_JSON, EXAMPLE_NATIVE_ARTIFACT_POLICY_NAME); + artifact2Policy = getExamplesPolicy(FOO_NATIVE_ARTIFACT_POLICY_JSON, FOO_NATIVE_ARTIFACT_POLICY_NAME); + valPolicy = + getPolicyFromFile(EXAMPLE_OTHER_VAL_POLICY_JSON, EXAMPLE_OTHER_VAL_POLICY_NAME); + unvalPolicy = + getPolicyFromFile(EXAMPLE_OTHER_UNVAL_POLICY_JSON, EXAMPLE_OTHER_UNVAL_POLICY_NAME); + } + + @Test + public void testUpdate() throws CoderException { + assertEquals(0, fsm.getPoliciesMap().size()); + assertEquals("ACTIVE", fsm.state().toString()); + assertEquals(0, PolicyControllerConstants.getFactory().inventory().size()); + + // native controller policy - deploy + // Delta: +controllerPolicy + assertTrue(fsm.update(getPdpUpdate(List.of(controllerPolicy)))); + verifyActivePolicies(List.of(controllerPolicy)); + + // no policies - undeploy + // Delta: [] + assertTrue(fsm.update(getPdpUpdate(Collections.emptyList()))); + verifyActivePolicies(Collections.emptyList()); + + // native controller + artifact policy (out of order) - deploy + // Delta: +artifactPolicy, +controllerPolicy + assertTrue(fsm.update(getPdpUpdate(List.of(artifactPolicy, controllerPolicy)))); + verifyActivePolicies(List.of(artifactPolicy, controllerPolicy)); + + // attempt to deploy opPolicy but invalid controller + // Delta: +opPolicy + assertFalse(fsm.update(getPdpUpdate(List.of(artifactPolicy, opPolicy, controllerPolicy)))); + assertEquals(1, PolicyControllerConstants.getFactory().inventory().size()); + assertFalse(fsm.getActivePolicies().contains(opPolicy)); + verifyExists(false, "lifecycle", List.of(opPolicy)); + verifyActivePolicies(List.of(artifactPolicy, controllerPolicy)); + + // Delta: +opPolicy + opPolicy.getProperties().remove("controllerName"); + assertTrue(fsm.update(getPdpUpdate(List.of(artifactPolicy, opPolicy, controllerPolicy)))); + verifyExists(true, "lifecycle", List.of(opPolicy)); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy)); + + // Delta: -opPolicy + assertTrue(fsm.update(getPdpUpdate(List.of(artifactPolicy, controllerPolicy)))); + assertFalse(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().exists(opPolicy)); + verifyActivePolicies(List.of(controllerPolicy, artifactPolicy)); + + // Delta: -artifactPolicy + assertTrue(fsm.update(getPdpUpdate(List.of(controllerPolicy)))); + assertFalse(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained()); + verifyActivePolicies(List.of(controllerPolicy)); + + // Delta: -controllerPolicy + assertTrue(fsm.update(getPdpUpdate(Collections.emptyList()))); + assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle")); + assertEquals(0, PolicyControllerConstants.getFactory().inventory().size()); + verifyActivePolicies(Collections.emptyList()); + + // Delta: +controllerPolicy, +artifactPolicy, and +opPolicy + assertTrue(fsm.update(getPdpUpdate(List.of(opPolicy, artifactPolicy, controllerPolicy)))); + verifyExists(true, "lifecycle", List.of(opPolicy)); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy)); + + // Delta: -artifactPolicy + assertTrue(fsm.update(getPdpUpdate(List.of(opPolicy, controllerPolicy)))); + assertEquals(1, PolicyControllerConstants.getFactory().inventory().size()); + assertFalse(PolicyControllerConstants.getFactory().get("lifecycle").getDrools().isBrained()); + + // Delta: +artifactPolicy + // from deltas, all delta updates should be successfully applied + assertTrue(fsm.update(getPdpUpdate(List.of(opPolicy, controllerPolicy, artifactPolicy)))); + verifyExists(true, "lifecycle", List.of(opPolicy)); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy)); + + // Delta: -controllerPolicy + // from deltas, all delta updates should be successfully applied + assertTrue(fsm.update(getPdpUpdate(List.of(opPolicy, artifactPolicy)))); + assertEquals(0, PolicyControllerConstants.getFactory().inventory().size()); + + // Delta: +controllerPolicy + // from deltas, all delta updates should be successfully applied + assertTrue(fsm.update(getPdpUpdate(List.of(opPolicy, controllerPolicy, artifactPolicy)))); + verifyExists(true, "lifecycle", List.of(opPolicy)); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy)); + + // Delta: +op2Policy, +controller2Policy + // from deltas, all delta updates should be successfully applied + op2Policy.getProperties().put("controllerName", "lifecycle"); + assertTrue(fsm.update(getPdpUpdate( + List.of(opPolicy, controllerPolicy, artifactPolicy, op2Policy, controller2Policy)))); + verifyExists(true, "lifecycle", List.of(opPolicy, op2Policy)); + assertFalse(PolicyControllerConstants.getFactory().get("foo").getDrools().isBrained()); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy, op2Policy, controller2Policy)); + + // Delta: +artifact2policy, +valPolicy, +unvalPolicy + // from deltas, all delta updates should be successfully applied + assertTrue(fsm.update(getPdpUpdate( + List.of(opPolicy, controllerPolicy, artifactPolicy, + op2Policy, controller2Policy, valPolicy, unvalPolicy, artifact2Policy)))); + verifyExists(true, "lifecycle", List.of(opPolicy, op2Policy, valPolicy, unvalPolicy)); + verifyExists(true, "foo", List.of(valPolicy, unvalPolicy)); + verifyExists(false, "foo", List.of(opPolicy, op2Policy)); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy, op2Policy, + controller2Policy, valPolicy, unvalPolicy, artifact2Policy)); + + // Delta: -artifact2Policy, +valPolicy + // from deltas, all delta updates should be successfully applied, and unvalPolicy disabled + assertTrue(fsm.update(getPdpUpdate( + List.of(opPolicy, controllerPolicy, artifactPolicy, + op2Policy, controller2Policy, valPolicy)))); + verifyExists(true, "lifecycle", List.of(opPolicy, op2Policy, valPolicy)); + verifyExists(false, "lifecycle", List.of(unvalPolicy)); + assertFalse(PolicyControllerConstants.getFactory().get("foo").getDrools().isBrained()); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy, op2Policy, + controller2Policy, valPolicy)); + + // Delta: +artifact2Policy + // from deltas, all delta updates should be successfully applied, opPolicy, op2Policy and unvalPolicy + // should be reapplied. + assertTrue(fsm.update(getPdpUpdate( + List.of(opPolicy, controllerPolicy, artifactPolicy, + op2Policy, controller2Policy, valPolicy, artifact2Policy)))); + verifyExists(true, "lifecycle", List.of(opPolicy, op2Policy, valPolicy)); + verifyExists(false, "lifecycle", List.of(unvalPolicy)); + verifyExists(true, "foo", List.of(valPolicy)); + verifyExists(false, "foo", List.of(opPolicy, op2Policy, unvalPolicy)); + verifyActivePolicies(List.of(opPolicy, artifactPolicy, controllerPolicy, op2Policy, + controller2Policy, valPolicy, artifact2Policy)); + + // Delta: -controllerPolicy, +artifactPolicy, +unvalPolicy + // from deltas, all delta updates should be successful + assertTrue(fsm.update(getPdpUpdate( + List.of(opPolicy, op2Policy, controller2Policy, valPolicy, artifact2Policy, unvalPolicy)))); + assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle")); + verifyExists(true, "foo", List.of(valPolicy, unvalPolicy)); + verifyExists(false, "foo", List.of(opPolicy, op2Policy)); + // since -controllerPolicy delta => the existing artifact2Policy, opPolicy, op2Policy become disabled as no + // policy type is readily available to host them until there is a host. + verifyActivePoliciesWithDisables( + List.of(opPolicy, op2Policy, controller2Policy, valPolicy, artifact2Policy, unvalPolicy), + List.of(opPolicy.getIdentifier(), op2Policy.getIdentifier())); + + // Delta: -opPolicy, -op2Policy, -controller2Policy, -valPolicy, -artifact2Policy, -unvalPolicy + // from deltas, -opPolicy and -op2Policy undeploys will fail since there is not controller with that + // policy type supported + assertFalse(fsm.update(getPdpUpdate(Collections.emptyList()))); + assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("lifecycle")); + assertThatIllegalArgumentException().isThrownBy(() -> PolicyControllerConstants.getFactory().get("foo")); + assertEquals(0, PolicyControllerConstants.getFactory().inventory().size()); + verifyActivePolicies(Collections.emptyList()); + + fsm.shutdown(); + } + + protected PdpUpdate getPdpUpdate(List policies) { + PdpUpdate update = new PdpUpdate(); + update.setName(NetworkUtil.getHostname()); + update.setPdpGroup("A"); + update.setPdpSubgroup("a"); + update.setPolicies(policies); + return update; + } + + protected void verifyExists(boolean exists, String controller, List policies) { + assertTrue(PolicyControllerConstants.getFactory().get(controller).getDrools().isBrained()); + for (ToscaPolicy policy : policies) { + assertEquals("ID: " + controller + ":" + policy.getIdentifier(), + exists, PolicyControllerConstants.getFactory().get(controller).getDrools().exists(policy)); + } + } + + protected void verifyActivePolicies(List testPolicies) throws CoderException { + verifyActivePoliciesWithDisables(testPolicies, Collections.emptyList()); + } + + protected void verifyActivePoliciesWithDisables(List testPolicies, + List nativeDisables) throws CoderException { + // verify that each policy is tracked in the active lists + + for (ToscaPolicy policy : testPolicies) { + assertTrue(policy.getIdentifier().toString(), fsm.getActivePolicies().contains(policy)); + if (!nativeDisables.contains(policy.getIdentifier())) { + assertTrue(policy.getIdentifier().toString(), + fsm.getPolicyTypesMap().containsKey(policy.getTypeIdentifier())); + } + } + assertEquals(testPolicies.size(), fsm.getActivePolicies().size()); + + Map> testPoliciesMap = fsm.groupPoliciesByPolicyType(testPolicies); + Map> activePolicyMap = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); + assertEquals(new HashSet<>(activePolicyMap.keySet()), new HashSet<>(testPoliciesMap.keySet())); + for (String key: fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()).keySet()) { + assertEquals(new HashSet<>(activePolicyMap.get(key)), new HashSet<>(testPoliciesMap.get(key))); + } + + // verify that a controller exists for each controller policy + assertEquals(fsm.getNativeControllerPolicies(testPoliciesMap).size(), + PolicyControllerConstants.getFactory().inventory().size()); + + // verify that a brained controller with same application coordinates exist for + // each native artifact policy + + verifyNativeArtifactPolicies(fsm.getNativeArtifactPolicies(testPoliciesMap)); + + // verify non-native policies are attached to the right set of brained controllers + + for (ToscaPolicy policy : fsm.getNonNativePolicies(testPoliciesMap)) { + verifyNonNativePolicy(policy, nativeDisables); + } + } + + protected void verifyNativeArtifactPolicies(List policies) throws CoderException { + // check that a brained controller exists for each native artifact policy + for (ToscaPolicy policy : policies) { + NativeArtifactPolicy artifactPolicy = + fsm.getDomainMaker().convertTo(policy, NativeArtifactPolicy.class); + String controllerName = artifactPolicy.getProperties().getController().getName(); + assertTrue(PolicyControllerConstants.getFactory().get(controllerName).getDrools().isBrained()); + assertEquals(artifactPolicy.getProperties().getRulesArtifact().getGroupId(), + PolicyControllerConstants.getFactory().get(controllerName).getDrools().getGroupId()); + assertEquals(artifactPolicy.getProperties().getRulesArtifact().getArtifactId(), + PolicyControllerConstants.getFactory().get(controllerName).getDrools().getArtifactId()); + assertEquals(artifactPolicy.getProperties().getRulesArtifact().getVersion(), + PolicyControllerConstants.getFactory().get(controllerName).getDrools().getVersion()); + } + } + + protected void verifyNonNativePolicy(ToscaPolicy testPolicy, + List nativeDisables) throws CoderException { + List nativeArtifactPolicies = + fsm.getNativeArtifactPolicies(fsm.groupPoliciesByPolicyType(fsm.getActivePolicies())); + + List nativeControllerPolicies = + fsm.getNativeControllerPolicies(fsm.groupPoliciesByPolicyType(fsm.getActivePolicies())); + + String controllerName = (String) testPolicy.getProperties().get("controllerName"); + + if (Strings.isNullOrEmpty(controllerName)) { + // this non-native policy applies to all controllers that are brained + + // verify the policy is present as a fact in all brained controllers + // and there is a controller policy for each controllerName + + for (ToscaPolicy nativePolicy : nativeArtifactPolicies) { + NativeArtifactPolicy artifactPolicy = + fsm.getDomainMaker().convertTo(nativePolicy, NativeArtifactPolicy.class); + String artifactControllerName = artifactPolicy.getProperties().getController().getName(); + + // brained controller check + assertTrue(artifactControllerName + ":" + testPolicy.getIdentifier(), + PolicyControllerConstants.getFactory().get(artifactControllerName).getDrools().isBrained()); + + // non native tosca policy as a fact in drools + if (PolicyControllerConstants.getFactory() + .get(artifactControllerName).getPolicyTypes().contains(testPolicy.getTypeIdentifier())) { + assertTrue(artifactControllerName + ":" + testPolicy.getIdentifier(), + PolicyControllerConstants.getFactory() + .get(artifactControllerName).getDrools().exists(testPolicy)); + } else { + assertFalse(artifactControllerName + ":" + testPolicy.getIdentifier(), + PolicyControllerConstants.getFactory() + .get(artifactControllerName).getDrools().exists(testPolicy)); + } + + // there should always be a controller policy for each artifact policy + assertEquals(1, + getNativeControllerPolicies(nativeControllerPolicies, artifactControllerName).size()); + } + + return; + } + + // this non-native policy applies only to the specified native controller + // which could be brained or brainless + + // there should always be a controller policy + + if (nativeDisables.contains(testPolicy.getIdentifier())) { + // skip evaluating next section + return; + } + + assertEquals(1, getNativeControllerPolicies(nativeControllerPolicies, controllerName).size()); + + // verify the policy is present as a fact if there is matching artifact policy + + List candidateNativeArtifactPolicies = + getNativeArtifactPolicies(nativeArtifactPolicies, controllerName); + + if (candidateNativeArtifactPolicies.size() == 1) { + assertTrue(controllerName + ":" + testPolicy.getIdentifier(), + PolicyControllerConstants.getFactory().get(controllerName).getDrools().isBrained()); + assertTrue(controllerName + ":" + testPolicy.getIdentifier(), + PolicyControllerConstants.getFactory().get(controllerName).getDrools().exists(testPolicy)); + + // verify that the other brained controllers don't have this non-native policy + + for (NativeArtifactPolicy nativePolicy : + getNativeArtifactPoliciesBut(nativeArtifactPolicies, controllerName)) { + assertTrue(PolicyControllerConstants.getFactory() + .get(nativePolicy.getProperties().getController().getName()) + .getDrools().isBrained()); + assertFalse(controllerName + ":" + testPolicy.getIdentifier(), + PolicyControllerConstants.getFactory() + .get(nativePolicy.getProperties().getController().getName()) + .getDrools().exists(testPolicy)); + } + + return; + } + + // at this point the only valid possibility is that there is no native artifact policies + + assertTrue("There is more than 1 native artifact policy for " + controllerName, + candidateNativeArtifactPolicies.isEmpty()); + } + + protected List getNativeArtifactPoliciesBut(List nativePolicies, + String controllerName) { + return + nativePolicies.stream() + .map(nativePolicy -> { + try { + return fsm.getDomainMaker().convertTo(nativePolicy, NativeArtifactPolicy.class); + } catch (CoderException ex) { + throw new RuntimeException(nativePolicy.getIdentifier().toString(), ex); + } + }) + .filter(nativeArtifactPolicy -> !controllerName.equals(nativeArtifactPolicy + .getProperties() + .getController() + .getName())) + .collect(Collectors.toList()); + } + + protected List getNativeArtifactPolicies(List nativePolicies, + String controllerName) { + return + nativePolicies.stream() + .map(nativePolicy -> { + try { + return fsm.getDomainMaker().convertTo(nativePolicy, NativeArtifactPolicy.class); + } catch (CoderException ex) { + throw new RuntimeException(nativePolicy.getIdentifier().toString(), ex); + } + }) + .filter(nativeArtifactPolicy -> controllerName.equals(nativeArtifactPolicy + .getProperties() + .getController() + .getName())) + .collect(Collectors.toList()); + } + + protected List getNativeControllerPolicies(List nativePolicies, + String controllerName) { + return + nativePolicies.stream() + .map(controllerPolicy -> { + try { + return fsm.getDomainMaker().convertTo(controllerPolicy, ControllerPolicy.class); + } catch (CoderException ex) { + throw new RuntimeException(controllerPolicy.getIdentifier().toString(), ex); + } + }) + .filter(controllerPolicy -> controllerName.equals(controllerPolicy + .getProperties() + .getControllerName())) + .collect(Collectors.toList()); + } + + protected ToscaPolicy getPolicyFromFile(String filePath, String policyName) throws CoderException, IOException { + String policyJson = Files.readString(Paths.get(filePath)); + ToscaServiceTemplate serviceTemplate = coder.decode(policyJson, ToscaServiceTemplate.class); + return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName); + } + + protected ToscaPolicy getExamplesPolicy(String resourcePath, String policyName) throws CoderException { + String policyJson = ResourceUtils.getResourceAsString(resourcePath); + ToscaServiceTemplate serviceTemplate = new StandardCoder().decode(policyJson, ToscaServiceTemplate.class); + return serviceTemplate.getToscaTopologyTemplate().getPolicies().get(0).get(policyName); + } + +} \ No newline at end of file diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java index 9547aa47..afa89d68 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java @@ -2,7 +2,7 @@ * ============LICENSE_START======================================================= * ONAP * ================================================================================ - * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved. * Modifications Copyright (C) 2021 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -140,7 +140,7 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { } @Test - public void testUpdate() throws IOException, CoderException { + public void testUpdate() throws CoderException { controllerSupport.getController().getDrools().delete(ToscaPolicy.class); assertEquals(0, controllerSupport.getController().getDrools().factCount("junits")); @@ -224,6 +224,18 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { assertBasicPassive(); assertEquals(0, controllerSupport.getController().getDrools().factCount("junits")); + // The "update" event will undeploy "toscaPolicy" and deploy "toscaPolicy2" + ToscaPolicy toscaPolicy2 = + getExamplesPolicy("policies/vFirewall.policy.operational.input.tosca.json", "operational.modifyconfig"); + toscaPolicy.getProperties().remove("controllerName"); + update.setPolicies(Arrays.asList(toscaPolicy2)); + assertTrue(fsm.update(update)); + assertEquals(3, fsm.policyTypesMap.size()); + assertEquals(1, fsm.policiesMap.size()); + assertEquals(toscaPolicy2, fsm.policiesMap.get(toscaPolicy2.getIdentifier())); + assertNull(fsm.policiesMap.get(toscaPolicy.getIdentifier())); + assertEquals(0, controllerSupport.getController().getDrools().factCount("junits")); + update.setPdpGroup(null); update.setPdpSubgroup(null); update.setPolicies(Collections.emptyList()); @@ -240,7 +252,6 @@ public class LifecycleStatePassiveTest extends LifecycleStateRunningTest { fsm.shutdown(); } - @Test public void testStateChange() throws CoderException, IOException { /* no name */ diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java index 4f4b124e..18d00fc9 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2020-2021 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. @@ -20,6 +20,7 @@ package org.onap.policy.drools.lifecycle; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; @@ -74,17 +75,36 @@ public class PolicyTypeDroolsControllerTest extends LifecycleStateRunningTest { /* non-existing controller */ assertFalse(controller.undeploy(policy)); assertFalse(controller.deploy(policy)); + assertFalse(controllerSupport.getController().getDrools().exists(policy)); + assertEquals(0, controllerSupport.getController().getDrools().factCount(ControllerSupport.SESSION_NAME)); policy.getProperties().remove("controllerName"); - assertTrue(controller.deploy(policy)); - assertTrue(controller.undeploy(policy)); - assertFalse(controller.undeploy(policy)); + + deploy(); + deploy(); // one more time + + undeploy(); + undeploy(); // one more time /* existing controller */ policy.getProperties().put("controllerName", "lifecycle"); - assertTrue(controller.deploy(policy)); + + deploy(); + deploy(); // one more time + + undeploy(); + undeploy(); // one more time + } + + protected void undeploy() { assertTrue(controller.undeploy(policy)); - assertFalse(controller.undeploy(policy)); + assertFalse(controllerSupport.getController().getDrools().exists(policy)); + assertEquals(0, controllerSupport.getController().getDrools().factCount(ControllerSupport.SESSION_NAME)); } + protected void deploy() { + assertTrue(controller.deploy(policy)); + assertTrue(controllerSupport.getController().getDrools().exists(policy)); + assertEquals(1, controllerSupport.getController().getDrools().factCount(ControllerSupport.SESSION_NAME)); + } } \ No newline at end of file diff --git a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java index 3a04c313..43d3fe32 100644 --- a/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java @@ -25,8 +25,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Collections; @@ -441,15 +439,8 @@ public class RestLifecycleManagerTest { } private LifecycleFsm newFsmInstance() throws NoSuchFieldException, IllegalAccessException { - Field fsmField = LifecycleFeature.class.getDeclaredField("fsm"); - fsmField.setAccessible(true); - - Field modifiers = Field.class.getDeclaredField("modifiers"); - modifiers.setAccessible(true); - modifiers.setInt(fsmField, fsmField.getModifiers() & ~Modifier.FINAL); - LifecycleFsm fsm = new LifecycleFsm(); - fsmField.set(null, fsm); + ControllerSupport.setStaticField(LifecycleFeature.class, "fsm", fsm); return fsm; } diff --git a/feature-lifecycle/src/test/resources/echo.drl b/feature-lifecycle/src/test/resources/echo.drl new file mode 100644 index 00000000..ac1af3e3 --- /dev/null +++ b/feature-lifecycle/src/test/resources/echo.drl @@ -0,0 +1,35 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2021 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.test; + +rule "INIT" +lock-on-active +when +then + insert(new String("I am up")); +end + +rule "ECHO" +when + $o : Object(); +then + System.out.println("ECHO: " + $o.toString()); +end diff --git a/feature-lifecycle/src/test/resources/echo.kmodule b/feature-lifecycle/src/test/resources/echo.kmodule new file mode 100644 index 00000000..98d80a90 --- /dev/null +++ b/feature-lifecycle/src/test/resources/echo.kmodule @@ -0,0 +1,27 @@ + + + + + + + + + \ No newline at end of file diff --git a/feature-lifecycle/src/test/resources/echo.pom b/feature-lifecycle/src/test/resources/echo.pom new file mode 100644 index 00000000..e66e783d --- /dev/null +++ b/feature-lifecycle/src/test/resources/echo.pom @@ -0,0 +1,31 @@ + + + + + + 4.0.0 + + org.onap.policy.drools.test + echo + + 1.0.0 + diff --git a/feature-lifecycle/src/test/resources/tosca-policy-native-artifact-foo.json b/feature-lifecycle/src/test/resources/tosca-policy-native-artifact-foo.json index afdc0a83..eeb3e5a4 100644 --- a/feature-lifecycle/src/test/resources/tosca-policy-native-artifact-foo.json +++ b/feature-lifecycle/src/test/resources/tosca-policy-native-artifact-foo.json @@ -14,7 +14,7 @@ "properties": { "rulesArtifact": { "groupId": "org.onap.policy.drools.test", - "artifactId": "lifecycle", + "artifactId": "echo", "version": "1.0.0" }, "controller": { -- cgit 1.2.3-korg