diff options
16 files changed, 1055 insertions, 113 deletions
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<ToscaPolicy> getDeployablePoliciesAction(@NonNull List<ToscaPolicy> policies) { List<ToscaPolicy> 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<String, List<ToscaPolicy>> policyTypeGroups = groupPoliciesByPolicyType(deployPolicies); // place native controller policies at the start of the list - List<ToscaPolicy> orderedDeployableList = - new ArrayList<>(policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName(), - Collections.EMPTY_LIST)); + List<ToscaPolicy> 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<ToscaPolicy> getUndeployablePoliciesAction(@NonNull List<ToscaPolicy> policies) { - List<ToscaPolicy> undeployPolicies = new ArrayList<>(policiesMap.values()); + List<ToscaPolicy> 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<ToscaPolicy> resetPoliciesAction() { - List<ToscaPolicy> policies = new ArrayList<>(policiesMap.values()); + List<ToscaPolicy> policies = new ArrayList<>(getActivePolicies()); policiesMap.clear(); return policies; } - protected boolean updatePoliciesAction(List<ToscaPolicy> toscaPolicies) { - return (this.scheduler.submit(() -> state.updatePolicies(toscaPolicies)) != null); + protected void updatePoliciesAction(List<ToscaPolicy> toscaPolicies) { + this.scheduler.submit(() -> state.updatePolicies(toscaPolicies)); } protected PolicyTypeController getController(ToscaConceptIdentifier policyType) { @@ -428,7 +425,9 @@ public class LifecycleFsm implements Startable { } protected Map<String, List<ToscaPolicy>> groupPoliciesByPolicyType(List<ToscaPolicy> deployPolicies) { - return deployPolicies.stream().collect(Collectors.groupingBy(policy -> policy.getTypeIdentifier().getName())); + return deployPolicies.stream() + .distinct() + .collect(Collectors.groupingBy(policy -> policy.getTypeIdentifier().getName())); } protected List<ToscaPolicy> getNonNativePolicies(@NonNull Map<String, List<ToscaPolicy>> policyTypeGroups) { @@ -438,6 +437,25 @@ public class LifecycleFsm implements Startable { .flatMap(entry -> entry.getValue().stream()).collect(Collectors.toList()); } + protected List<ToscaPolicy> getNativeArtifactPolicies(@NonNull Map<String, List<ToscaPolicy>> 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<ToscaPolicy> getNativeControllerPolicies(@NonNull Map<String, List<ToscaPolicy>> 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<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> activePoliciesPreUpdate = fsm.getActivePolicies(); + + // update policies with the current set of active policies + + Pair<List<ToscaPolicy>, List<ToscaPolicy>> 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<ToscaPolicy> 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<ToscaPolicy> policies) { + Pair<List<ToscaPolicy>, List<ToscaPolicy>> results = updatePoliciesWithResults(policies); + return results.getLeft().isEmpty() && results.getRight().isEmpty(); + } + + protected Pair<List<ToscaPolicy>, List<ToscaPolicy>> updatePoliciesWithResults(List<ToscaPolicy> 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<ToscaPolicy> failedUndeployPolicies = undeployPolicies(policies); + if (!failedUndeployPolicies.isEmpty()) { + logger.warn("update-policies: undeployment failures: {}", fsm.getPolicyIdsMessage(failedUndeployPolicies)); + failedUndeployPolicies.stream().forEach(fsm::undeployedPolicyAction); + } + + List<ToscaPolicy> failedDeployPolicies = deployPolicies(policies); + if (!failedDeployPolicies.isEmpty()) { + logger.warn("update-policies: deployment failures: {}", fsm.getPolicyIdsMessage(failedDeployPolicies)); + } + + return Pair.of(failedUndeployPolicies, failedDeployPolicies); } - protected boolean deployPolicies(List<ToscaPolicy> policies) { + protected List<ToscaPolicy> reapplyNonNativePolicies(List<ToscaPolicy> preActivePolicies) { + // only need to re-apply non native policies if there are new native artifact policies + + Map<String, List<ToscaPolicy>> activePoliciesByType = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); + List<ToscaPolicy> activeNativeArtifactPolicies = fsm.getNativeArtifactPolicies(activePoliciesByType); + + Map<String, List<ToscaPolicy>> 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<ToscaPolicy> 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<ToscaPolicy> failedPolicies = syncPolicies(preNonNativePolicies, this::deployPolicy); + logger.info("re-applying non-native policies failures: {}", fsm.getPolicyIdsMessage(failedPolicies)); + + return failedPolicies; + } + + protected List<ToscaPolicy> reapplyNativeArtifactPolicies(List<ToscaPolicy> preActivePolicies) { + // only need to re-apply native artifact policies if there are new native controller policies + + Map<String, List<ToscaPolicy>> activePoliciesByType = fsm.groupPoliciesByPolicyType(fsm.getActivePolicies()); + List<ToscaPolicy> activeNativeControllerPolicies = fsm.getNativeControllerPolicies(activePoliciesByType); + + Map<String, List<ToscaPolicy>> 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<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> deployPolicies(List<ToscaPolicy> policies) { return syncPolicies(fsm.getDeployablePoliciesAction(policies), this::deployPolicy); } - protected boolean undeployPolicies(List<ToscaPolicy> policies) { + protected List<ToscaPolicy> undeployPolicies(List<ToscaPolicy> policies) { return syncPolicies(fsm.getUndeployablePoliciesAction(policies), this::undeployPolicy); } - protected boolean syncPolicies(List<ToscaPolicy> policies, + protected List<ToscaPolicy> syncPolicies(List<ToscaPolicy> policies, BiPredicate<PolicyTypeController, ToscaPolicy> sync) { - boolean success = true; + List<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> 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(); @@ -81,14 +84,21 @@ public class ControllerSupport { } /** + * Install a maven artifact. + */ + public static ReleaseId installArtifact(File kmodule, File pom, + String drlKjarPath, List<File> 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 <T> Field unsetFinalStaticAccess(Class<T> 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 <T, E> void setStaticField(Class<T> 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<ToscaPolicy> 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<String, List<ToscaPolicy>> 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<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> 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<ToscaPolicy> testPolicies) throws CoderException { + verifyActivePoliciesWithDisables(testPolicies, Collections.emptyList()); + } + + protected void verifyActivePoliciesWithDisables(List<ToscaPolicy> testPolicies, + List<ToscaConceptIdentifier> 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<String, List<ToscaPolicy>> testPoliciesMap = fsm.groupPoliciesByPolicyType(testPolicies); + Map<String, List<ToscaPolicy>> 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<ToscaPolicy> 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<ToscaConceptIdentifier> nativeDisables) throws CoderException { + List<ToscaPolicy> nativeArtifactPolicies = + fsm.getNativeArtifactPolicies(fsm.groupPoliciesByPolicyType(fsm.getActivePolicies())); + + List<ToscaPolicy> 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<NativeArtifactPolicy> 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<NativeArtifactPolicy> getNativeArtifactPoliciesBut(List<ToscaPolicy> 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<NativeArtifactPolicy> getNativeArtifactPolicies(List<ToscaPolicy> 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<ControllerPolicy> getNativeControllerPolicies(List<ToscaPolicy> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============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========================================================= + --> + +<kmodule xmlns="http://jboss.org/kie/6.0.0/kmodule"> + <kbase name="onap.policies.typeA" default="false" equalsBehavior="equality"/> + <kbase name="onap.policies.type1.type2" includes="onap.policies.typeA"> + <ksession name="echo"/> + </kbase> +</kmodule>
\ 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ============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========================================================= + --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>org.onap.policy.drools.test</groupId> + <artifactId>echo</artifactId> + <!-- the version below is irrelevant --> + <version>1.0.0</version> +</project> 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": { |