ab80bc2779b066bc69b3822a4670f1149f95293e
[policy/clamp.git] /
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2021-2024 Nordix Foundation.
4  * ================================================================================
5  * Modifications Copyright (C) 2021 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  *
19  * SPDX-License-Identifier: Apache-2.0
20  * ============LICENSE_END=========================================================
21  */
22
23 package org.onap.policy.clamp.models.acm.persistence.provider;
24
25 import jakarta.ws.rs.core.Response;
26 import jakarta.ws.rs.core.Response.Status;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Optional;
30 import java.util.UUID;
31 import lombok.AllArgsConstructor;
32 import lombok.NonNull;
33 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
34 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement;
35 import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionInfo;
36 import org.onap.policy.clamp.models.acm.concepts.DeployState;
37 import org.onap.policy.clamp.models.acm.concepts.LockState;
38 import org.onap.policy.clamp.models.acm.concepts.SubState;
39 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationComposition;
40 import org.onap.policy.clamp.models.acm.persistence.concepts.JpaAutomationCompositionElement;
41 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionElementRepository;
42 import org.onap.policy.clamp.models.acm.persistence.repository.AutomationCompositionRepository;
43 import org.onap.policy.clamp.models.acm.utils.AcmUtils;
44 import org.onap.policy.common.parameters.BeanValidationResult;
45 import org.onap.policy.common.parameters.ValidationStatus;
46 import org.onap.policy.models.base.PfModelRuntimeException;
47 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
48 import org.springframework.data.domain.Example;
49 import org.springframework.stereotype.Service;
50 import org.springframework.transaction.annotation.Isolation;
51 import org.springframework.transaction.annotation.Transactional;
52
53 /**
54  * This class provides information on automation composition concepts in the database to callers.
55  */
56 @Service
57 @Transactional
58 @AllArgsConstructor
59 public class AutomationCompositionProvider {
60
61     private final AutomationCompositionRepository automationCompositionRepository;
62     private final AutomationCompositionElementRepository acElementRepository;
63
64     /**
65      * Get automation composition.
66      *
67      * @param instanceId the ID of the automation composition to get
68      * @return the automation composition found
69      */
70     @Transactional(readOnly = true)
71     public AutomationComposition getAutomationComposition(final UUID instanceId) {
72         var result = automationCompositionRepository.findById(instanceId.toString());
73         if (result.isEmpty()) {
74             throw new PfModelRuntimeException(Status.NOT_FOUND, "AutomationComposition not found");
75         }
76         return result.get().toAuthorative();
77     }
78
79     /**
80      * Find automation composition.
81      *
82      * @param instanceId the ID of the automation composition to get
83      * @return the automation composition found
84      */
85     @Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
86     public Optional<AutomationComposition> findAutomationComposition(final UUID instanceId) {
87         var result = automationCompositionRepository.findById(instanceId.toString());
88         return result.stream().map(JpaAutomationComposition::toAuthorative).findFirst();
89     }
90
91     /**
92      * Find automation composition by automationCompositionId.
93      *
94      * @param automationCompositionId the ID of the automation composition to get
95      * @return the automation composition found
96      */
97     @Transactional(readOnly = true)
98     public Optional<AutomationComposition> findAutomationComposition(
99             final ToscaConceptIdentifier automationCompositionId) {
100         return automationCompositionRepository
101                 .findOne(createExample(null, automationCompositionId.getName(), automationCompositionId.getVersion()))
102                 .map(JpaAutomationComposition::toAuthorative);
103     }
104
105     /**
106      * Create automation composition.
107      *
108      * @param automationComposition the automation composition to create
109      * @return the create automation composition
110      */
111     public AutomationComposition createAutomationComposition(final AutomationComposition automationComposition) {
112         automationComposition.setInstanceId(UUID.randomUUID());
113         AcmUtils.setCascadedState(automationComposition, DeployState.UNDEPLOYED, LockState.NONE);
114         var result = automationCompositionRepository.save(ProviderUtils.getJpaAndValidate(automationComposition,
115                 JpaAutomationComposition::new, "automation composition"));
116
117         // Return the saved automation composition
118         return result.toAuthorative();
119     }
120
121
122     /**
123      * Update automation composition state.
124      *
125      * @param acSource the automation composition to update
126      * @return the updated automation composition
127      */
128     public AutomationComposition updateAcState(final AutomationComposition acSource) {
129         var automationComposition = automationCompositionRepository
130                 .getReferenceById(acSource.getInstanceId().toString());
131         automationComposition.fromAuthorativeBase(acSource);
132         var result = automationCompositionRepository.save(automationComposition);
133         automationCompositionRepository.flush();
134         // Return the saved automation composition
135         return result.toAuthorative();
136     }
137
138     /**
139      * Update automation composition.
140      *
141      * @param automationComposition the automation composition to update
142      * @return the updated automation composition
143      */
144     public AutomationComposition updateAutomationComposition(
145             @NonNull final AutomationComposition automationComposition) {
146         var result = automationCompositionRepository.save(ProviderUtils.getJpaAndValidate(automationComposition,
147                 JpaAutomationComposition::new, "automation composition"));
148         automationCompositionRepository.flush();
149         // Return the saved automation composition
150         return result.toAuthorative();
151     }
152
153     /**
154      * Get all automation compositions by compositionId.
155      *
156      * @param compositionId the compositionId of the automation composition definition
157      * @return all automation compositions found
158      */
159     @Transactional(readOnly = true)
160     public List<AutomationComposition> getAcInstancesByCompositionId(UUID compositionId) {
161         return ProviderUtils
162                 .asEntityList(automationCompositionRepository.findByCompositionId(compositionId.toString()));
163     }
164
165     /**
166      * Get all automation compositions in transition..
167      *
168      * @return all automation compositions found
169      */
170     @Transactional(readOnly = true)
171     public List<AutomationComposition> getAcInstancesInTransition() {
172         var jpaList = automationCompositionRepository.findByDeployStateIn(List.of(DeployState.DEPLOYING,
173             DeployState.UNDEPLOYING, DeployState.DELETING, DeployState.UPDATING, DeployState.MIGRATING));
174         jpaList.addAll(automationCompositionRepository.findByLockStateIn(
175             List.of(LockState.LOCKING, LockState.UNLOCKING)));
176         jpaList.addAll(automationCompositionRepository.findBySubStateIn(
177                 List.of(SubState.PREPARING, SubState.MIGRATION_PRECHECKING, SubState.REVIEWING)));
178         return ProviderUtils.asEntityList(jpaList);
179     }
180
181     /**
182      * Get automation compositions.
183      *
184      * @param name the name of the automation composition to get, null to get all automation compositions
185      * @param version the version of the automation composition to get, null to get all automation compositions
186      * @return the automation compositions found
187      */
188     @Transactional(readOnly = true)
189     public List<AutomationComposition> getAutomationCompositions(final UUID compositionId, final String name,
190             final String version) {
191
192         return ProviderUtils
193                 .asEntityList(automationCompositionRepository.findAll(createExample(compositionId, name, version)));
194     }
195
196     private Example<JpaAutomationComposition> createExample(final UUID compositionId, final String name,
197             final String version) {
198         var example = new JpaAutomationComposition();
199         example.setCompositionId(compositionId != null ? compositionId.toString() : null);
200         example.setName(name);
201         example.setVersion(version);
202         example.setInstanceId(null);
203         example.setElements(null);
204         example.setDeployState(null);
205         example.setLockState(null);
206
207         return Example.of(example);
208     }
209
210     /**
211      * Delete a automation composition.
212      *
213      * @param instanceId the ID of the automation composition to get
214      * @return the automation composition deleted
215      */
216     public AutomationComposition deleteAutomationComposition(@NonNull final UUID instanceId) {
217         var jpaDeleteAutomationComposition = automationCompositionRepository.findById(instanceId.toString());
218         if (jpaDeleteAutomationComposition.isEmpty()) {
219             var errorMessage = "delete of automation composition \"" + instanceId
220                     + "\" failed, automation composition does not exist";
221             throw new PfModelRuntimeException(Response.Status.NOT_FOUND, errorMessage);
222         }
223
224         automationCompositionRepository.deleteById(instanceId.toString());
225
226         return jpaDeleteAutomationComposition.get().toAuthorative();
227     }
228
229     /**
230      * Upgrade States.
231      *
232      * @param automationCompositionInfoList list of AutomationCompositionInfo
233      */
234     public void upgradeStates(@NonNull final List<AutomationCompositionInfo> automationCompositionInfoList) {
235         if (automationCompositionInfoList.isEmpty()) {
236             return;
237         }
238         List<JpaAutomationCompositionElement> jpaList = new ArrayList<>();
239         for (var acInstance : automationCompositionInfoList) {
240             for (var element : acInstance.getElements()) {
241                 var jpa = acElementRepository.getReferenceById(element.getAutomationCompositionElementId().toString());
242                 jpa.setUseState(element.getUseState());
243                 jpa.setOperationalState(element.getOperationalState());
244                 jpa.setOutProperties(element.getOutProperties());
245                 jpaList.add(jpa);
246             }
247         }
248         acElementRepository.saveAll(jpaList);
249     }
250
251     /**
252      * Update AutomationCompositionElement.
253      *
254      * @param element the AutomationCompositionElement
255      */
256     public void updateAutomationCompositionElement(@NonNull final AutomationCompositionElement element) {
257         var jpaAcElement = acElementRepository.getReferenceById(element.getId().toString());
258         jpaAcElement.setMessage(element.getMessage());
259         jpaAcElement.setOutProperties(element.getOutProperties());
260         jpaAcElement.setOperationalState(element.getOperationalState());
261         jpaAcElement.setUseState(element.getUseState());
262         jpaAcElement.setDeployState(element.getDeployState());
263         jpaAcElement.setLockState(element.getLockState());
264         jpaAcElement.setSubState(element.getSubState());
265         jpaAcElement.setStage(element.getStage());
266         jpaAcElement.setRestarting(element.getRestarting());
267
268         ProviderUtils.validate(element, jpaAcElement, "AutomationCompositionElement");
269         acElementRepository.save(jpaAcElement);
270     }
271
272     /**
273      * Delete AutomationCompositionElement.
274      *
275      * @param elementId the AutomationCompositionElement Id
276      */
277     public void deleteAutomationCompositionElement(@NonNull final UUID elementId) {
278         acElementRepository.deleteById(elementId.toString());
279     }
280
281     /**
282      * Validate ElementIds.
283      *
284      * @param automationComposition the AutomationComposition
285      * @return the BeanValidationResult
286      */
287     public BeanValidationResult validateElementIds(final AutomationComposition automationComposition) {
288         var result = new BeanValidationResult(
289             "UUID elements " + automationComposition.getName(), automationComposition);
290
291         var ids = automationComposition
292             .getElements().values().stream().map(AutomationCompositionElement::getId).toList();
293         var elements = acElementRepository.findAllById(ids.stream().map(UUID::toString).toList());
294         if (automationComposition.getInstanceId() == null) {
295             for (var element : elements) {
296                 result.addResult(
297                     element.getDescription(), element.getElementId(), ValidationStatus.INVALID, "UUID already used");
298             }
299         } else {
300             var instanceId = automationComposition.getInstanceId().toString();
301             for (var element : elements) {
302                 if (!instanceId.equals(element.getInstanceId())) {
303                     result.addResult(
304                         element.getDescription(), element.getElementId(), ValidationStatus.INVALID,
305                         "UUID already used");
306                 }
307             }
308         }
309         return result;
310     }
311 }