diff options
-rw-r--r-- | feature-lifecycle/src/main/java/org/onap/policy/drools/lifecycle/LifecycleFsm.java | 66 | ||||
-rw-r--r-- | feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java | 172 |
2 files changed, 235 insertions, 3 deletions
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 ef47e1d6..5478136f 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 @@ -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"); @@ -22,6 +22,7 @@ package org.onap.policy.drools.lifecycle; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -347,13 +348,61 @@ public class LifecycleFsm implements Startable { protected List<ToscaPolicy> getDeployablePoliciesAction(@NonNull List<ToscaPolicy> policies) { List<ToscaPolicy> deployPolicies = new ArrayList<>(policies); deployPolicies.removeAll(policiesMap.values()); - return deployPolicies; + + // 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 + // controllers, starting with the ones that affect the existence of the controller (native controller), + // second the ones that "brain" the controller with application logic (native artifacts). + // Lastly the application specific ones such as operational policies. + + // group policies by policy types + 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)); + + // add to the working list the native controller policies + orderedDeployableList.addAll( + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_RULES.getName(), Collections.EMPTY_LIST)); + + // place non-native policies to place at the end of the list + orderedDeployableList.addAll(getNonNativePolicies(policyTypeGroups)); + + return orderedDeployableList; } protected List<ToscaPolicy> getUndeployablePoliciesAction(@NonNull List<ToscaPolicy> policies) { List<ToscaPolicy> undeployPolicies = new ArrayList<>(policiesMap.values()); undeployPolicies.removeAll(policies); - return undeployPolicies; + if (undeployPolicies.isEmpty()) { + return undeployPolicies; + } + + // Ensure that the sequence of policy undeployments is sane to minimize potential errors, + // as it is assumed not smart ordering from the policies sent by the PAP. + // First policies to undeploy are those that are only of relevance within a drools container, + // such as the operational policies. The next set of policies to undeploy are those that + // affect the overall PDP-D application support, firstly the ones that supports the + // application software wiring (native rules policies), and second those that relate + // to the PDP-D controllers lifecycle. + + // group policies by policy types + Map<String, List<ToscaPolicy>> policyTypeGroups = groupPoliciesByPolicyType(undeployPolicies); + + // place controller only (non-native policies) at the start of the list of the undeployment list + List<ToscaPolicy> orderedUndeployableList = getNonNativePolicies(policyTypeGroups); + + // add to the working list the native rules policies if any + orderedUndeployableList.addAll( + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_RULES.getName(), Collections.EMPTY_LIST)); + + // finally add to the working list native controller policies if any + orderedUndeployableList.addAll( + policyTypeGroups.getOrDefault(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName(), Collections.EMPTY_LIST)); + + return orderedUndeployableList; } protected void deployedPolicyAction(@NonNull ToscaPolicy policy) { @@ -378,6 +427,17 @@ public class LifecycleFsm implements Startable { return policyTypesMap.get(policyType); } + protected Map<String, List<ToscaPolicy>> groupPoliciesByPolicyType(List<ToscaPolicy> deployPolicies) { + return deployPolicies.stream().collect(Collectors.groupingBy(policy -> policy.getTypeIdentifier().getName())); + } + + protected List<ToscaPolicy> getNonNativePolicies(@NonNull Map<String, List<ToscaPolicy>> policyTypeGroups) { + return policyTypeGroups.entrySet().stream() + .filter(entry -> !entry.getKey().equals(POLICY_TYPE_DROOLS_NATIVE_RULES.getName()) + && !entry.getKey().equals(POLICY_TYPE_DROOLS_NATIVE_CONTROLLER.getName())) + .flatMap(entry -> entry.getValue().stream()).collect(Collectors.toList()); + } + /** * Do I support the mandatory policy types?. */ 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 new file mode 100644 index 00000000..b5c4f1b5 --- /dev/null +++ b/feature-lifecycle/src/test/java/org/onap/policy/drools/lifecycle/LifecycleFsmTest.java @@ -0,0 +1,172 @@ +/* + * ============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.junit.Assert.assertEquals; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ScheduledExecutorService; +import org.junit.Before; +import org.junit.Test; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +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.persistence.SystemPersistenceConstants; +import org.onap.policy.drools.utils.logging.LoggerUtil; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +/** + * Lifecycle FSM Test. + */ +public class LifecycleFsmTest { + + 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 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 String USECASES_NATIVE_CONTROLLER_POLICY_NAME = "usecases"; + private static final String USECASES_NATIVE_CONTROLLER_JSON = + "policies/usecases.native.controller.policy.input.tosca.json"; + + private static final String USECASES_NATIVE_ARTIFACT_POLICY_NAME = "usecases.artifacts"; + private static final String USECASES_NATIVE_ARTIFACT_JSON = + "policies/usecases.native.artifact.policy.input.tosca.json"; + + private static final StandardCoder coder = new StandardCoder(); + + 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; + + /** + * Test initialization. + */ + @Before + public void init() throws CoderException, 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"); + + fsm = new LifecycleFsm() { + @Override + protected ScheduledExecutorService makeExecutor() { + return new PseudoScheduledExecutorService(new TestTimeMulti()); + } + }; + + 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 = getExamplesPolicy(USECASES_NATIVE_CONTROLLER_JSON, USECASES_NATIVE_CONTROLLER_POLICY_NAME); + artifactPolicy = + getPolicyFromFile(EXAMPLE_NATIVE_ARTIFACT_POLICY_JSON, EXAMPLE_NATIVE_ARTIFACT_POLICY_NAME); + artifact2Policy = getExamplesPolicy(USECASES_NATIVE_ARTIFACT_JSON, USECASES_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 testGetDeployableActions() { + List<ToscaPolicy> expectedDeployOrder = + List.of(controllerPolicy, controller2Policy, artifact2Policy, artifactPolicy, + op2Policy, opPolicy, unvalPolicy, valPolicy); + + assertEquals(expectedDeployOrder, fsm.getDeployablePoliciesAction(expectedDeployOrder)); + assertEquals(expectedDeployOrder, + fsm.getDeployablePoliciesAction( + List.of(op2Policy, artifact2Policy, valPolicy, opPolicy, unvalPolicy, artifactPolicy, + controllerPolicy, controller2Policy))); + assertEquals(expectedDeployOrder, + fsm.getDeployablePoliciesAction( + List.of(artifact2Policy, op2Policy, artifactPolicy, controllerPolicy, opPolicy, + controller2Policy, valPolicy, unvalPolicy))); + } + + @Test + public void testGetUndeployableActions() { + fsm.deployedPolicyAction(controllerPolicy); + fsm.deployedPolicyAction(controller2Policy); + fsm.deployedPolicyAction(artifactPolicy); + fsm.deployedPolicyAction(artifact2Policy); + fsm.deployedPolicyAction(opPolicy); + 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 { + 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 |