summaryrefslogtreecommitdiffstats
path: root/feature-lifecycle
diff options
context:
space:
mode:
authorjhh <jorge.hernandez-herrero@att.com>2021-01-15 16:51:47 -0600
committerjhh <jorge.hernandez-herrero@att.com>2021-01-27 00:39:32 -0600
commit77d088a607c33c236bc41c58d9567e10299357a5 (patch)
treec35c7d92a58f49cc6d069910a4eab20a6bd08993 /feature-lifecycle
parent6d94c4ec33520776971c781c6ea6e80e6d0070b5 (diff)
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 <jorge.hernandez-herrero@att.com> Change-Id: Ieb8e5e17862e9d607433a1d4e86a026725d73498 Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
Diffstat (limited to 'feature-lifecycle')
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFeature.java16
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java52
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStatePassive.java5
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleStateRunning.java186
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsController.java29
-rw-r--r--feature-lifecycle/src/main/java/org/onap/policy/drools/server/restful/RestLifecycleManager.java64
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/ControllerSupport.java47
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java29
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmUpdateTest.java585
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleStatePassiveTest.java17
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/PolicyTypeDroolsControllerTest.java32
-rw-r--r--feature-lifecycle/src/test/java/org/onap/policy/drools/server/restful/RestLifecycleManagerTest.java11
-rw-r--r--feature-lifecycle/src/test/resources/echo.drl35
-rw-r--r--feature-lifecycle/src/test/resources/echo.kmodule27
-rw-r--r--feature-lifecycle/src/test/resources/echo.pom31
-rw-r--r--feature-lifecycle/src/test/resources/tosca-policy-native-artifact-foo.json2
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": {