55d7b0c1368b48f0b94b7742d591d3c553e20873
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2021-2022 Nordix Foundation.
4  * Modifications Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
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.clamp.acm.runtime.commissioning;
23
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.stream.Collectors;
30 import javax.ws.rs.core.Response.Status;
31 import org.apache.commons.collections4.CollectionUtils;
32 import org.apache.commons.collections4.MapUtils;
33 import org.apache.commons.lang3.StringUtils;
34 import org.onap.policy.clamp.acm.runtime.supervision.SupervisionHandler;
35 import org.onap.policy.clamp.models.acm.concepts.Participant;
36 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse;
37 import org.onap.policy.clamp.models.acm.persistence.provider.AutomationCompositionProvider;
38 import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider;
39 import org.onap.policy.clamp.models.acm.persistence.provider.ServiceTemplateProvider;
40 import org.onap.policy.common.utils.coder.Coder;
41 import org.onap.policy.common.utils.coder.CoderException;
42 import org.onap.policy.common.utils.coder.StandardCoder;
43 import org.onap.policy.models.base.PfModelException;
44 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
45 import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
46 import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter;
48 import org.springframework.stereotype.Service;
49 import org.springframework.transaction.annotation.Transactional;
50
51 /**
52  * This class provides the create, read and delete actions on Commissioning of automation composition concepts in the
53  * database to the callers.
54  */
55 @Service
56 @Transactional
57 public class CommissioningProvider {
58     public static final String AUTOMATION_COMPOSITION_NODE_TYPE = "org.onap.policy.clamp.acm.AutomationComposition";
59     private static final String HYPHEN = "-";
60
61     private final ServiceTemplateProvider serviceTemplateProvider;
62     private final AutomationCompositionProvider acProvider;
63     private static final Coder CODER = new StandardCoder();
64     private final ParticipantProvider participantProvider;
65     private final SupervisionHandler supervisionHandler;
66
67     /**
68      * Create a commissioning provider.
69      *
70      * @param serviceTemplateProvider the ServiceTemplate Provider
71      * @param acProvider the AutomationComposition Provider
72      * @param supervisionHandler the Supervision Handler
73      * @param participantProvider the Participant Provider
74      */
75     public CommissioningProvider(ServiceTemplateProvider serviceTemplateProvider,
76             AutomationCompositionProvider acProvider, SupervisionHandler supervisionHandler,
77             ParticipantProvider participantProvider) {
78         this.serviceTemplateProvider = serviceTemplateProvider;
79         this.acProvider = acProvider;
80         this.supervisionHandler = supervisionHandler;
81         this.participantProvider = participantProvider;
82     }
83
84     /**
85      * Create automation compositions from a service template.
86      *
87      * @param serviceTemplate the service template
88      * @return the result of the commissioning operation
89      * @throws PfModelException on creation errors
90      */
91     public CommissioningResponse createAutomationCompositionDefinitions(ToscaServiceTemplate serviceTemplate)
92             throws PfModelException {
93
94         if (verifyIfInstancePropertiesExists()) {
95             throw new PfModelException(Status.BAD_REQUEST,
96                     "Delete instances, to commission automation composition definitions");
97         }
98         serviceTemplate = serviceTemplateProvider.createServiceTemplate(serviceTemplate);
99         List<Participant> participantList = participantProvider.getParticipants();
100         if (!participantList.isEmpty()) {
101             supervisionHandler.handleSendCommissionMessage(serviceTemplate.getName(), serviceTemplate.getVersion());
102         }
103         var response = new CommissioningResponse();
104         // @formatter:off
105         response.setAffectedAutomationCompositionDefinitions(
106             serviceTemplate.getToscaTopologyTemplate().getNodeTemplates()
107                 .values()
108                 .stream()
109                 .map(template -> template.getKey().asIdentifier())
110                 .collect(Collectors.toList()));
111         // @formatter:on
112
113         return response;
114     }
115
116     /**
117      * Delete the automation composition definition with the given name and version.
118      *
119      * @param name the name of the automation composition definition to delete
120      * @param version the version of the automation composition to delete
121      * @return the result of the deletion
122      * @throws PfModelException on deletion errors
123      */
124     public CommissioningResponse deleteAutomationCompositionDefinition(String name, String version)
125             throws PfModelException {
126
127         if (verifyIfInstancePropertiesExists()) {
128             throw new PfModelException(Status.BAD_REQUEST,
129                     "Delete instances, to commission automation composition definitions");
130         }
131         List<Participant> participantList = participantProvider.getParticipants();
132         if (!participantList.isEmpty()) {
133             supervisionHandler.handleSendDeCommissionMessage();
134         }
135         serviceTemplateProvider.deleteServiceTemplate(name, version);
136         var response = new CommissioningResponse();
137         response.setAffectedAutomationCompositionDefinitions(List.of(new ToscaConceptIdentifier(name, version)));
138
139         return response;
140     }
141
142     /**
143      * Get automation composition node templates.
144      *
145      * @param acName the name of the automation composition, null for all
146      * @param acVersion the version of the automation composition, null for all
147      * @return list of automation composition node templates
148      * @throws PfModelException on errors getting automation composition definitions
149      */
150     @Transactional(readOnly = true)
151     public List<ToscaNodeTemplate> getAutomationCompositionDefinitions(String acName, String acVersion)
152             throws PfModelException {
153
154         // @formatter:off
155         ToscaTypedEntityFilter<ToscaNodeTemplate> nodeTemplateFilter = ToscaTypedEntityFilter
156                 .<ToscaNodeTemplate>builder()
157                 .name(acName)
158                 .version(acVersion)
159                 .type(AUTOMATION_COMPOSITION_NODE_TYPE)
160                 .build();
161         // @formatter:on
162
163         return acProvider.getFilteredNodeTemplates(nodeTemplateFilter);
164     }
165
166     /**
167      * Get the automation composition elements from a automation composition node template.
168      *
169      * @param automationCompositionNodeTemplate the automation composition node template
170      * @return a list of the automation composition element node templates in a automation composition node template
171      * @throws PfModelException on errors get automation composition element node templates
172      */
173     @Transactional(readOnly = true)
174     public List<ToscaNodeTemplate> getAutomationCompositionElementDefinitions(
175             ToscaNodeTemplate automationCompositionNodeTemplate) throws PfModelException {
176         if (!AUTOMATION_COMPOSITION_NODE_TYPE.equals(automationCompositionNodeTemplate.getType())) {
177             return Collections.emptyList();
178         }
179
180         if (MapUtils.isEmpty(automationCompositionNodeTemplate.getProperties())) {
181             return Collections.emptyList();
182         }
183
184         @SuppressWarnings("unchecked")
185         List<Map<String, String>> automationCompositionElements =
186                 (List<Map<String, String>>) automationCompositionNodeTemplate.getProperties().get("elements");
187
188         if (CollectionUtils.isEmpty(automationCompositionElements)) {
189             return Collections.emptyList();
190         }
191
192         List<ToscaNodeTemplate> automationCompositionElementList = new ArrayList<>();
193         // @formatter:off
194         automationCompositionElementList.addAll(
195                 automationCompositionElements
196                         .stream()
197                         .map(elementMap -> acProvider.getNodeTemplates(elementMap.get("name"),
198                                 elementMap.get("version")))
199                         .flatMap(List::stream)
200                         .collect(Collectors.toList())
201         );
202         // @formatter:on
203
204         return automationCompositionElementList;
205     }
206
207     /**
208      * Get the requested automation composition definitions.
209      *
210      * @param name the name of the definition to get, null for all definitions
211      * @param version the version of the definition to get, null for all definitions
212      * @return the automation composition definitions
213      * @throws PfModelException on errors getting automation composition definitions
214      */
215     @Transactional(readOnly = true)
216     public ToscaServiceTemplate getToscaServiceTemplate(String name, String version) throws PfModelException {
217         return serviceTemplateProvider.getToscaServiceTemplate(name, version);
218     }
219
220     /**
221      * Get All the requested automation composition definitions.
222      *
223      * @return the automation composition definitions
224      * @throws PfModelException on errors getting automation composition definitions
225      */
226     @Transactional(readOnly = true)
227     public List<ToscaServiceTemplate> getAllToscaServiceTemplate() throws PfModelException {
228         return serviceTemplateProvider.getAllServiceTemplates();
229     }
230
231     /**
232      * Get the tosca service template with only required sections.
233      *
234      * @param name the name of the template to get, null for all definitions
235      * @param version the version of the template to get, null for all definitions
236      * @param instanceName automation composition name
237      * @return the tosca service template
238      * @throws PfModelException on errors getting tosca service template
239      */
240     @Transactional(readOnly = true)
241     public String getToscaServiceTemplateReduced(
242             final String name, final String version, final String instanceName)
243             throws PfModelException {
244
245         var serviceTemplateList = serviceTemplateProvider.getServiceTemplateList(name, version);
246
247         List<ToscaServiceTemplate> filteredServiceTemplateList =
248                 filterToscaNodeTemplateInstance(serviceTemplateList, instanceName);
249
250         if (filteredServiceTemplateList.isEmpty()) {
251             throw new PfModelException(Status.BAD_REQUEST, "Invalid Service Template");
252         }
253
254         ToscaServiceTemplate fullTemplate = filteredServiceTemplateList.get(0);
255
256         var template = new HashMap<String, Object>();
257         template.put("tosca_definitions_version", fullTemplate.getToscaDefinitionsVersion());
258         template.put("data_types", fullTemplate.getDataTypes());
259         template.put("policy_types", fullTemplate.getPolicyTypes());
260         template.put("node_types", fullTemplate.getNodeTypes());
261         template.put("topology_template", fullTemplate.getToscaTopologyTemplate());
262
263         try {
264             return CODER.encode(template);
265
266         } catch (CoderException e) {
267             throw new PfModelException(Status.BAD_REQUEST, "Converion to Json Schema failed", e);
268         }
269     }
270
271     /**
272      * Filters service templates if is not an instantiation type.
273      *
274      * @param serviceTemplates tosca service template
275      * @param instanceName     automation composition name
276      * @return List of tosca service templates
277      */
278     private List<ToscaServiceTemplate> filterToscaNodeTemplateInstance(
279             List<ToscaServiceTemplate> serviceTemplates, String instanceName) {
280
281         List<ToscaServiceTemplate> toscaServiceTemplates = new ArrayList<>();
282
283         serviceTemplates.forEach(serviceTemplate -> {
284
285             Map<String, ToscaNodeTemplate> toscaNodeTemplates = new HashMap<>();
286
287             serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().forEach((key, nodeTemplate) -> {
288                 if (StringUtils.isNotEmpty(instanceName) && nodeTemplate.getName().contains(instanceName)) {
289                     toscaNodeTemplates.put(key, nodeTemplate);
290                 } else if (!nodeTemplate.getName().contains(HYPHEN)) {
291                     toscaNodeTemplates.put(key, nodeTemplate);
292                 }
293             });
294
295             serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().clear();
296             serviceTemplate.getToscaTopologyTemplate().setNodeTemplates(toscaNodeTemplates);
297
298             toscaServiceTemplates.add(serviceTemplate);
299         });
300
301         return toscaServiceTemplates;
302     }
303
304     /**
305      * Validates to see if there is any instance properties saved.
306      *
307      * @return true if exists instance properties
308      */
309     private boolean verifyIfInstancePropertiesExists() {
310         return acProvider.getAllNodeTemplates().stream()
311                 .anyMatch(nodeTemplate -> nodeTemplate.getKey().getName().contains(HYPHEN));
312
313     }
314 }