Improve code coverage
[nonrtric/plt/rappmanager.git] / rapp-manager-acm / src / test / java / com / oransc / rappmanager / acm / service / AcmDeployerTest.java
1 /*-
2  * ============LICENSE_START======================================================================
3  * Copyright (C) 2023 Nordix Foundation. All rights reserved.
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  * ============LICENSE_END========================================================================
17  */
18
19 package com.oransc.rappmanager.acm.service;
20
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertFalse;
23 import static org.junit.jupiter.api.Assertions.assertNull;
24 import static org.junit.jupiter.api.Assertions.assertTrue;
25 import static org.mockito.ArgumentMatchers.any;
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.times;
28 import static org.mockito.Mockito.verify;
29 import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
30 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
31 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
32
33 import com.fasterxml.jackson.core.JsonProcessingException;
34 import com.fasterxml.jackson.databind.ObjectMapper;
35 import com.oransc.rappmanager.acm.configuration.ACMConfiguration;
36 import com.oransc.rappmanager.models.cache.RappCacheService;
37 import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
38 import com.oransc.rappmanager.models.rapp.Rapp;
39 import com.oransc.rappmanager.models.rapp.RappEvent;
40 import com.oransc.rappmanager.models.rapp.RappResourceBuilder;
41 import com.oransc.rappmanager.models.rapp.RappResources;
42 import com.oransc.rappmanager.models.rapp.RappState;
43 import com.oransc.rappmanager.models.rappinstance.RappInstance;
44 import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
45 import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachineConfig;
46 import java.io.IOException;
47 import java.util.UUID;
48 import org.junit.jupiter.api.BeforeAll;
49 import org.junit.jupiter.api.BeforeEach;
50 import org.junit.jupiter.api.Test;
51 import org.junit.jupiter.api.TestInstance;
52 import org.onap.policy.clamp.models.acm.concepts.AutomationComposition;
53 import org.onap.policy.clamp.models.acm.concepts.DeployState;
54 import org.onap.policy.clamp.models.acm.concepts.LockState;
55 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.CommissioningResponse;
56 import org.onap.policy.clamp.models.acm.messages.rest.commissioning.PrimeOrder;
57 import org.onap.policy.clamp.models.acm.messages.rest.instantiation.InstantiationResponse;
58 import org.springframework.beans.factory.annotation.Autowired;
59 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
60 import org.springframework.boot.test.context.SpringBootTest;
61 import org.springframework.boot.test.mock.mockito.SpyBean;
62 import org.springframework.http.HttpMethod;
63 import org.springframework.http.HttpStatus;
64 import org.springframework.http.MediaType;
65 import org.springframework.test.web.client.ExpectedCount;
66 import org.springframework.test.web.client.MockRestServiceServer;
67 import org.springframework.web.client.RestTemplate;
68
69 @SpringBootTest(classes = {BeanTestConfiguration.class, ACMConfiguration.class, AcmDeployer.class,
70         RappCsarConfigurationHandler.class, RappCacheService.class, RappInstanceStateMachineConfig.class,
71         RappInstanceStateMachine.class})
72 @TestInstance(TestInstance.Lifecycle.PER_CLASS)
73 @AutoConfigureMockMvc
74 class AcmDeployerTest {
75
76     MockRestServiceServer mockServer;
77     @SpyBean
78     AcmDeployer acmDeployer;
79     @Autowired
80     RestTemplate restTemplate;
81     @Autowired
82     ACMConfiguration acmConfiguration;
83     @SpyBean
84     RappInstanceStateMachine rappInstanceStateMachine;
85     @Autowired
86     RappCsarConfigurationHandler rappCsarConfigurationHandler;
87
88     RappResourceBuilder rappResourceBuilder = new RappResourceBuilder();
89     private final String validRappFile = "valid-rapp-package.csar";
90     String validCsarFileLocation = "src/test/resources/";
91     ObjectMapper objectMapper = new ObjectMapper();
92     String URI_ACM_COMPOSITIONS, URI_ACM_COMPOSITION, URI_ACM_INSTANCES, URI_ACM_INSTANCE;
93
94     @BeforeAll
95     void initACMURI() {
96         URI_ACM_COMPOSITIONS = acmConfiguration.getBaseUrl() + "compositions";
97         URI_ACM_COMPOSITION = acmConfiguration.getBaseUrl() + "compositions/%s";
98         URI_ACM_INSTANCES = acmConfiguration.getBaseUrl() + "compositions/%s/instances";
99         URI_ACM_INSTANCE = acmConfiguration.getBaseUrl() + "compositions/%s/instances/%s";
100     }
101
102     @BeforeEach
103     public void init() {
104         mockServer = MockRestServiceServer.createServer(restTemplate);
105     }
106
107     @Test
108     void testCreateComposition() throws IOException {
109         RappResources rappResources = rappResourceBuilder.getResources();
110         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
111                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
112                             .rappResources(rappResources).build();
113
114         String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp);
115
116         CommissioningResponse commissioningResponseExpected = new CommissioningResponse();
117         commissioningResponseExpected.setCompositionId(UUID.randomUUID());
118         mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST))
119                 .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
120                                     .body(objectMapper.writeValueAsString(commissioningResponseExpected)));
121         CommissioningResponse commissioningResponseActual = acmDeployer.createComposition(compositionPayload);
122         mockServer.verify();
123         assertEquals(commissioningResponseActual.getCompositionId(), commissioningResponseExpected.getCompositionId());
124     }
125
126     @Test
127     void testCreateCompositionFailure() {
128         RappResources rappResources = rappResourceBuilder.getResources();
129         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
130                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
131                             .rappResources(rappResources).build();
132         String compositionPayload = rappCsarConfigurationHandler.getAcmCompositionPayload(rapp);
133         mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST))
134                 .andRespond(withStatus(HttpStatus.BAD_GATEWAY));
135         CommissioningResponse commissioningResponseActual = acmDeployer.createComposition(compositionPayload);
136         mockServer.verify();
137         assertNull(commissioningResponseActual);
138     }
139
140     @Test
141     void testCompositionPriming() {
142         UUID compositionId = UUID.randomUUID();
143         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
144                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED));
145
146         acmDeployer.primeACMComposition(compositionId, PrimeOrder.PRIME);
147         mockServer.verify();
148     }
149
150     @Test
151     void testDeployRappInstance() throws Exception {
152
153         UUID compositionId = UUID.randomUUID();
154         UUID rappId = UUID.randomUUID();
155         UUID instanceId = UUID.randomUUID();
156         Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId)
157                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
158         InstantiationResponse instantiationResponse = new InstantiationResponse();
159         instantiationResponse.setInstanceId(instanceId);
160         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCES, compositionId)))
161                 .andExpect(method(HttpMethod.POST)).andRespond(
162                         withStatus(HttpStatus.ACCEPTED).contentType(MediaType.APPLICATION_JSON)
163                                 .body(objectMapper.writeValueAsString(instantiationResponse)));
164         mockServer.expect(ExpectedCount.once(),
165                         requestTo(acmConfiguration.getBaseUrl() + "compositions/" + compositionId + "/instances/" + instanceId))
166                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED));
167         boolean rappDeployStateActual = acmDeployer.deployRappInstance(rapp, rappResourceBuilder.getRappInstance());
168         assertTrue(rappDeployStateActual);
169         mockServer.verify();
170     }
171
172     @Test
173     void testDeployRappInstanceFailure() throws Exception {
174         UUID compositionId = UUID.randomUUID();
175         UUID rappId = UUID.randomUUID();
176         UUID instanceId = UUID.randomUUID();
177         Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId)
178                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
179         InstantiationResponse instantiationResponse = new InstantiationResponse();
180         instantiationResponse.setInstanceId(instanceId);
181         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCES, compositionId)))
182                 .andExpect(method(HttpMethod.POST)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
183
184         boolean rappDeployStateActual = acmDeployer.deployRappInstance(rapp, rappResourceBuilder.getRappInstance());
185         mockServer.verify();
186         assertFalse(rappDeployStateActual);
187     }
188
189     @Test
190     void testUndeployRappInstance() throws JsonProcessingException {
191         UUID compositionId = UUID.randomUUID();
192         UUID rappId = UUID.randomUUID();
193         UUID instanceId = UUID.randomUUID();
194         Rapp rapp = Rapp.builder().rappId(rappId).name("").packageName(validRappFile).compositionId(compositionId)
195                             .state(RappState.PRIMED).build();
196
197         expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.DEPLOYED, LockState.LOCKED,
198                 ExpectedCount.once());
199
200         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId)))
201                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED));
202
203         expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.UNDEPLOYED, LockState.UNLOCKED,
204                 ExpectedCount.once());
205
206         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId)))
207                 .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.NO_CONTENT));
208
209         RappInstance rappInstance = rappResourceBuilder.getRappInstance();
210         rappInstance.getAcm().setAcmInstanceId(instanceId);
211         rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
212         boolean rappUndeployStateActual = acmDeployer.undeployRappInstance(rapp, rappInstance);
213         mockServer.verify();
214         assertTrue(rappUndeployStateActual);
215     }
216
217     @Test
218     void testUndeployRappInstanceFailure() throws JsonProcessingException {
219         UUID compositionId = UUID.randomUUID();
220         UUID rappId = UUID.randomUUID();
221         UUID instanceId = UUID.randomUUID();
222         Rapp rapp = Rapp.builder().name(rappId.toString()).packageName(validRappFile).compositionId(compositionId)
223                             .state(RappState.PRIMED).build();
224
225         expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.DEPLOYED, LockState.LOCKED,
226                 ExpectedCount.once());
227
228         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId)))
229                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED));
230
231         expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.UNDEPLOYING, LockState.UNLOCKING,
232                 ExpectedCount.manyTimes());
233
234         RappInstance rappInstance = rappResourceBuilder.getRappInstance();
235         rappInstance.getAcm().setAcmInstanceId(instanceId);
236         rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
237         boolean rappUndeployStateActual = acmDeployer.undeployRappInstance(rapp, rappInstance);
238         mockServer.verify();
239         assertFalse(rappUndeployStateActual);
240     }
241
242     @Test
243     void testSyncRappInstanceStatus() throws JsonProcessingException {
244         UUID compositionId = UUID.randomUUID();
245         UUID instanceId = UUID.randomUUID();
246         expectAcmGetInstanceToReturnState(compositionId, instanceId, DeployState.UNDEPLOYING, LockState.UNLOCKING,
247                 ExpectedCount.once());
248         RappInstance rappInstance = rappResourceBuilder.getRappInstance();
249         rappInstance.getAcm().setAcmInstanceId(instanceId);
250         rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
251         acmDeployer.syncRappInstanceStatus(compositionId, rappInstance);
252         mockServer.verify();
253         verify(rappInstanceStateMachine, times(1)).sendRappInstanceEvent(rappInstance, RappEvent.UNDEPLOYING);
254     }
255
256     @Test
257     void testSyncRappStatusFailure() {
258         UUID compositionId = UUID.randomUUID();
259         UUID instanceId = UUID.randomUUID();
260
261         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId)))
262                 .andExpect(method(HttpMethod.GET)).andRespond(withStatus(HttpStatus.BAD_GATEWAY));
263
264         RappInstance rappInstance = rappResourceBuilder.getRappInstance();
265         rappInstance.getAcm().setAcmInstanceId(instanceId);
266         rappInstanceStateMachine.onboardRappInstance(rappInstance.getRappInstanceId());
267         acmDeployer.syncRappInstanceStatus(compositionId, rappInstance);
268         mockServer.verify();
269         verify(rappInstanceStateMachine, never()).sendRappInstanceEvent(any(), any());
270     }
271
272     @Test
273     void testPrimeRapp() throws JsonProcessingException {
274         UUID compositionId = UUID.randomUUID();
275         RappResources rappResources = rappResourceBuilder.getResources();
276         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
277                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
278                             .compositionId(compositionId).rappResources(rappResources).build();
279
280         CommissioningResponse commissioningResponseExpected = new CommissioningResponse();
281         commissioningResponseExpected.setCompositionId(compositionId);
282         mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST))
283                 .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
284                                     .body(objectMapper.writeValueAsString(commissioningResponseExpected)));
285         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
286                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.ACCEPTED));
287         boolean primeRapp = acmDeployer.primeRapp(rapp);
288         mockServer.verify();
289         assertTrue(primeRapp);
290     }
291
292     @Test
293     void testPrimeRappFailure() throws JsonProcessingException {
294         UUID compositionId = UUID.randomUUID();
295         RappResources rappResources = rappResourceBuilder.getResources();
296         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
297                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
298                             .compositionId(compositionId).rappResources(rappResources).build();
299
300         CommissioningResponse commissioningResponseExpected = new CommissioningResponse();
301         commissioningResponseExpected.setCompositionId(compositionId);
302         mockServer.expect(ExpectedCount.once(), requestTo(URI_ACM_COMPOSITIONS)).andExpect(method(HttpMethod.POST))
303                 .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
304                                     .body(objectMapper.writeValueAsString(commissioningResponseExpected)));
305         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
306                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
307         boolean primeRapp = acmDeployer.primeRapp(rapp);
308         mockServer.verify();
309         assertFalse(primeRapp);
310         assertEquals(RappState.COMMISSIONED, rapp.getState());
311     }
312
313     @Test
314     void testDeprimeRapp() throws JsonProcessingException {
315         UUID compositionId = UUID.randomUUID();
316         RappResources rappResources = rappResourceBuilder.getResources();
317         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
318                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
319                             .compositionId(compositionId).rappResources(rappResources).build();
320
321         CommissioningResponse commissioningResponseExpected = new CommissioningResponse();
322         commissioningResponseExpected.setCompositionId(compositionId);
323         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
324                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.OK));
325         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
326                 .andExpect(method(HttpMethod.DELETE)).andRespond(
327                         withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
328                                 .body(objectMapper.writeValueAsString(commissioningResponseExpected)));
329
330         boolean deprimeRapp = acmDeployer.deprimeRapp(rapp);
331         mockServer.verify();
332         assertTrue(deprimeRapp);
333     }
334
335     @Test
336     void testDeprimeFailureRapp() {
337         UUID compositionId = UUID.randomUUID();
338         RappResources rappResources = rappResourceBuilder.getResources();
339         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
340                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED)
341                             .compositionId(compositionId).rappResources(rappResources).build();
342
343         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
344                 .andExpect(method(HttpMethod.PUT)).andRespond(withStatus(HttpStatus.OK));
345         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
346                 .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
347
348         boolean deprimeRapp = acmDeployer.deprimeRapp(rapp);
349         mockServer.verify();
350         assertFalse(deprimeRapp);
351     }
352
353     @Test
354     void testDeprimeExceptionRapp() {
355         Rapp rapp = Rapp.builder().rappId(UUID.randomUUID()).name("").packageName(validRappFile)
356                             .packageLocation(validCsarFileLocation).state(RappState.COMMISSIONED).build();
357         boolean deprimeRapp = acmDeployer.deprimeRapp(rapp);
358         assertFalse(deprimeRapp);
359     }
360
361     @Test
362     void testDeleteComposition() throws JsonProcessingException {
363         UUID compositionId = UUID.randomUUID();
364         CommissioningResponse commissioningResponseExpected = new CommissioningResponse();
365         commissioningResponseExpected.setCompositionId(compositionId);
366         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
367                 .andExpect(method(HttpMethod.DELETE)).andRespond(
368                         withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
369                                 .body(objectMapper.writeValueAsString(commissioningResponseExpected)));
370         CommissioningResponse commissioningResponse = acmDeployer.deleteComposition(compositionId);
371         mockServer.verify();
372         assertEquals(commissioningResponse.getCompositionId(), compositionId);
373     }
374
375     @Test
376     void testDeleteCompositionFailure() {
377         UUID compositionId = UUID.randomUUID();
378         CommissioningResponse commissioningResponseExpected = new CommissioningResponse();
379         commissioningResponseExpected.setCompositionId(compositionId);
380         mockServer.expect(ExpectedCount.once(), requestTo(String.format(URI_ACM_COMPOSITION, compositionId)))
381                 .andExpect(method(HttpMethod.DELETE)).andRespond(withStatus(HttpStatus.INTERNAL_SERVER_ERROR));
382         CommissioningResponse commissioningResponse = acmDeployer.deleteComposition(compositionId);
383         mockServer.verify();
384         assertNull(commissioningResponse);
385     }
386
387     void expectAcmGetInstanceToReturnState(UUID compositionId, UUID instanceId, DeployState deployState,
388             LockState lockState, ExpectedCount expectedCount) throws JsonProcessingException {
389         AutomationComposition automationCompositionDeployed = new AutomationComposition();
390         automationCompositionDeployed.setCompositionId(compositionId);
391         automationCompositionDeployed.setInstanceId(instanceId);
392         automationCompositionDeployed.setDeployState(deployState);
393         automationCompositionDeployed.setLockState(lockState);
394
395         mockServer.expect(expectedCount, requestTo(String.format(URI_ACM_INSTANCE, compositionId, instanceId)))
396                 .andExpect(method(HttpMethod.GET)).andRespond(
397                         withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON)
398                                 .body(objectMapper.writeValueAsString(automationCompositionDeployed)));
399     }
400 }