a33fa0a589124adacf0129b7ed08446f19482ffe
[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 (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
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 void populateToscaNodeTemplateFragment(ControlLoopElement clElement,
191             ToscaServiceTemplate toscaServiceTemplate) {
192         ToscaNodeTemplate toscaNodeTemplate = toscaServiceTemplate
193             .getToscaTopologyTemplate().getNodeTemplates().get(clElement.getDefinition().getName());
194         // If the ControlLoopElement has policy_type_id or policy_id, identify it as a PolicyControlLoopElement
195         // and pass respective PolicyTypes or Policies as part of toscaServiceTemplateFragment
196         if ((toscaNodeTemplate.getProperties().get(POLICY_TYPE_ID) != null)
197                 || (toscaNodeTemplate.getProperties().get(POLICY_ID) != null)) {
198             // ControlLoopElement for policy framework, send policies and policyTypes to participants
199             if ((toscaServiceTemplate.getPolicyTypes() != null)
200                     || (toscaServiceTemplate.getToscaTopologyTemplate().getPolicies() != null)) {
201                 ToscaServiceTemplate toscaServiceTemplateFragment = new ToscaServiceTemplate();
202                 toscaServiceTemplateFragment.setPolicyTypes(toscaServiceTemplate.getPolicyTypes());
203
204                 ToscaTopologyTemplate toscaTopologyTemplate = new ToscaTopologyTemplate();
205                 toscaTopologyTemplate.setPolicies(toscaServiceTemplate.getToscaTopologyTemplate().getPolicies());
206                 toscaServiceTemplateFragment.setToscaTopologyTemplate(toscaTopologyTemplate);
207
208                 toscaServiceTemplateFragment.setDataTypes(toscaServiceTemplate.getDataTypes());
209
210                 clElement.setToscaServiceTemplateFragment(toscaServiceTemplateFragment);
211             }
212         }
213     }
214
215     private static void prepareParticipantUpdateForControlLoop(ControlLoopElement clElement,
216         List<ParticipantUpdates> participantUpdates) {
217         if (participantUpdates.isEmpty()) {
218             participantUpdates.add(getControlLoopElementList(clElement));
219         } else {
220             boolean participantExists = false;
221             for (ParticipantUpdates participantUpdate : participantUpdates) {
222                 if (participantUpdate.getParticipantId().equals(clElement.getParticipantId())) {
223                     participantUpdate.getControlLoopElementList().add(clElement);
224                     participantExists = true;
225                 }
226             }
227             if (!participantExists) {
228                 participantUpdates.add(getControlLoopElementList(clElement));
229             }
230         }
231     }
232
233     private static ParticipantUpdates getControlLoopElementList(ControlLoopElement clElement) {
234         ParticipantUpdates participantUpdate = new ParticipantUpdates();
235         List<ControlLoopElement> controlLoopElementList = new ArrayList<>();
236         participantUpdate.setParticipantId(clElement.getParticipantId());
237         controlLoopElementList.add(clElement);
238         participantUpdate.setControlLoopElementList(controlLoopElementList);
239         return participantUpdate;
240     }
241
242     /**
243      * Method to create participantUpdateMsg.
244      *
245      * @return ParticipantUpdate message
246      */
247     public static ParticipantUpdate createParticipantUpdateMsg() {
248         final ParticipantUpdate participantUpdateMsg = new ParticipantUpdate();
249         ToscaConceptIdentifier participantId = new ToscaConceptIdentifier("org.onap.PM_Policy", "1.0.0");
250         ToscaConceptIdentifier participantType = new ToscaConceptIdentifier(
251                 "org.onap.policy.controlloop.PolicyControlLoopParticipant", "2.3.1");
252
253         participantUpdateMsg.setParticipantId(participantId);
254         participantUpdateMsg.setTimestamp(Instant.now());
255         participantUpdateMsg.setParticipantType(participantType);
256         participantUpdateMsg.setTimestamp(Instant.ofEpochMilli(3000));
257         participantUpdateMsg.setMessageId(UUID.randomUUID());
258
259         ToscaServiceTemplate toscaServiceTemplate = testControlLoopRead();
260         // Add policies to the toscaServiceTemplate
261         TestListenerUtils.addPoliciesToToscaServiceTemplate(toscaServiceTemplate);
262
263         List<ParticipantDefinition> participantDefinitionUpdates = new ArrayList<>();
264         for (Map.Entry<String, ToscaNodeTemplate> toscaInputEntry :
265             toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates().entrySet()) {
266             if (toscaInputEntry.getValue().getType().contains(CONTROL_LOOP_ELEMENT)) {
267                 ToscaConceptIdentifier clParticipantType;
268                 try {
269                     clParticipantType = CODER.decode(
270                             toscaInputEntry.getValue().getProperties().get("participantType").toString(),
271                             ToscaConceptIdentifier.class);
272                 } catch (CoderException e) {
273                     throw new RuntimeException("cannot get ParticipantType from toscaNodeTemplate", e);
274                 }
275                 prepareParticipantDefinitionUpdate(clParticipantType, toscaInputEntry.getKey(),
276                     toscaInputEntry.getValue(), participantDefinitionUpdates);
277             }
278         }
279
280         participantUpdateMsg.setParticipantDefinitionUpdates(participantDefinitionUpdates);
281         return participantUpdateMsg;
282     }
283
284     private static void prepareParticipantDefinitionUpdate(ToscaConceptIdentifier clParticipantType, String entryKey,
285         ToscaNodeTemplate entryValue, List<ParticipantDefinition> participantDefinitionUpdates) {
286
287         var clDefinition = new ControlLoopElementDefinition();
288         clDefinition.setClElementDefinitionId(new ToscaConceptIdentifier(
289             entryKey, entryValue.getVersion()));
290         clDefinition.setControlLoopElementToscaNodeTemplate(entryValue);
291         List<ControlLoopElementDefinition> controlLoopElementDefinitionList = new ArrayList<>();
292
293         if (participantDefinitionUpdates.isEmpty()) {
294             participantDefinitionUpdates.add(getParticipantDefinition(clDefinition, clParticipantType,
295                 controlLoopElementDefinitionList));
296         } else {
297             boolean participantExists = false;
298             for (ParticipantDefinition participantDefinitionUpdate : participantDefinitionUpdates) {
299                 if (participantDefinitionUpdate.getParticipantType().equals(clParticipantType)) {
300                     participantDefinitionUpdate.getControlLoopElementDefinitionList().add(clDefinition);
301                     participantExists = true;
302                 }
303             }
304             if (!participantExists) {
305                 participantDefinitionUpdates.add(getParticipantDefinition(clDefinition, clParticipantType,
306                     controlLoopElementDefinitionList));
307             }
308         }
309     }
310
311     private static ParticipantDefinition getParticipantDefinition(ControlLoopElementDefinition clDefinition,
312         ToscaConceptIdentifier clParticipantType,
313         List<ControlLoopElementDefinition> controlLoopElementDefinitionList) {
314         ParticipantDefinition participantDefinition = new ParticipantDefinition();
315         participantDefinition.setParticipantType(clParticipantType);
316         controlLoopElementDefinitionList.add(clDefinition);
317         participantDefinition.setControlLoopElementDefinitionList(controlLoopElementDefinitionList);
318         return participantDefinition;
319     }
320
321     /**
322      * Method to create ControlLoopUpdate using the arguments passed.
323      *
324      * @param jsonFilePath the path of the controlloop content
325      *
326      * @return ControlLoopUpdate message
327      * @throws CoderException exception while reading the file to object
328      */
329     public static ControlLoopUpdate createParticipantClUpdateMsgFromJson(String jsonFilePath) throws CoderException {
330         ControlLoopUpdate controlLoopUpdateMsg = CODER.decode(new File(jsonFilePath), ControlLoopUpdate.class);
331         return controlLoopUpdateMsg;
332     }
333
334     private static ToscaServiceTemplate testControlLoopRead() {
335         Set<String> controlLoopDirectoryContents =
336                 ResourceUtils.getDirectoryContents("src/test/resources/utils/servicetemplates");
337
338         boolean atLeastOneControlLoopTested = false;
339         ToscaServiceTemplate toscaServiceTemplate = null;
340
341         for (String controlLoopFilePath : controlLoopDirectoryContents) {
342             if (!controlLoopFilePath.endsWith(".yaml")) {
343                 continue;
344             }
345             atLeastOneControlLoopTested = true;
346             toscaServiceTemplate = testControlLoopYamlSerialization(controlLoopFilePath);
347         }
348
349         // Add policy_types to the toscaServiceTemplate
350         addPolicyTypesToToscaServiceTemplate(toscaServiceTemplate);
351
352         assertTrue(atLeastOneControlLoopTested);
353         return toscaServiceTemplate;
354     }
355
356     private static void addPolicyTypesToToscaServiceTemplate(
357             ToscaServiceTemplate toscaServiceTemplate) {
358         Set<String> policyTypeDirectoryContents = ResourceUtils.getDirectoryContents("policytypes");
359
360         for (String policyTypeFilePath : policyTypeDirectoryContents) {
361             String policyTypeString = ResourceUtils.getResourceAsString(policyTypeFilePath);
362
363             ToscaServiceTemplate foundPolicyTypeSt =
364                     yamlTranslator.fromYaml(policyTypeString, ToscaServiceTemplate.class);
365
366             toscaServiceTemplate.setDerivedFrom(foundPolicyTypeSt.getDerivedFrom());
367             toscaServiceTemplate.setDescription(foundPolicyTypeSt.getDescription());
368             toscaServiceTemplate.setMetadata(foundPolicyTypeSt.getMetadata());
369             toscaServiceTemplate.setName(foundPolicyTypeSt.getName());
370             toscaServiceTemplate.setToscaDefinitionsVersion(foundPolicyTypeSt.getToscaDefinitionsVersion());
371             toscaServiceTemplate.setVersion(foundPolicyTypeSt.getVersion());
372
373             if (foundPolicyTypeSt.getDataTypes() != null) {
374                 if (toscaServiceTemplate.getDataTypes() == null) {
375                     toscaServiceTemplate.setDataTypes(foundPolicyTypeSt.getDataTypes());
376                 } else {
377                     toscaServiceTemplate.getDataTypes().putAll(foundPolicyTypeSt.getDataTypes());
378                 }
379             }
380
381             if (toscaServiceTemplate.getPolicyTypes() == null) {
382                 toscaServiceTemplate.setPolicyTypes(foundPolicyTypeSt.getPolicyTypes());
383             } else {
384                 toscaServiceTemplate.getPolicyTypes().putAll(foundPolicyTypeSt.getPolicyTypes());
385             }
386         }
387     }
388
389     /**
390      * Method to add polcies to the toscaServiceTemplate.
391      *
392      * @param toscaServiceTemplate to add policies
393      */
394     public static void addPoliciesToToscaServiceTemplate(ToscaServiceTemplate toscaServiceTemplate) {
395         Set<String> policiesDirectoryContents = ResourceUtils.getDirectoryContents("policies");
396
397         for (String policiesFilePath : policiesDirectoryContents) {
398             String policiesString = ResourceUtils.getResourceAsString(policiesFilePath);
399
400             ToscaServiceTemplate foundPoliciesSt =
401                     yamlTranslator.fromYaml(policiesString, ToscaServiceTemplate.class);
402             toscaServiceTemplate.getToscaTopologyTemplate().setPolicies(
403                     foundPoliciesSt.getToscaTopologyTemplate().getPolicies());
404         }
405     }
406
407     private static ToscaServiceTemplate testControlLoopYamlSerialization(String controlLoopFilePath) {
408         try {
409             String controlLoopString = ResourceUtils.getResourceAsString(controlLoopFilePath);
410             if (controlLoopString == null) {
411                 throw new FileNotFoundException(controlLoopFilePath);
412             }
413
414             ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml(
415                     controlLoopString, ToscaServiceTemplate.class);
416             return serviceTemplate;
417         } catch (FileNotFoundException e) {
418             LOGGER.error("cannot find YAML file", controlLoopFilePath);
419             throw new IllegalArgumentException(e);
420         }
421     }
422 }