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