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