50cd2570b9e6c89b44290a220cdf02e303378cb8
[sdc.git] / catalog-be / src / test / java / org / openecomp / sdc / be / servlets / ArchiveEndpointTest.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
4  * ================================================================================
5  * Copyright (C) 2017 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  * ============LICENSE_END=========================================================
19  * Modifications copyright (c) 2019 Nokia
20  * ================================================================================
21  */
22
23 package org.openecomp.sdc.be.servlets;
24
25 import static org.assertj.core.api.Assertions.assertThat;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyString;
28 import static org.mockito.ArgumentMatchers.eq;
29 import static org.mockito.Mockito.doThrow;
30 import static org.mockito.Mockito.mock;
31 import static org.mockito.Mockito.when;
32
33 import fj.data.Either;
34 import java.util.HashMap;
35 import java.util.LinkedList;
36 import java.util.List;
37 import java.util.Map;
38 import javax.servlet.ServletContext;
39 import javax.servlet.http.HttpServletRequest;
40 import javax.ws.rs.client.Entity;
41 import javax.ws.rs.core.Application;
42 import javax.ws.rs.core.GenericType;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.Response;
45 import org.glassfish.jersey.server.ResourceConfig;
46 import org.glassfish.jersey.test.JerseyTest;
47 import org.junit.BeforeClass;
48 import org.junit.Test;
49 import org.openecomp.sdc.be.components.impl.ArchiveBusinessLogic;
50 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
51 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
52 import org.openecomp.sdc.be.components.path.utils.GraphTestUtils;
53 import org.openecomp.sdc.be.components.validation.AccessValidations;
54 import org.openecomp.sdc.be.components.validation.ComponentValidations;
55 import org.openecomp.sdc.be.config.ConfigurationManager;
56 import org.openecomp.sdc.be.dao.DAOJanusGraphStrategy;
57 import org.openecomp.sdc.be.dao.JanusGraphClientStrategy;
58 import org.openecomp.sdc.be.dao.api.ActionStatus;
59 import org.openecomp.sdc.be.dao.impl.HealingPipelineDao;
60 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
61 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphClient;
62 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
63 import org.openecomp.sdc.be.dao.jsongraph.HealingJanusGraphDao;
64 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
65 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
66 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
67 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
68 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
69 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
70 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
71 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
72 import org.openecomp.sdc.be.impl.ComponentsUtils;
73 import org.openecomp.sdc.be.impl.ServletUtils;
74 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
75 import org.openecomp.sdc.be.model.LifecycleStateEnum;
76 import org.openecomp.sdc.be.model.User;
77 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
78 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation;
79 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.CategoryOperation;
80 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
81 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation;
82 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTypeOperation;
83 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.TopologyTemplateOperation;
84 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
85 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
86 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
87 import org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper;
88 import org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper;
89 import org.openecomp.sdc.be.servlets.exception.StorageExceptionMapper;
90 import org.openecomp.sdc.be.user.Role;
91 import org.openecomp.sdc.be.user.UserBusinessLogic;
92 import org.openecomp.sdc.common.api.ConfigurationSource;
93 import org.openecomp.sdc.common.api.Constants;
94 import org.openecomp.sdc.common.impl.ExternalConfiguration;
95 import org.openecomp.sdc.common.impl.FSConfigurationSource;
96 import org.openecomp.sdc.exception.ResponseFormat;
97 import org.springframework.context.ApplicationContext;
98 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
99 import org.springframework.context.annotation.Bean;
100 import org.springframework.context.annotation.Configuration;
101 import org.springframework.context.annotation.PropertySource;
102 import org.springframework.http.HttpStatus;
103 import org.springframework.web.context.WebApplicationContext;
104
105 public class ArchiveEndpointTest extends JerseyTest {
106
107     private static final ServletContext servletContext = mock(ServletContext.class);
108     private static final String CSAR_UUID1 = "123456789abcdefgh";
109     private static final String CSAR_UUID2 = "987654321abcdefgh";
110
111     public static final WebAppContextWrapper webAppContextWrapper = mock(WebAppContextWrapper.class);
112     private static final WebApplicationContext webApplicationContext = mock(WebApplicationContext.class);
113     private static final ServletUtils servletUtils = mock(ServletUtils.class);
114     private static final UserBusinessLogic userAdmin = mock(UserBusinessLogic.class);
115     private static final ComponentsUtils componentUtils = mock(ComponentsUtils.class);
116     private static final ResponseFormat responseFormat = mock(ResponseFormat.class);
117     private static final ResponseFormat notFoundResponseFormat = mock(ResponseFormat.class);
118     private static final ResponseFormat badRequestResponseFormat = mock(ResponseFormat.class);
119     private static final ResponseFormat invalidServiceStateResponseFormat = mock(ResponseFormat.class);
120     private static final AccessValidations accessValidationsMock = mock(AccessValidations.class);
121     private static final ComponentValidations componentValidationsMock = mock(ComponentValidations.class);
122     private static final IGraphLockOperation graphLockOperation = mock(IGraphLockOperation.class);
123     private static final HealingJanusGraphGenericDao
124         janusGraphGenericDao = mock(HealingJanusGraphGenericDao.class);
125     private static final HealingPipelineDao HEALING_PIPELINE_DAO = mock(HealingPipelineDao.class);
126     private static GraphVertex serviceVertex;
127     private static GraphVertex resourceVertex;
128     private static GraphVertex resourceVertexVspArchived;
129
130     private static HealingJanusGraphDao janusGraphDao;
131
132     @Configuration
133     @PropertySource("classpath:dao.properties")
134     static class TestSpringConfig {
135         private ArchiveOperation archiveOperation;
136         private GraphVertex catalogVertex;
137
138         @Bean
139         ArchiveEndpoint archiveEndpoint() {
140             return new ArchiveEndpoint(archiveBusinessLogic());
141         }
142
143         @Bean
144         ComponentExceptionMapper componentExceptionMapper() {
145             return new ComponentExceptionMapper(componentUtils);
146         }
147
148         @Bean
149         StorageExceptionMapper storageExceptionMapper() {
150             return new StorageExceptionMapper(componentUtils);
151         }
152
153         @Bean
154         DefaultExceptionMapper defaultExceptionMapper() {
155             return new DefaultExceptionMapper();
156         }
157
158         @Bean
159         ArchiveBusinessLogic archiveBusinessLogic() {
160             return new ArchiveBusinessLogic(janusGraphDao(), accessValidations(), archiveOperation(), toscaOperationFacade(), componentUtils);
161         }
162
163         @Bean
164         ArchiveOperation archiveOperation() {
165             this.archiveOperation = new ArchiveOperation(janusGraphDao(), graphLockOperation());
166             GraphTestUtils.clearGraph(janusGraphDao);
167             initGraphForTest();
168             return this.archiveOperation;
169         }
170
171         @Bean
172         ComponentValidations componentValidations() {
173             return componentValidationsMock;
174         }
175
176         @Bean
177         AccessValidations accessValidations() {
178             return accessValidationsMock;
179         }
180
181         @Bean
182         ToscaOperationFacade toscaOperationFacade() {
183             return new ToscaOperationFacade();
184         }
185
186         @Bean
187         TopologyTemplateOperation topologyTemplateOperation() {
188             return new TopologyTemplateOperation();
189         }
190
191         @Bean
192         NodeTypeOperation nodeTypeOpertaion() {
193             return new NodeTypeOperation(null);
194         }
195
196         @Bean
197         NodeTemplateOperation nodeTemplateOperation() {
198             return new NodeTemplateOperation();
199         }
200
201         @Bean
202         GroupsOperation groupsOperation() {
203             return new GroupsOperation();
204         }
205
206         @Bean
207         HealingJanusGraphDao janusGraphDao() {
208             janusGraphDao = new HealingJanusGraphDao(healingPipelineDao(), janusGraphClient());
209             return janusGraphDao;
210         }
211
212         @Bean
213         JanusGraphClient janusGraphClient() {
214             return new JanusGraphClient(janusGraphClientStrategy());
215         }
216
217         @Bean
218         JanusGraphClientStrategy janusGraphClientStrategy() {
219             return new DAOJanusGraphStrategy();
220         }
221
222         @Bean
223         CategoryOperation categoryOperation() {
224             return new CategoryOperation();
225         }
226
227         @Bean
228         IGraphLockOperation graphLockOperation() {
229             return graphLockOperation;
230         }
231
232         @Bean
233         JanusGraphGenericDao janusGraphGenericDao() {
234             return janusGraphGenericDao;
235         }
236
237         @Bean
238         HealingPipelineDao healingPipelineDao(){
239             return HEALING_PIPELINE_DAO;
240         }
241
242         private void initGraphForTest() {
243             //Create Catalog Root
244             catalogVertex = GraphTestUtils.createRootCatalogVertex(janusGraphDao);
245             //Create Archive Root
246             GraphTestUtils.createRootArchiveVertex(janusGraphDao);
247
248             createSingleVersionServiceAndResource();
249         }
250
251         private void createSingleVersionServiceAndResource() {
252             //Create Service for Scenario 1 Tests (1 Service)
253             serviceVertex = GraphTestUtils.createServiceVertex(janusGraphDao, propsForHighestVersion());
254
255
256             Map<GraphPropertyEnum, Object> props = propsForHighestVersion();
257             props.put(GraphPropertyEnum.IS_VSP_ARCHIVED, false);
258             props.put(GraphPropertyEnum.CSAR_UUID, CSAR_UUID1);
259             resourceVertex = GraphTestUtils.createResourceVertex(janusGraphDao, props, ResourceTypeEnum.VF);
260
261             props = propsForHighestVersion();
262             props.put(GraphPropertyEnum.IS_VSP_ARCHIVED, true);
263             props.put(GraphPropertyEnum.CSAR_UUID, CSAR_UUID2);
264             resourceVertexVspArchived = GraphTestUtils.createResourceVertex(janusGraphDao, props, ResourceTypeEnum.VF);
265
266             //Connect Service/Resource to Catalog Root
267             janusGraphDao.createEdge(catalogVertex, serviceVertex, EdgeLabelEnum.CATALOG_ELEMENT, null);
268             janusGraphDao.createEdge(catalogVertex, resourceVertex, EdgeLabelEnum.CATALOG_ELEMENT, null);
269         }
270
271         private Map<GraphPropertyEnum, Object> propsForHighestVersion(){
272             Map<GraphPropertyEnum, Object> props = new HashMap<>();
273             props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
274             return props;
275         }
276     }
277
278     public static final HttpServletRequest request = mock(HttpServletRequest.class);
279
280     /* Users */
281     private static final User adminUser = new User("admin", "admin", "admin", "admin@email.com", Role.ADMIN.name(), System.currentTimeMillis());
282     private static final User designerUser = new User("designer", "designer", "designer", "designer@email.com", Role.DESIGNER.name(), System
283                                                                                                                                               .currentTimeMillis());
284     private static final User otherUser = new User("other", "other", "other", "other@email.com", Role.OPS.name(), System.currentTimeMillis());
285
286     @BeforeClass
287     public static void setup() {
288         //Needed for User Authorization
289         //========================================================================================================================
290         when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR)).thenReturn(webAppContextWrapper);
291         when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
292         when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
293         when(servletUtils.getUserAdmin()).thenReturn(userAdmin);
294         when(servletUtils.getComponentsUtils()).thenReturn(componentUtils);
295         when(componentUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)).thenReturn(responseFormat);
296         when(componentUtils.getResponseFormat(eq(ActionStatus.INVALID_SERVICE_STATE), any())).thenReturn(invalidServiceStateResponseFormat);
297         when(responseFormat.getStatus()).thenReturn(HttpStatus.UNAUTHORIZED.value());
298
299         ComponentException ce = new ByResponseFormatComponentException(responseFormat);
300         doThrow(ce).when(accessValidationsMock).userIsAdminOrDesigner(eq(otherUser.getUserId()), any());
301
302         //Needed for error configuration
303         when(notFoundResponseFormat.getStatus()).thenReturn(HttpStatus.NOT_FOUND.value());
304         when(invalidServiceStateResponseFormat.getStatus()).thenReturn(HttpStatus.CONFLICT.value());
305         when(badRequestResponseFormat.getStatus()).thenReturn(HttpStatus.BAD_REQUEST.value());
306         when(componentUtils.getResponseFormat(eq(ActionStatus.RESOURCE_NOT_FOUND), (String[]) any())).thenReturn(notFoundResponseFormat);
307         when(componentUtils.getResponseFormat(eq(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID), (String[]) any())).thenReturn(badRequestResponseFormat);
308
309         when(graphLockOperation.lockComponent(anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK);
310
311         Either<User, ActionStatus> adminEither = Either.left(adminUser);
312         Either<User, ActionStatus> designerEither = Either.left(designerUser);
313         Either<User, ActionStatus> otherEither = Either.left(otherUser);
314
315         when(userAdmin.getUser(adminUser.getUserId(), false)).thenReturn(adminEither);
316         when(userAdmin.getUser(designerUser.getUserId(), false)).thenReturn(designerEither);
317         when(userAdmin.getUser(otherUser.getUserId(), false)).thenReturn(otherEither);
318         //========================================================================================================================
319
320         String appConfigDir = "src/test/resources/config";
321         ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
322         ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
323
324         org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
325         configuration.setJanusGraphInMemoryGraph(true);
326
327         configurationManager.setConfiguration(configuration);
328         ExternalConfiguration.setAppName("catalog-be");
329     }
330
331     @Test
332     public void getArchivedComponents_Empty() {
333         assertOnGetArchivedComponents(null, 0);
334     }
335
336     @Test
337     public void archiveAndGetArchivedComponents_SingleComponent() {
338         archiveComponent(serviceVertex.getUniqueId(), HttpStatus.OK.value());
339         assertOnGetArchivedComponents(ComponentTypeEnum.SERVICE_PARAM_NAME, 1);
340     }
341
342     @Test
343     public void attemptArchiveCheckedOutService() {
344         checkoutComponent(serviceVertex);
345         archiveComponent(serviceVertex.getUniqueId(), HttpStatus.CONFLICT.value());
346     }
347
348     @Test
349     public void testOnArchivedVsps(){
350         String path = "/v1/catalog/notif/vsp/archived";
351         List<String> csarIds = new LinkedList<>();
352         csarIds.add("123456");
353         csarIds.add(CSAR_UUID2);   //An archived CSAR ID
354         Response response = target()
355                                     .path(path)
356                                     .request(MediaType.APPLICATION_JSON)
357                                     .accept(MediaType.APPLICATION_JSON)
358                                     .header(Constants.USER_ID_HEADER, designerUser.getUserId())
359                                     .post(Entity.json(csarIds));
360
361         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
362         assertOnVertexProp(resourceVertexVspArchived.getUniqueId(), true);
363     }
364
365     @Test
366     public void testOnRestoredVsps(){
367         String path = "/v1/catalog/notif/vsp/restored";
368         List<String> csarIds = new LinkedList<>();
369         csarIds.add("123456");
370         csarIds.add(CSAR_UUID1);   //Non archived CSAR_ID
371         Response response = target()
372                                     .path(path)
373                                     .request(MediaType.APPLICATION_JSON)
374                                     .accept(MediaType.APPLICATION_JSON)
375                                     .header(Constants.USER_ID_HEADER, designerUser.getUserId())
376                                     .post(Entity.json(csarIds));
377
378         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
379         assertOnVertexProp(resourceVertex.getUniqueId(), false);
380     }
381
382     /*
383      *   Rainy Scenarios
384      */
385     @Test
386     public void archiveWithInvalidUid() {
387         archiveComponent("fakeUid", HttpStatus.NOT_FOUND.value());
388     }
389
390     @Test
391     public void restoreWithInvalidUid() {
392         restoreComponent("fakeUid", HttpStatus.NOT_FOUND.value());
393     }
394
395     @Test
396     public void archiveWithTester() {
397         String path = String.format("/v1/catalog/services/%s/%s", serviceVertex.getUniqueId(), "archive");
398         Response response = target()
399                                     .path(path)
400                                     .request()
401                                     .accept(MediaType.APPLICATION_JSON)
402                                     .header(Constants.USER_ID_HEADER, otherUser.getUserId())
403                                     .post(null);
404
405         assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
406     }
407
408     private void checkoutComponent(GraphVertex component) {
409         Either<GraphVertex, JanusGraphOperationStatus> vE = janusGraphDao.getVertexById(component.getUniqueId());
410         GraphVertex v = vE.left().value();
411         v.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
412         v.setJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
413         janusGraphDao.updateVertex(v);
414         janusGraphDao.commit();
415     }
416
417     private void assertOnVertexProp(String componentId, Object expectedValue) {
418         Either<GraphVertex, JanusGraphOperationStatus> vE = janusGraphDao.getVertexById(componentId);
419         GraphVertex v = vE.left().value();
420         assertThat(v.getMetadataProperty(GraphPropertyEnum.IS_VSP_ARCHIVED)).isEqualTo(expectedValue);
421     }
422
423     private void archiveComponent(String id, int expectedStatus){ archiveOrRestoreComponent(id, ArchiveOperation.Action.ARCHIVE, expectedStatus); }
424     private void restoreComponent(String id, int expectedStatus){ archiveOrRestoreComponent(id, ArchiveOperation.Action.RESTORE, expectedStatus); }
425
426     private void archiveOrRestoreComponent(String compUid, ArchiveOperation.Action action, int expectedStatus) {
427         String path = String.format("/v1/catalog/services/%s/%s", compUid, action.name().toLowerCase());
428         Response response = target()
429                                     .path(path)
430                                     .request()
431                                     .accept(MediaType.APPLICATION_JSON)
432                                     .header(Constants.USER_ID_HEADER, designerUser.getUserId())
433                                     .post(null);
434
435         assertThat(response.getStatus()).isEqualTo(expectedStatus);
436     }
437
438     private void assertOnGetArchivedComponents(String componentType, int expectedCount) {
439         String path = "/v1/catalog/archive";
440
441         Response response = target()
442                                     .path(path)
443                                     .request()
444                                     .accept(MediaType.APPLICATION_JSON)
445                                     .header(Constants.USER_ID_HEADER, designerUser.getUserId())
446                                     .get();
447
448         Map<String, List<CatalogComponent>> archivedComponents = response.readEntity(new GenericType<Map<String, List<CatalogComponent>>>() {  });
449         assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
450
451         if (componentType == null) {
452             assertThat(archivedComponents).isEmpty();
453         } else {
454             assertThat(archivedComponents.get(componentType)).hasSize(expectedCount);
455         }
456
457     }
458
459     @Override
460     protected Application configure() {
461         ApplicationContext context = new AnnotationConfigApplicationContext(TestSpringConfig.class);
462         return new ResourceConfig(ArchiveEndpoint.class)
463                        .register(DefaultExceptionMapper.class)
464                        .register(ComponentExceptionMapper.class)
465                        .register(StorageExceptionMapper.class)
466                        .property("contextConfig", context);
467     }
468 }