support for PAP delta updates
[policy/drools-pdp.git] / feature-lifecycle / src / test / java / org / onap / policy / drools / lifecycle / LifecycleStateActiveTest.java
1 /*
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2021 AT&T Intellectual Property. All rights reserved.
4  * Modifications Copyright (C) 2021 Nordix Foundation.
5  * ================================================================================
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * SPDX-License-Identifier: Apache-2.0
19  * =============LICENSE_END========================================================
20  */
21
22 package org.onap.policy.drools.lifecycle;
23
24 import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertFalse;
27 import static org.junit.Assert.assertNotEquals;
28 import static org.junit.Assert.assertNotNull;
29 import static org.junit.Assert.assertTrue;
30
31 import java.io.IOException;
32 import java.nio.charset.StandardCharsets;
33 import java.nio.file.Files;
34 import java.nio.file.Paths;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.Objects;
38 import java.util.concurrent.TimeUnit;
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.onap.policy.common.utils.coder.CoderException;
42 import org.onap.policy.common.utils.coder.StandardCoder;
43 import org.onap.policy.common.utils.network.NetworkUtil;
44 import org.onap.policy.models.pdp.concepts.PdpStateChange;
45 import org.onap.policy.models.pdp.concepts.PdpStatus;
46 import org.onap.policy.models.pdp.concepts.PdpUpdate;
47 import org.onap.policy.models.pdp.enums.PdpState;
48 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
49 import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicy;
50
51 /**
52  * Lifecycle State Active Test.
53  */
54 public class LifecycleStateActiveTest extends LifecycleStateRunningTest {
55
56     private static final String POLICY_COMPLIANT_VCPE_BAD_INTEGER_JSON =
57             "src/test/resources/tosca-policy-compliant-vcpe-bad-integer.json";
58
59     /**
60      * Start tests in the Active state.
61      */
62     @Before
63     public void startActive() throws CoderException {
64         fsm = makeFsmWithPseudoTime();
65
66         fsm.setStatusTimerSeconds(15);
67         assertTrue(fsm.start());
68
69         goActive();
70         assertActive();
71     }
72
73     private void goActive() throws CoderException {
74         PdpStateChange change = new PdpStateChange();
75         change.setPdpGroup("A");
76         change.setPdpSubgroup("a");
77         change.setState(PdpState.ACTIVE);
78         change.setName(fsm.getName());
79
80         fsm.setSubGroup("a");
81         fsm.source.offer(new StandardCoder().encode(change));
82         controllerSupport.getController().start();
83     }
84
85     @Test
86     public void constructor() {
87         assertThatIllegalArgumentException().isThrownBy(() -> new LifecycleStateActive(null));
88         fsm.shutdown();
89     }
90
91     @Test
92     public void testStart() {
93         assertActive();
94         assertFalse(fsm.start());
95         assertActive();
96
97         fsm.shutdown();
98     }
99
100     private void assertActive() {
101         assertEquals(PdpState.ACTIVE, fsm.state());
102         assertEquals(LifecycleFsm.DEFAULT_PDP_GROUP, fsm.getGroup());
103         assertEquals("a", fsm.getSubGroup());
104         assertTrue(fsm.isAlive());
105         waitUntil(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS, isStatus(PdpState.ACTIVE));
106     }
107
108     @Test
109     public void testStop() {
110         assertTrue(fsm.stop());
111         assertBasicTerminated();
112
113         fsm.shutdown();
114     }
115
116     private void assertBasicTerminated() {
117         assertEquals(PdpState.TERMINATED, fsm.state());
118         assertFalse(fsm.isAlive());
119         assertFalse(fsm.state.isAlive());
120         waitUntil(1, TimeUnit.SECONDS, isStatus(PdpState.TERMINATED));
121     }
122
123     @Test
124     public void testShutdown() {
125         fsm.shutdown();
126
127         assertBasicTerminated();
128
129         assertTrue(fsm.statusTask.isCancelled());
130         assertTrue(fsm.statusTask.isDone());
131     }
132
133     @Test
134     public void testStatus() {
135         waitUntil(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS, isStatus(PdpState.ACTIVE));
136         int preCount = fsm.client.getSink().getRecentEvents().length;
137
138         assertTrue(fsm.status());
139         assertEquals(preCount + 1, fsm.client.getSink().getRecentEvents().length);
140
141         fsm.start(controllerSupport.getController());
142         assertTrue(fsm.status());
143         assertEquals(preCount + 2, fsm.client.getSink().getRecentEvents().length);
144
145         fsm.stop(controllerSupport.getController());
146         fsm.shutdown();
147     }
148
149     @Test
150     public void testStateChange() throws CoderException {
151         assertActive();
152
153         /* no name and mismatching group info */
154         PdpStateChange change = new PdpStateChange();
155         change.setPdpGroup("B");
156         change.setPdpSubgroup("b");
157         change.setState(PdpState.ACTIVE);
158
159         fsm.source.offer(new StandardCoder().encode(change));
160         assertEquals(PdpState.ACTIVE, fsm.state());
161         assertEquals(LifecycleFsm.DEFAULT_PDP_GROUP, fsm.getGroup());
162         assertNotEquals("b", fsm.getSubGroup());
163
164         change.setName(fsm.getName());
165         fsm.source.offer(new StandardCoder().encode(change));
166         assertEquals(PdpState.ACTIVE, fsm.state());
167         assertEquals(LifecycleFsm.DEFAULT_PDP_GROUP, fsm.getGroup());
168         assertEquals("a", fsm.getSubGroup());
169
170         change.setState(PdpState.SAFE);
171         fsm.source.offer(new StandardCoder().encode(change));
172         assertEquals(PdpState.ACTIVE, fsm.state());
173
174         change.setState(PdpState.TERMINATED);
175         fsm.source.offer(new StandardCoder().encode(change));
176         assertEquals(PdpState.ACTIVE, fsm.state());
177
178         change.setState(PdpState.PASSIVE);
179         fsm.source.offer(new StandardCoder().encode(change));
180         assertEquals(PdpState.PASSIVE, fsm.state());
181         waitUntil(fsm.getStatusTimerSeconds() + 1, TimeUnit.SECONDS, isStatus(PdpState.PASSIVE));
182
183         fsm.shutdown();
184     }
185
186     @Test
187     public void testUpdate() throws IOException, CoderException {
188
189         // TODO: extract repeated similar assertion blocks into their own helper methods
190
191         PdpUpdate update = new PdpUpdate();
192         update.setName(NetworkUtil.getHostname());
193         update.setPdpGroup("W");
194         update.setPdpSubgroup("w");
195
196         fsm.start(controllerSupport.getController());
197         assertTrue(fsm.update(update));
198
199         assertEquals(PdpState.ACTIVE, fsm.state());
200         assertEquals(LifecycleFsm.DEFAULT_PDP_GROUP, fsm.getGroup());
201         assertEquals("w", fsm.getSubGroup());
202
203         ToscaPolicy toscaPolicyRestartV1 =
204             getExamplesPolicy("policies/vCPE.policy.operational.input.tosca.json", "operational.restart");
205         toscaPolicyRestartV1.getProperties().put("controllerName", "lifecycle");
206         update.setPoliciesToBeDeployed(List.of(toscaPolicyRestartV1));
207
208         int qlength = fsm.client.getSink().getRecentEvents().length;
209
210         // update with an operational.restart policy
211
212         assertTrue(fsm.update(update));
213         assertEquals(qlength + 1, fsm.client.getSink().getRecentEvents().length);
214         assertEquals(3, fsm.policyTypesMap.size());
215         assertNotNull(fsm.getPolicyTypesMap().get(
216                 new ToscaConceptIdentifier("onap.policies.native.drools.Controller", "1.0.0")));
217         assertNotNull(fsm.getPolicyTypesMap().get(
218                 new ToscaConceptIdentifier("onap.policies.native.drools.Artifact", "1.0.0")));
219         assertNotNull(fsm.getPolicyTypesMap().get(
220                 new ToscaConceptIdentifier("onap.policies.controlloop.operational.common.Drools",
221                 "1.0.0")));
222         PdpStatus cachedStatus = new StandardCoder()
223                                     .decode(fsm.client.getSink().getRecentEvents()[qlength], PdpStatus.class);
224         assertEquals("foo", cachedStatus.getPdpType());
225         assertEquals(new ArrayList<>(fsm.policiesMap.keySet()), cachedStatus.getPolicies());
226
227         List<ToscaPolicy> factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
228         assertEquals(1, factPolicies.size());
229         assertEquals(toscaPolicyRestartV1, factPolicies.get(0));
230         assertEquals(1, fsm.policiesMap.size());
231
232         // dup update with the same operational.restart policy - nothing changes
233
234         assertTrue(fsm.update(update));
235         assertEquals(qlength + 2, fsm.client.getSink().getRecentEvents().length);
236         assertEquals(3, fsm.policyTypesMap.size());
237         cachedStatus = new StandardCoder()
238             .decode(fsm.client.getSink().getRecentEvents()[qlength + 1], PdpStatus.class);
239         assertEquals(new ArrayList<>(fsm.policiesMap.keySet()), cachedStatus.getPolicies());
240
241         factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
242         assertEquals(1, factPolicies.size());
243         assertEquals(toscaPolicyRestartV1, factPolicies.get(0));
244         assertEquals(1, fsm.policiesMap.size());
245
246         // undeploy operational.restart policy
247
248         update.setPolicies(List.of());
249         update.setPoliciesToBeDeployed(List.of());
250         update.setPoliciesToBeUndeployed(List.of(toscaPolicyRestartV1.getIdentifier()));
251         assertTrue(fsm.update(update));
252         assertEquals(qlength + 3, fsm.client.getSink().getRecentEvents().length);
253         assertEquals(3, fsm.policyTypesMap.size());
254         cachedStatus = new StandardCoder()
255             .decode(fsm.client.getSink().getRecentEvents()[qlength + 2], PdpStatus.class);
256         assertEquals(new ArrayList<>(fsm.policiesMap.keySet()), cachedStatus.getPolicies());
257
258         factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
259         assertEquals(0, factPolicies.size());
260         assertEquals(0, fsm.policiesMap.size());
261
262         // redeploy operational.restart policy
263
264         update.setPolicies(List.of());
265         update.setPoliciesToBeUndeployed(List.of());
266         update.setPoliciesToBeDeployed(List.of(toscaPolicyRestartV1));
267         assertTrue(fsm.update(update));
268         assertEquals(qlength + 4, fsm.client.getSink().getRecentEvents().length);
269         assertEquals(3, fsm.policyTypesMap.size());
270         cachedStatus = new StandardCoder()
271             .decode(fsm.client.getSink().getRecentEvents()[qlength + 3], PdpStatus.class);
272         assertEquals(new ArrayList<>(fsm.policiesMap.keySet()), cachedStatus.getPolicies());
273
274         factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
275         assertEquals(1, factPolicies.size());
276         assertEquals(toscaPolicyRestartV1, factPolicies.get(0));
277         assertEquals(1, fsm.policiesMap.size());
278
279         // deploy a new version of the operational.restart policy
280
281         ToscaPolicy toscaPolicyRestartV2 =
282             getExamplesPolicy("policies/vCPE.policy.operational.input.tosca.json", "operational.restart");
283         toscaPolicyRestartV2.setVersion("2.0.0");
284         toscaPolicyRestartV2.getProperties().put("controllerName", "lifecycle");
285         update.setPolicies(List.of());
286         update.setPoliciesToBeUndeployed(List.of(toscaPolicyRestartV1.getIdentifier()));
287         update.setPoliciesToBeDeployed(List.of(toscaPolicyRestartV2));
288         assertTrue(fsm.update(update));
289         assertEquals(qlength + 5, fsm.client.getSink().getRecentEvents().length);
290         assertEquals(3, fsm.policyTypesMap.size());
291         cachedStatus = new StandardCoder()
292             .decode(fsm.client.getSink().getRecentEvents()[qlength + 4], PdpStatus.class);
293         assertEquals(new ArrayList<>(fsm.policiesMap.keySet()), cachedStatus.getPolicies());
294
295         factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
296         assertEquals(1, factPolicies.size());
297         assertNotEquals(toscaPolicyRestartV1, factPolicies.get(0));
298         assertEquals(toscaPolicyRestartV2, factPolicies.get(0));
299         assertEquals(1, fsm.policiesMap.size());
300
301         // deploy another policy : firewall
302
303         ToscaPolicy toscaPolicyFirewall =
304             getExamplesPolicy("policies/vFirewall.policy.operational.input.tosca.json", "operational.modifyconfig");
305         toscaPolicyFirewall.getProperties().put("controllerName", "lifecycle");
306         update.setPolicies(List.of());
307         update.setPoliciesToBeUndeployed(List.of());
308         update.setPoliciesToBeDeployed(List.of(toscaPolicyRestartV2, toscaPolicyFirewall));
309         assertTrue(fsm.update(update));
310         assertEquals(qlength + 6, fsm.client.getSink().getRecentEvents().length);
311         assertEquals(3, fsm.policyTypesMap.size());
312         cachedStatus = new StandardCoder()
313             .decode(fsm.client.getSink().getRecentEvents()[qlength + 5], PdpStatus.class);
314         assertEquals(new ArrayList<>(fsm.policiesMap.keySet()), cachedStatus.getPolicies());
315
316         factPolicies = controllerSupport.getFacts(ToscaPolicy.class);
317         assertEquals(2, factPolicies.size());
318         assertTrue(factPolicies.stream().noneMatch((ff) -> Objects.equals(toscaPolicyRestartV1, ff)));
319         assertTrue(factPolicies.stream().anyMatch((ff) -> Objects.equals(toscaPolicyRestartV2, ff)));
320         assertTrue(factPolicies.stream().anyMatch((ff) -> Objects.equals(toscaPolicyFirewall, ff)));
321         assertEquals(2, fsm.policiesMap.size());
322
323         long originalInterval = fsm.getStatusTimerSeconds();
324         long interval = 10 * originalInterval;
325         update.setPdpHeartbeatIntervalMs(interval * 1000L);
326
327         update.setPolicies(List.of());
328         update.setPoliciesToBeUndeployed(List.of());
329         update.setPoliciesToBeDeployed(List.of());
330         assertTrue(fsm.update(update));
331
332         assertEquals(PdpState.ACTIVE, fsm.state());
333         assertEquals(interval, fsm.getStatusTimerSeconds());
334
335         // bad policy deployment
336
337         String badIntegerPolicy =
338             Files.readString(Paths.get(POLICY_COMPLIANT_VCPE_BAD_INTEGER_JSON), StandardCharsets.UTF_8);
339         ToscaPolicy toscaPolicyRestartBad = new StandardCoder().decode(badIntegerPolicy, ToscaPolicy.class);
340         update.setPolicies(List.of());
341         update.setPoliciesToBeUndeployed(List.of(toscaPolicyRestartV2.getIdentifier(),
342                 toscaPolicyFirewall.getIdentifier()));
343         update.setPoliciesToBeDeployed(List.of(toscaPolicyRestartBad));
344         assertFalse(fsm.update(update));
345
346         assertTrue(controllerSupport.getController().getDrools().delete(ToscaPolicy.class));
347
348         fsm.shutdown();
349     }
350
351 }