2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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 * ================================================================================
23 package org.openecomp.sdc.be.servlets;
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;
33 import fj.data.Either;
34 import java.util.HashMap;
35 import java.util.LinkedList;
36 import java.util.List;
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;
106 public class ArchiveEndpointTest extends JerseyTest {
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";
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;
132 private static HealingJanusGraphDao janusGraphDao;
135 @PropertySource("classpath:dao.properties")
136 static class TestSpringConfig {
137 private ArchiveOperation archiveOperation;
138 private GraphVertex catalogVertex;
141 ArchiveEndpoint archiveEndpoint() {
142 return new ArchiveEndpoint(archiveBusinessLogic());
146 ComponentExceptionMapper componentExceptionMapper() {
147 return new ComponentExceptionMapper(componentUtils);
151 StorageExceptionMapper storageExceptionMapper() {
152 return new StorageExceptionMapper(componentUtils);
156 DefaultExceptionMapper defaultExceptionMapper() {
157 return new DefaultExceptionMapper();
161 ArchiveBusinessLogic archiveBusinessLogic() {
162 return new ArchiveBusinessLogic(janusGraphDao(), accessValidations(), archiveOperation(), toscaOperationFacade(), componentUtils);
166 ArchiveOperation archiveOperation() {
167 this.archiveOperation = new ArchiveOperation(janusGraphDao(), graphLockOperation());
168 GraphTestUtils.clearGraph(janusGraphDao);
170 return this.archiveOperation;
174 ComponentValidations componentValidations() {
175 return componentValidationsMock;
179 AccessValidations accessValidations() {
180 return accessValidationsMock;
184 ToscaOperationFacade toscaOperationFacade() {
185 return new ToscaOperationFacade();
189 TopologyTemplateOperation topologyTemplateOperation() {
190 return new TopologyTemplateOperation();
194 NodeTypeOperation nodeTypeOpertaion() {
195 return new NodeTypeOperation(null);
199 NodeTemplateOperation nodeTemplateOperation() {
200 return new NodeTemplateOperation();
204 GroupsOperation groupsOperation() {
205 return new GroupsOperation();
209 ICacheMangerOperation cacheMangerOperation() {
210 return cacheManagerOperation;
214 HealingJanusGraphDao janusGraphDao() {
215 janusGraphDao = new HealingJanusGraphDao(janusGraphClient());
216 return janusGraphDao;
220 JanusGraphClient janusGraphClient() {
221 return new JanusGraphClient(janusGraphClientStrategy());
225 JanusGraphClientStrategy janusGraphClientStrategy() {
226 return new DAOJanusGraphStrategy();
230 CategoryOperation categoryOperation() {
231 return new CategoryOperation();
235 IGraphLockOperation graphLockOperation() {
236 return graphLockOperation;
240 JanusGraphGenericDao janusGraphGenericDao() {
241 return janusGraphGenericDao;
245 HealingPipelineDao healingPipelineDao(){
246 return HEALING_PIPELINE_DAO;
249 private void initGraphForTest() {
250 //Create Catalog Root
251 catalogVertex = GraphTestUtils.createRootCatalogVertex(janusGraphDao);
252 //Create Archive Root
253 GraphTestUtils.createRootArchiveVertex(janusGraphDao);
255 createSingleVersionServiceAndResource();
258 private void createSingleVersionServiceAndResource() {
259 //Create Service for Scenario 1 Tests (1 Service)
260 serviceVertex = GraphTestUtils.createServiceVertex(janusGraphDao, propsForHighestVersion());
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);
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);
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);
278 private Map<GraphPropertyEnum, Object> propsForHighestVersion(){
279 Map<GraphPropertyEnum, Object> props = new HashMap<>();
280 props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
285 public static final HttpServletRequest request = mock(HttpServletRequest.class);
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());
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());
306 ComponentException ce = new ByResponseFormatComponentException(responseFormat);
307 doThrow(ce).when(accessValidationsMock).userIsAdminOrDesigner(eq(otherUser.getUserId()), any());
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);
316 when(graphLockOperation.lockComponent(anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK);
318 Either<User, ActionStatus> adminEither = Either.left(adminUser);
319 Either<User, ActionStatus> designerEither = Either.left(designerUser);
320 Either<User, ActionStatus> otherEither = Either.left(otherUser);
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 //========================================================================================================================
327 String appConfigDir = "src/test/resources/config";
328 ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
329 ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
331 org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
332 configuration.setJanusGraphInMemoryGraph(true);
334 configurationManager.setConfiguration(configuration);
335 ExternalConfiguration.setAppName("catalog-be");
339 public void getArchivedComponents_Empty() {
340 assertOnGetArchivedComponents(null, 0);
344 public void archiveAndGetArchivedComponents_SingleComponent() {
345 archiveComponent(serviceVertex.getUniqueId(), HttpStatus.OK.value());
346 assertOnGetArchivedComponents(ComponentTypeEnum.SERVICE_PARAM_NAME, 1);
350 public void attemptArchiveCheckedOutService() {
351 checkoutComponent(serviceVertex);
352 archiveComponent(serviceVertex.getUniqueId(), HttpStatus.CONFLICT.value());
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()
363 .request(MediaType.APPLICATION_JSON)
364 .accept(MediaType.APPLICATION_JSON)
365 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
366 .post(Entity.json(csarIds));
368 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
369 assertOnVertexProp(resourceVertexVspArchived.getUniqueId(), true);
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()
380 .request(MediaType.APPLICATION_JSON)
381 .accept(MediaType.APPLICATION_JSON)
382 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
383 .post(Entity.json(csarIds));
385 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
386 assertOnVertexProp(resourceVertex.getUniqueId(), false);
393 public void archiveWithInvalidUid() {
394 archiveComponent("fakeUid", HttpStatus.NOT_FOUND.value());
398 public void restoreWithInvalidUid() {
399 restoreComponent("fakeUid", HttpStatus.NOT_FOUND.value());
403 public void archiveWithTester() {
404 String path = String.format("/v1/catalog/services/%s/%s", serviceVertex.getUniqueId(), "archive");
405 Response response = target()
408 .accept(MediaType.APPLICATION_JSON)
409 .header(Constants.USER_ID_HEADER, otherUser.getUserId())
412 assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
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();
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);
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); }
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()
438 .accept(MediaType.APPLICATION_JSON)
439 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
442 assertThat(response.getStatus()).isEqualTo(expectedStatus);
445 private void assertOnGetArchivedComponents(String componentType, int expectedCount) {
446 String path = "/v1/catalog/archive";
448 Response response = target()
451 .accept(MediaType.APPLICATION_JSON)
452 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
455 Map<String, List<CatalogComponent>> archivedComponents = response.readEntity(new GenericType<Map<String, List<CatalogComponent>>>() { });
456 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
458 if (componentType == null) {
459 assertThat(archivedComponents).isEmpty();
461 assertThat(archivedComponents.get(componentType)).hasSize(expectedCount);
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);