summaryrefslogtreecommitdiffstats
path: root/feature-lifecycle
diff options
context:
space:
mode:
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": {