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