Copy policy-endpoints from drools-pdp to common
[policy/drools-applications.git] / controlloop / templates / template.demo / src / test / java / org / onap / policy / template / demo / VFWControlLoopTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * demo
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.template.demo;
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertTrue;
26 import static org.junit.Assert.fail;
27
28 import java.io.IOException;
29 import java.net.URLEncoder;
30 import java.time.Instant;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Properties;
34 import java.util.UUID;
35
36 import org.junit.AfterClass;
37 import org.junit.BeforeClass;
38 import org.junit.Test;
39 import org.kie.api.runtime.KieSession;
40 import org.kie.api.runtime.rule.FactHandle;
41 import org.onap.policy.appc.Request;
42 import org.onap.policy.appc.Response;
43 import org.onap.policy.appc.ResponseCode;
44 import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure;
45 import org.onap.policy.common.endpoints.event.comm.TopicEndpoint;
46 import org.onap.policy.common.endpoints.event.comm.TopicListener;
47 import org.onap.policy.common.endpoints.event.comm.TopicSink;
48 import org.onap.policy.common.endpoints.http.server.HttpServletServer;
49 import org.onap.policy.common.endpoints.properties.PolicyEndPointProperties;
50 import org.onap.policy.controlloop.ControlLoopEventStatus;
51 import org.onap.policy.controlloop.ControlLoopNotificationType;
52 import org.onap.policy.controlloop.VirtualControlLoopEvent;
53 import org.onap.policy.controlloop.VirtualControlLoopNotification;
54 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
55 import org.onap.policy.drools.protocol.coders.EventProtocolCoder;
56 import org.onap.policy.drools.protocol.coders.JsonProtocolFilter;
57 import org.onap.policy.drools.system.PolicyController;
58 import org.onap.policy.drools.system.PolicyEngine;
59 import org.onap.policy.drools.utils.logging.LoggerUtil;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 public class VFWControlLoopTest implements TopicListener {
64
65     private static final Logger logger = LoggerFactory.getLogger(VFWControlLoopTest.class);
66
67     private static List<? extends TopicSink> noopTopics;
68
69     private static KieSession kieSession;
70     private static Util.Pair<ControlLoopPolicy, String> pair;
71     private UUID requestID;
72
73     static {
74         /* Set environment properties */
75         Util.setAAIProps();
76         Util.setGuardProps();
77         Util.setPUProp();
78         LoggerUtil.setLevel(LoggerUtil.ROOT_LOGGER, "INFO");
79     }
80
81     @BeforeClass
82     public static void setUpSimulator() {
83         PolicyEngine.manager.configure(new Properties());
84         assertTrue(PolicyEngine.manager.start());
85         Properties noopSinkProperties = new Properties();
86         noopSinkProperties.put(PolicyEndPointProperties.PROPERTY_NOOP_SINK_TOPICS, "APPC-CL,POLICY-CL-MGT");
87         noopSinkProperties.put("noop.sink.topics.APPC-CL.events", "org.onap.policy.appc.Response");
88         noopSinkProperties.put("noop.sink.topics.APPC-CL.events.custom.gson",
89                 "org.onap.policy.appc.util.Serialization,gsonPretty");
90         noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events",
91                 "org.onap.policy.controlloop.VirtualControlLoopNotification");
92         noopSinkProperties.put("noop.sink.topics.POLICY-CL-MGT.events.custom.gson",
93                 "org.onap.policy.controlloop.util.Serialization,gsonPretty");
94         noopTopics = TopicEndpoint.manager.addTopicSinks(noopSinkProperties);
95
96         EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "POLICY-CL-MGT",
97                 "org.onap.policy.controlloop.VirtualControlLoopNotification", new JsonProtocolFilter(), null, null,
98                 1111);
99         EventProtocolCoder.manager.addEncoder("junit.groupId", "junit.artifactId", "APPC-CL",
100                 "org.onap.policy.appc.Request", new JsonProtocolFilter(), null, null, 1111);
101
102         try {
103             Util.buildAaiSim();
104             Util.buildGuardSim();
105         } catch (Exception e) {
106             fail(e.getMessage());
107         }
108
109         /*
110          * Start the kie session
111          */
112         try {
113             kieSession = startSession(
114                     "../archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl",
115                     "src/test/resources/yaml/policy_ControlLoop_vFW.yaml",
116                     "service=ServiceDemo;resource=Res1Demo;type=operational", "CL_vFW",
117                     "org.onap.closed_loop.ServiceDemo:VNFS:1.0.0");
118         } catch (IOException e) {
119             e.printStackTrace();
120             logger.debug("Could not create kieSession");
121             fail("Could not create kieSession");
122         }
123     }
124
125     @AfterClass
126     public static void tearDownSimulator() {
127         /*
128          * Gracefully shut down the kie session
129          */
130         kieSession.dispose();
131
132         PolicyEngine.manager.stop();
133         HttpServletServer.factory.destroy();
134         PolicyController.factory.shutdown();
135         TopicEndpoint.manager.shutdown();
136     }
137
138     @Test
139     public void successTest() {
140
141         /*
142          * Allows the PolicyEngine to callback to this object to notify that there is an event ready
143          * to be pulled from the queue
144          */
145         for (TopicSink sink : noopTopics) {
146             assertTrue(sink.start());
147             sink.register(this);
148         }
149
150         /*
151          * Create a unique requestId
152          */
153         requestID = UUID.randomUUID();
154
155         /*
156          * Simulate an onset event the policy engine will receive from DCAE to kick off processing
157          * through the rules
158          */
159         sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET);
160
161         try {
162             kieSession.fireUntilHalt();
163         } catch (Exception e) {
164             e.printStackTrace();
165             logger.warn(e.toString());
166             fail("fail");
167         }
168
169
170         /*
171          * The only fact in memory should be Params
172          */
173         assertEquals(1, kieSession.getFactCount());
174
175         /*
176          * Print what's left in memory
177          */
178         dumpFacts(kieSession);
179     }
180
181     @Test
182     public void aaiFailTests() {
183
184         /*
185          * Allows the PolicyEngine to callback to this object to notify that there is an event ready
186          * to be pulled from the queue
187          */
188         for (TopicSink sink : noopTopics) {
189             assertTrue(sink.start());
190             sink.register(this);
191         }
192
193         /*
194          * Create a unique requestId
195          */
196         requestID = UUID.randomUUID();
197
198         /*
199          * Simulate an onset event the policy engine will receive from DCAE to kick off processing
200          * through the rules
201          */
202         sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET, "error");
203         try {
204             kieSession.fireUntilHalt();
205         } catch (Exception e) {
206             e.printStackTrace();
207             logger.warn(e.toString());
208             fail(e.getMessage());
209         }
210
211         /*
212          * The only fact in memory should be Params
213          */
214         assertEquals(1, kieSession.getFactCount());
215
216         /*
217          * Print what's left in memory
218          */
219         dumpFacts(kieSession);
220
221         /*
222          * Create a unique requestId
223          */
224         requestID = UUID.randomUUID();
225
226         /*
227          * Simulate an onset event the policy engine will receive from DCAE to kick off processing
228          * through the rules
229          */
230
231         sendEvent(pair.a, requestID, ControlLoopEventStatus.ONSET, "getFail");
232
233         try {
234             kieSession.fireUntilHalt();
235         } catch (Exception e) {
236             e.printStackTrace();
237             logger.warn(e.toString());
238             fail(e.getMessage());
239         }
240
241         /*
242          * The only fact in memory should be Params
243          */
244         assertEquals(1, kieSession.getFactCount());
245
246         /*
247          * Print what's left in memory
248          */
249         dumpFacts(kieSession);
250     }
251
252     /**
253      * This method will start a kie session and instantiate the Policy Engine.
254      * 
255      * @param droolsTemplate the DRL rules file
256      * @param yamlFile the yaml file containing the policies
257      * @param policyScope scope for policy
258      * @param policyName name of the policy
259      * @param policyVersion version of the policy
260      * @return the kieSession to be used to insert facts
261      * @throws IOException
262      */
263     private static KieSession startSession(String droolsTemplate, String yamlFile, String policyScope,
264             String policyName, String policyVersion) throws IOException {
265
266         /*
267          * Load policies from yaml
268          */
269         pair = Util.loadYaml(yamlFile);
270         assertNotNull(pair);
271         assertNotNull(pair.a);
272         assertNotNull(pair.a.getControlLoop());
273         assertNotNull(pair.a.getControlLoop().getControlLoopName());
274         assertTrue(pair.a.getControlLoop().getControlLoopName().length() > 0);
275
276         /*
277          * Construct a kie session
278          */
279         final KieSession kieSession = Util.buildContainer(droolsTemplate, pair.a.getControlLoop().getControlLoopName(),
280                 policyScope, policyName, policyVersion, URLEncoder.encode(pair.b, "UTF-8"));
281
282         /*
283          * Retrieve the Policy Engine
284          */
285
286         logger.debug("============");
287         logger.debug(URLEncoder.encode(pair.b, "UTF-8"));
288         logger.debug("============");
289
290         return kieSession;
291     }
292
293     /*
294      * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
295      */
296     @Override
297     public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
298         /*
299          * Pull the object that was sent out to DMAAP and make sure it is a ControlLoopNoticiation
300          * of type active
301          */
302         Object obj = null;
303         if ("POLICY-CL-MGT".equals(topic)) {
304             obj = org.onap.policy.controlloop.util.Serialization.gsonJunit.fromJson(event,
305                     org.onap.policy.controlloop.VirtualControlLoopNotification.class);
306         } else if ("APPC-CL".equals(topic)) {
307             obj = org.onap.policy.appc.util.Serialization.gsonPretty.fromJson(event,
308                     org.onap.policy.appc.Request.class);
309         }
310         assertNotNull(obj);
311         if (obj instanceof VirtualControlLoopNotification) {
312             VirtualControlLoopNotification notification = (VirtualControlLoopNotification) obj;
313             String policyName = notification.getPolicyName();
314             if (policyName.endsWith("EVENT")) {
315                 logger.debug("Rule Fired: " + notification.getPolicyName());
316                 assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.getNotification()));
317             } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
318                 logger.debug("Rule Fired: " + notification.getPolicyName());
319                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
320                 assertNotNull(notification.getMessage());
321                 assertTrue(notification.getMessage().startsWith("Sending guard query"));
322             } else if (policyName.endsWith("GUARD.RESPONSE")) {
323                 logger.debug("Rule Fired: " + notification.getPolicyName());
324                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
325                 assertNotNull(notification.getMessage());
326                 assertTrue(notification.getMessage().toLowerCase().endsWith("permit"));
327             } else if (policyName.endsWith("GUARD_PERMITTED")) {
328                 logger.debug("Rule Fired: " + notification.getPolicyName());
329                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
330                 assertNotNull(notification.getMessage());
331                 assertTrue(notification.getMessage().startsWith("actor=APPC"));
332             } else if (policyName.endsWith("OPERATION.TIMEOUT")) {
333                 logger.debug("Rule Fired: " + notification.getPolicyName());
334                 kieSession.halt();
335                 logger.debug("The operation timed out");
336                 fail("Operation Timed Out");
337             } else if (policyName.endsWith("APPC.RESPONSE")) {
338                 logger.debug("Rule Fired: " + notification.getPolicyName());
339                 assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.getNotification()));
340                 assertNotNull(notification.getMessage());
341                 assertTrue(notification.getMessage().startsWith("actor=APPC"));
342                 sendEvent(pair.a, requestID, ControlLoopEventStatus.ABATED);
343             } else if (policyName.endsWith("EVENT.MANAGER")) {
344                 logger.debug("Rule Fired: " + notification.getPolicyName());
345                 if ("error".equals(notification.getAai().get("generic-vnf.vnf-name"))) {
346                     assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notification.getNotification());
347                     assertEquals("Target vnf-id could not be found", notification.getMessage());
348                 } else if ("getFail".equals(notification.getAai().get("generic-vnf.vnf-name"))) {
349                     assertEquals(ControlLoopNotificationType.FINAL_FAILURE, notification.getNotification());
350                 } else {
351                     assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.getNotification()));
352                 }
353                 kieSession.halt();
354             } else if (policyName.endsWith("EVENT.MANAGER.TIMEOUT")) {
355                 logger.debug("Rule Fired: " + notification.getPolicyName());
356                 kieSession.halt();
357                 logger.debug("The control loop timed out");
358                 fail("Control Loop Timed Out");
359             }
360         } else if (obj instanceof Request) {
361             assertTrue(((Request) obj).getCommonHeader().getSubRequestId().equals("1"));
362             assertNotNull(((Request) obj).getPayload().get("generic-vnf.vnf-id"));
363
364             logger.debug("\n============ APPC received the request!!! ===========\n");
365
366             /*
367              * Simulate a success response from APPC and insert the response into the working memory
368              */
369             Response appcResponse = new Response((Request) obj);
370             appcResponse.getStatus().setCode(ResponseCode.SUCCESS.getValue());
371             appcResponse.getStatus().setValue("SUCCESS");
372             kieSession.insert(appcResponse);
373         }
374     }
375
376     /**
377      * This method is used to simulate event messages from DCAE that start the control loop (onset
378      * message) or end the control loop (abatement message).
379      * 
380      * @param policy the controlLoopName comes from the policy
381      * @param requestID the requestId for this event
382      * @param status could be onset or abated
383      */
384     protected void sendEvent(ControlLoopPolicy policy, UUID requestID, ControlLoopEventStatus status) {
385         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
386         event.setClosedLoopControlName(policy.getControlLoop().getControlLoopName());
387         event.setRequestId(requestID);
388         event.setTarget("generic-vnf.vnf-name");
389         event.setClosedLoopAlarmStart(Instant.now());
390         event.setAai(new HashMap<>());
391         event.getAai().put("generic-vnf.vnf-name", "testGenericVnfID");
392         event.setClosedLoopEventStatus(status);
393         kieSession.insert(event);
394     }
395
396     /**
397      * This method is used to simulate event messages from DCAE that start the control loop (onset
398      * message) or end the control loop (abatement message).
399      * 
400      * @param policy the controlLoopName comes from the policy
401      * @param requestID the requestId for this event
402      * @param status could be onset or abated
403      */
404     protected void sendEvent(ControlLoopPolicy policy, UUID requestID, ControlLoopEventStatus status, String vnfId) {
405         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
406         event.setClosedLoopControlName(policy.getControlLoop().getControlLoopName());
407         event.setRequestId(requestID);
408         event.setTarget("generic-vnf.vnf-name");
409         event.setClosedLoopAlarmStart(Instant.now());
410         event.setAai(new HashMap<>());
411         event.getAai().put("generic-vnf.vnf-name", vnfId);
412         event.setClosedLoopEventStatus(status);
413         kieSession.insert(event);
414     }
415
416     /**
417      * This method will dump all the facts in the working memory.
418      * 
419      * @param kieSession the session containing the facts
420      */
421     public void dumpFacts(KieSession kieSession) {
422         logger.debug("Fact Count: {}", kieSession.getFactCount());
423         for (FactHandle handle : kieSession.getFactHandles()) {
424             logger.debug("FACT: {}", handle);
425         }
426     }
427 }