fe7cb3c96d8a217098d2418ecb0d14a798c90435
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation.
4  * ================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.clamp.controlloop.participant.policy.main.utils;
22
23 import static org.junit.Assert.assertTrue;
24
25 import java.io.File;
26 import java.io.FileNotFoundException;
27 import java.time.Instant;
28 import java.util.ArrayList;
29 import java.util.LinkedHashMap;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.UUID;
34 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
35 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
36 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElementDefinition;
37 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopOrderedState;
38 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopState;
39 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantDefinition;
40 import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantUpdates;
41 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopStateChange;
42 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ControlLoopUpdate;
43 import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantUpdate;
44 import org.onap.policy.clamp.controlloop.participant.policy.main.parameters.CommonTestData;
45 import org.onap.policy.common.utils.coder.Coder;
46 import org.onap.policy.common.utils.coder.CoderException;
47 import org.onap.policy.common.utils.coder.StandardCoder;
48 import org.onap.policy.common.utils.coder.YamlJsonTranslator;
49 import org.onap.policy.common.utils.resources.ResourceUtils;
50 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
51 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
52 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
53 import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 public class TestListenerUtils {
58
59     private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator();
60     private static final Coder CODER = new StandardCoder();
61     static CommonTestData commonTestData = new CommonTestData();
62     private static final Logger LOGGER = LoggerFactory.getLogger(TestListenerUtils.class);
63     private static final String CONTROL_LOOP_ELEMENT = "org.onap.policy.clamp.controlloop.ControlLoopElement";
64     private static final String POLICY_TYPE_ID = "policy_type_id";
65     private static final String POLICY_ID = "policy_id";
66
67     private TestListenerUtils() {}
68
69     /**
70      * Method to create a controlLoop from a yaml file.
71      *
72      * @return ControlLoop controlloop
73      */
74     public static ControlLoop createControlLoop() {
75         ControlLoop controlLoop = new ControlLoop();
76         Map<UUID, ControlLoopElement> elements = new LinkedHashMap<>();
77         ToscaServiceTemplate toscaServiceTemplate = testControlLoopRead();
78         Map<String, ToscaNodeTemplate> nodeTemplatesMap =
79                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
80         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry : nodeTemplatesMap.entrySet()) {
81             ControlLoopElement clElement = new ControlLoopElement();
82             clElement.setId(UUID.randomUUID());
83
84             ToscaConceptIdentifier clElementParticipantId = new ToscaConceptIdentifier();
85             clElementParticipantId.setName(toscaInputEntry.getKey());
86             clElementParticipantId.setVersion(toscaInputEntry.getValue().getVersion());
87             clElement.setParticipantId(clElementParticipantId);
88
89             clElement.setDefinition(clElementParticipantId);
90             clElement.setState(ControlLoopState.UNINITIALISED);
91             clElement.setDescription(toscaInputEntry.getValue().getDescription());
92             clElement.setOrderedState(ControlLoopOrderedState.UNINITIALISED);
93             elements.put(clElement.getId(), clElement);
94         }
95         controlLoop.setElements(elements);
96         controlLoop.setName("PMSHInstance0");
97         controlLoop.setVersion("1.0.0");
98
99         ToscaConceptIdentifier definition = new ToscaConceptIdentifier();
100         definition.setName("PMSHInstance0");
101         definition.setVersion("1.0.0");
102         controlLoop.setDefinition(definition);
103
104         return controlLoop;
105     }
106
107     /**
108      * Method to create ControlLoopStateChange message from the arguments passed.
109      *
110      * @param controlLoopOrderedState controlLoopOrderedState
111      *
112      * @return ControlLoopStateChange message
113      */
114     public static ControlLoopStateChange createControlLoopStateChangeMsg(
115             final ControlLoopOrderedState controlLoopOrderedState) {
116         final ControlLoopStateChange clStateChangeMsg = new ControlLoopStateChange();
117
118         ToscaConceptIdentifier controlLoopId = new ToscaConceptIdentifier();
119         controlLoopId.setName("PMSHInstance0");
120         controlLoopId.setVersion("1.0.0");
121
122         ToscaConceptIdentifier participantId = new ToscaConceptIdentifier();
123         participantId.setName("org.onap.PM_Policy");
124         participantId.setVersion("0.0.0");
125
126         clStateChangeMsg.setControlLoopId(controlLoopId);
127         clStateChangeMsg.setParticipantId(participantId);
128         clStateChangeMsg.setTimestamp(Instant.now());
129         clStateChangeMsg.setOrderedState(controlLoopOrderedState);
130
131         return clStateChangeMsg;
132     }
133
134     /**
135      * Method to create ControlLoopUpdateMsg.
136      *
137      * @return ControlLoopUpdate message
138      */
139     public static ControlLoopUpdate createControlLoopUpdateMsg() {
140         final ControlLoopUpdate clUpdateMsg = new ControlLoopUpdate();
141         ToscaConceptIdentifier controlLoopId =
142             new ToscaConceptIdentifier("PMSHInstance0", "1.0.0");
143         ToscaConceptIdentifier participantId =
144             new ToscaConceptIdentifier("org.onap.PM_Policy", "0.0.0");
145
146         clUpdateMsg.setControlLoopId(controlLoopId);
147         clUpdateMsg.setParticipantId(participantId);
148         clUpdateMsg.setMessageId(UUID.randomUUID());
149         clUpdateMsg.setTimestamp(Instant.now());
150
151         Map<UUID, ControlLoopElement> elements = new LinkedHashMap<>();
152         ToscaServiceTemplate toscaServiceTemplate = testControlLoopRead();
153         TestListenerUtils.addPoliciesToToscaServiceTemplate(toscaServiceTemplate);
154         Map<String, ToscaNodeTemplate> nodeTemplatesMap =
155                 toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates();
156         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry : nodeTemplatesMap.entrySet()) {
157             if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
158                 ControlLoopElement clElement = new ControlLoopElement();
159                 clElement.setId(UUID.randomUUID());
160                 ToscaConceptIdentifier clParticipantType;
161                 try {
162                     clParticipantType = CODER.decode(
163                             toscaInputEntry.getValue().getProperties().get("participantType").toString(),
164                             ToscaConceptIdentifier.class);
165                 } catch (CoderException e) {
166                     throw new RuntimeException("cannot get ParticipantType from toscaNodeTemplate", e);
167                 }
168
169                 clElement.setParticipantId(clParticipantType);
170                 clElement.setParticipantType(clParticipantType);
171
172                 clElement.setDefinition(new ToscaConceptIdentifier(toscaInputEntry.getKey(),
173                     toscaInputEntry.getValue().getVersion()));
174                 clElement.setState(ControlLoopState.UNINITIALISED);
175                 clElement.setDescription(toscaInputEntry.getValue().getDescription());
176                 clElement.setOrderedState(ControlLoopOrderedState.PASSIVE);
177                 elements.put(clElement.getId(), clElement);
178             }
179         }
180
181         List<ParticipantUpdates> participantUpdates = new ArrayList<>();
182         for (ControlLoopElement element : elements.values()) {
183             populateToscaNodeTemplateFragment(element, toscaServiceTemplate);
184             prepareParticipantUpdateForControlLoop(element, participantUpdates);
185         }
186         clUpdateMsg.setParticipantUpdatesList(participantUpdates);
187         return clUpdateMsg;
188     }
189
190     private static boolean checkIfNodeTemplateIsControlLoopElement(ToscaNodeTemplate nodeTemplate,
191             ToscaServiceTemplate toscaServiceTemplate) {
192         if (nodeTemplate.getType().contains(CONTROL_LOOP_ELEMENT)) {
193             return true;
194         } else {
195             var nodeType = toscaServiceTemplate.getNodeTypes().get(nodeTemplate.getType());
196             if (nodeType != null) {
197                 var derivedFrom = nodeType.getDerivedFrom();
198                 if (derivedFrom != null) {
199                     return derivedFrom.contains(CONTROL_LOOP_ELEMENT) ? true : false;
200                 }
201             }
202         }
203         return false;
204     }
205
206     private static void populateToscaNodeTemplateFragment(ControlLoopElement clElement,
207             ToscaServiceTemplate toscaServiceTemplate) {
208         ToscaNodeTemplate toscaNodeTemplate = toscaServiceTemplate
209             .getToscaTopologyTemplate().getNodeTemplates().get(clElement.getDefinition().getName());
210         // If the ControlLoopElement has policy_type_id or policy_id, identify it as a PolicyControlLoopElement
211         // and pass respective PolicyTypes or Policies as part of toscaServiceTemplateFragment
212         if ((toscaNodeTemplate.getProperties().get(POLICY_TYPE_ID) != null)
213                 || (toscaNodeTemplate.getProperties().get(POLICY_ID) != null)) {
214             // ControlLoopElement for policy framework, send policies and policyTypes to participants
215             if ((toscaServiceTemplate.getPolicyTypes() != null)
216                     || (toscaServiceTemplate.getToscaTopologyTemplate().getPolicies() != null)) {
217                 ToscaServiceTemplate toscaServiceTemplateFragment = new ToscaServiceTemplate();
218                 toscaServiceTemplateFragment.setPolicyTypes(toscaServiceTemplate.getPolicyTypes());
219
220                 ToscaTopologyTemplate toscaTopologyTemplate = new ToscaTopologyTemplate();
221                 toscaTopologyTemplate.setPolicies(toscaServiceTemplate.getToscaTopologyTemplate().getPolicies());
222                 toscaServiceTemplateFragment.setToscaTopologyTemplate(toscaTopologyTemplate);
223
224                 toscaServiceTemplateFragment.setDataTypes(toscaServiceTemplate.getDataTypes());
225
226                 clElement.setToscaServiceTemplateFragment(toscaServiceTemplateFragment);
227             }
228         }
229     }
230
231     private static void prepareParticipantUpdateForControlLoop(ControlLoopElement clElement,
232         List<ParticipantUpdates> participantUpdates) {
233         if (participantUpdates.isEmpty()) {
234             participantUpdates.add(getControlLoopElementList(clElement));
235         } else {
236             boolean participantExists = false;
237             for (ParticipantUpdates participantUpdate : participantUpdates) {
238                 if (participantUpdate.getParticipantId().equals(clElement.getParticipantId())) {
239                     participantUpdate.getControlLoopElementList().add(clElement);
240                     participantExists = true;
241                 }
242             }
243             if (!participantExists) {
244                 participantUpdates.add(getControlLoopElementList(clElement));
245             }
246         }
247     }
248
249     private static ParticipantUpdates getControlLoopElementList(ControlLoopElement clElement) {
250         ParticipantUpdates participantUpdate = new ParticipantUpdates();
251         List<ControlLoopElement> controlLoopElementList = new ArrayList<>();
252         participantUpdate.setParticipantId(clElement.getParticipantId());
253         controlLoopElementList.add(clElement);
254         participantUpdate.setControlLoopElementList(controlLoopElementList);
255         return participantUpdate;
256     }
257
258     /**
259      * Method to create participantUpdateMsg.
260      *
261      * @return ParticipantUpdate message
262      */
263     public static ParticipantUpdate createParticipantUpdateMsg() {
264         final ParticipantUpdate participantUpdateMsg = new ParticipantUpdate();
265         ToscaConceptIdentifier participantId = new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0");
266         ToscaConceptIdentifier participantType = new ToscaConceptIdentifier(
267                 "org.onap.policy.controlloop.PolicyControlLoopParticipant", "2.3.1");
268
269         participantUpdateMsg.setParticipantId(participantId);
270         participantUpdateMsg.setTimestamp(Instant.now());
271         participantUpdateMsg.setParticipantType(participantType);
272         participantUpdateMsg.setTimestamp(Instant.ofEpochMilli(3000));
273         participantUpdateMsg.setMessageId(UUID.randomUUID());
274
275         ToscaServiceTemplate toscaServiceTemplate = testControlLoopRead();
276         // Add policies to the toscaServiceTemplate
277         TestListenerUtils.addPoliciesToToscaServiceTemplate(toscaServiceTemplate);
278
279         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
280         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
281             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
282             if (checkIfNodeTemplateIsControlLoopElement(toscaInputEntry.getValue(), toscaServiceTemplate)) {
283                 ToscaConceptIdentifier clParticipantType;
284                 try {
285                     clParticipantType = CODER.decode(
286                             toscaInputEntry.getValue().getProperties().get("participantType").toString(),
287                             ToscaConceptIdentifier.class);
288                 } catch (CoderException e) {
289                     throw new RuntimeException("cannot get ParticipantType from toscaNodeTemplate", e);
290                 }
291                 prepareParticipantDefinitionUpdate(clParticipantType, toscaInputEntry.getKey(),
292                     toscaInputEntry.getValue(), participantDefinitionUpdates);
293             }
294         }
295
296         participantUpdateMsg.setParticipantDefinitionUpdates(participantDefinitionUpdates);
297         return participantUpdateMsg;
298     }
299
300     private static void prepareParticipantDefinitionUpdate(ToscaConceptIdentifier clParticipantType, String entryKey,
301         ToscaNodeTemplate entryValue, List<ParticipantDefinition> participantDefinitionUpdates) {
302
303         var clDefinition = new ControlLoopElementDefinition();
304         clDefinition.setClElementDefinitionId(new ToscaConceptIdentifier(
305             entryKey, entryValue.getVersion()));
306         clDefinition.setControlLoopElementToscaNodeTemplate(entryValue);
307         List<ControlLoopElementDefinition> controlLoopElementDefinitionList = new ArrayList<>();
308
309         if (participantDefinitionUpdates.isEmpty()) {
310             participantDefinitionUpdates.add(getParticipantDefinition(clDefinition, clParticipantType,
311                 controlLoopElementDefinitionList));
312         } else {
313             boolean participantExists = false;
314             for (ParticipantDefinition participantDefinitionUpdate : participantDefinitionUpdates) {
315                 if (participantDefinitionUpdate.getParticipantType().equals(clParticipantType)) {
316                     participantDefinitionUpdate.getControlLoopElementDefinitionList().add(clDefinition);
317                     participantExists = true;
318                 }
319             }
320             if (!participantExists) {
321                 participantDefinitionUpdates.add(getParticipantDefinition(clDefinition, clParticipantType,
322                     controlLoopElementDefinitionList));
323             }
324         }
325     }
326
327     private static ParticipantDefinition getParticipantDefinition(ControlLoopElementDefinition clDefinition,
328         ToscaConceptIdentifier clParticipantType,
329         List<ControlLoopElementDefinition> controlLoopElementDefinitionList) {
330         ParticipantDefinition participantDefinition = new ParticipantDefinition();
331         participantDefinition.setParticipantType(clParticipantType);
332         controlLoopElementDefinitionList.add(clDefinition);
333         participantDefinition.setControlLoopElementDefinitionList(controlLoopElementDefinitionList);
334         return participantDefinition;
335     }
336
337     /**
338      * Method to create ControlLoopUpdate using the arguments passed.
339      *
340      * @param jsonFilePath the path of the controlloop content
341      *
342      * @return ControlLoopUpdate message
343      * @throws CoderException exception while reading the file to object
344      */
345     public static ControlLoopUpdate createParticipantClUpdateMsgFromJson(String jsonFilePath) throws CoderException {
346         ControlLoopUpdate controlLoopUpdateMsg = CODER.decode(new File(jsonFilePath), ControlLoopUpdate.class);
347         return controlLoopUpdateMsg;
348     }
349
350     private static ToscaServiceTemplate testControlLoopRead() {
351         Set<String> controlLoopDirectoryContents =
352                 ResourceUtils.getDirectoryContents("src/test/resources/utils/servicetemplates");
353
354         boolean atLeastOneControlLoopTested = false;
355         ToscaServiceTemplate toscaServiceTemplate = null;
356
357         for (String controlLoopFilePath : controlLoopDirectoryContents) {
358             if (!controlLoopFilePath.endsWith(".yaml")) {
359                 continue;
360             }
361             atLeastOneControlLoopTested = true;
362             toscaServiceTemplate = testControlLoopYamlSerialization(controlLoopFilePath);
363         }
364
365         // Add policy_types to the toscaServiceTemplate
366         addPolicyTypesToToscaServiceTemplate(toscaServiceTemplate);
367
368         assertTrue(atLeastOneControlLoopTested);
369         return toscaServiceTemplate;
370     }
371
372     private static void addPolicyTypesToToscaServiceTemplate(
373             ToscaServiceTemplate toscaServiceTemplate) {
374         Set<String> policyTypeDirectoryContents = ResourceUtils.getDirectoryContents("policytypes");
375
376         for (String policyTypeFilePath : policyTypeDirectoryContents) {
377             String policyTypeString = ResourceUtils.getResourceAsString(policyTypeFilePath);
378
379             ToscaServiceTemplate foundPolicyTypeSt =
380                     yamlTranslator.fromYaml(policyTypeString, ToscaServiceTemplate.class);
381
382             toscaServiceTemplate.setDerivedFrom(foundPolicyTypeSt.getDerivedFrom());
383             toscaServiceTemplate.setDescription(foundPolicyTypeSt.getDescription());
384             toscaServiceTemplate.setMetadata(foundPolicyTypeSt.getMetadata());
385             toscaServiceTemplate.setName(foundPolicyTypeSt.getName());
386             toscaServiceTemplate.setToscaDefinitionsVersion(foundPolicyTypeSt.getToscaDefinitionsVersion());
387             toscaServiceTemplate.setVersion(foundPolicyTypeSt.getVersion());
388
389             if (foundPolicyTypeSt.getDataTypes() != null) {
390                 if (toscaServiceTemplate.getDataTypes() == null) {
391                     toscaServiceTemplate.setDataTypes(foundPolicyTypeSt.getDataTypes());
392                 } else {
393                     toscaServiceTemplate.getDataTypes().putAll(foundPolicyTypeSt.getDataTypes());
394                 }
395             }
396
397             if (toscaServiceTemplate.getPolicyTypes() == null) {
398                 toscaServiceTemplate.setPolicyTypes(foundPolicyTypeSt.getPolicyTypes());
399             } else {
400                 toscaServiceTemplate.getPolicyTypes().putAll(foundPolicyTypeSt.getPolicyTypes());
401             }
402         }
403     }
404
405     /**
406      * Method to add polcies to the toscaServiceTemplate.
407      *
408      * @param toscaServiceTemplate to add policies
409      */
410     public static void addPoliciesToToscaServiceTemplate(ToscaServiceTemplate toscaServiceTemplate) {
411         Set<String> policiesDirectoryContents = ResourceUtils.getDirectoryContents("policies");
412
413         for (String policiesFilePath : policiesDirectoryContents) {
414             String policiesString = ResourceUtils.getResourceAsString(policiesFilePath);
415
416             ToscaServiceTemplate foundPoliciesSt =
417                     yamlTranslator.fromYaml(policiesString, ToscaServiceTemplate.class);
418             toscaServiceTemplate.getToscaTopologyTemplate().setPolicies(
419                     foundPoliciesSt.getToscaTopologyTemplate().getPolicies());
420         }
421     }
422
423     private static ToscaServiceTemplate testControlLoopYamlSerialization(String controlLoopFilePath) {
424         try {
425             String controlLoopString = ResourceUtils.getResourceAsString(controlLoopFilePath);
426             if (controlLoopString == null) {
427                 throw new FileNotFoundException(controlLoopFilePath);
428             }
429
430             ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml(
431                     controlLoopString, ToscaServiceTemplate.class);
432             return serviceTemplate;
433         } catch (FileNotFoundException e) {
434             LOGGER.error("cannot find YAML file", controlLoopFilePath);
435             throw new IllegalArgumentException(e);
436         }
437     }
438 }