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 fj.data.Either;
26 import org.glassfish.jersey.server.ResourceConfig;
27 import org.glassfish.jersey.test.JerseyTest;
28 import org.junit.BeforeClass;
29 import org.junit.Test;
30 import org.mockito.Mockito;
31 import org.openecomp.sdc.be.catalog.enums.ChangeTypeEnum;
32 import org.openecomp.sdc.be.components.impl.ArchiveBusinessLogic;
33 import org.openecomp.sdc.be.components.impl.exceptions.ByResponseFormatComponentException;
34 import org.openecomp.sdc.be.components.impl.exceptions.ComponentException;
35 import org.openecomp.sdc.be.components.path.utils.GraphTestUtils;
36 import org.openecomp.sdc.be.components.validation.AccessValidations;
37 import org.openecomp.sdc.be.components.validation.ComponentValidations;
38 import org.openecomp.sdc.be.config.ConfigurationManager;
39 import org.openecomp.sdc.be.dao.DAOJanusGraphStrategy;
40 import org.openecomp.sdc.be.dao.JanusGraphClientStrategy;
41 import org.openecomp.sdc.be.dao.api.ActionStatus;
42 import org.openecomp.sdc.be.dao.impl.HealingPipelineDao;
43 import org.openecomp.sdc.be.dao.janusgraph.HealingJanusGraphGenericDao;
44 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphClient;
45 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphGenericDao;
46 import org.openecomp.sdc.be.dao.janusgraph.JanusGraphOperationStatus;
47 import org.openecomp.sdc.be.dao.jsongraph.GraphVertex;
48 import org.openecomp.sdc.be.dao.jsongraph.HealingJanusGraphDao;
49 import org.openecomp.sdc.be.dao.jsongraph.types.EdgeLabelEnum;
50 import org.openecomp.sdc.be.datatypes.enums.ComponentTypeEnum;
51 import org.openecomp.sdc.be.datatypes.enums.GraphPropertyEnum;
52 import org.openecomp.sdc.be.datatypes.enums.JsonPresentationFields;
53 import org.openecomp.sdc.be.datatypes.enums.NodeTypeEnum;
54 import org.openecomp.sdc.be.datatypes.enums.ResourceTypeEnum;
55 import org.openecomp.sdc.be.facade.operations.CatalogOperation;
56 import org.openecomp.sdc.be.impl.ComponentsUtils;
57 import org.openecomp.sdc.be.impl.ServletUtils;
58 import org.openecomp.sdc.be.impl.WebAppContextWrapper;
59 import org.openecomp.sdc.be.model.Component;
60 import org.openecomp.sdc.be.model.LifecycleStateEnum;
61 import org.openecomp.sdc.be.model.User;
62 import org.openecomp.sdc.be.model.catalog.CatalogComponent;
63 import org.openecomp.sdc.be.model.jsonjanusgraph.config.ContainerInstanceTypesData;
64 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArchiveOperation;
65 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.CategoryOperation;
66 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.GroupsOperation;
67 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTemplateOperation;
68 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.NodeTypeOperation;
69 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.TopologyTemplateOperation;
70 import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ToscaOperationFacade;
71 import org.openecomp.sdc.be.model.operations.api.IGraphLockOperation;
72 import org.openecomp.sdc.be.model.operations.api.StorageOperationStatus;
73 import org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper;
74 import org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper;
75 import org.openecomp.sdc.be.servlets.exception.StorageExceptionMapper;
76 import org.openecomp.sdc.be.user.Role;
77 import org.openecomp.sdc.be.user.UserBusinessLogic;
78 import org.openecomp.sdc.common.api.ConfigurationSource;
79 import org.openecomp.sdc.common.api.Constants;
80 import org.openecomp.sdc.common.impl.ExternalConfiguration;
81 import org.openecomp.sdc.common.impl.FSConfigurationSource;
82 import org.openecomp.sdc.exception.ResponseFormat;
83 import org.springframework.context.ApplicationContext;
84 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
85 import org.springframework.context.annotation.Bean;
86 import org.springframework.context.annotation.Configuration;
87 import org.springframework.context.annotation.PropertySource;
88 import org.springframework.http.HttpStatus;
89 import org.springframework.web.context.WebApplicationContext;
91 import javax.servlet.ServletContext;
92 import javax.servlet.http.HttpServletRequest;
93 import javax.ws.rs.client.Entity;
94 import javax.ws.rs.core.Application;
95 import javax.ws.rs.core.GenericType;
96 import javax.ws.rs.core.MediaType;
97 import javax.ws.rs.core.Response;
98 import java.util.HashMap;
99 import java.util.LinkedList;
100 import java.util.List;
101 import java.util.Map;
103 import static org.assertj.core.api.Assertions.assertThat;
104 import static org.mockito.ArgumentMatchers.any;
105 import static org.mockito.ArgumentMatchers.anyString;
106 import static org.mockito.ArgumentMatchers.eq;
107 import static org.mockito.Mockito.doThrow;
108 import static org.mockito.Mockito.mock;
109 import static org.mockito.Mockito.when;
111 public class ArchiveEndpointTest extends JerseyTest {
113 private static final ServletContext servletContext = mock(ServletContext.class);
114 private static final String CSAR_UUID1 = "123456789abcdefgh";
115 private static final String CSAR_UUID2 = "987654321abcdefgh";
117 public static final WebAppContextWrapper webAppContextWrapper = mock(WebAppContextWrapper.class);
118 private static final WebApplicationContext webApplicationContext = mock(WebApplicationContext.class);
119 private static final ServletUtils servletUtils = mock(ServletUtils.class);
120 private static final UserBusinessLogic userAdmin = mock(UserBusinessLogic.class);
121 private static final ComponentsUtils componentUtils = mock(ComponentsUtils.class);
122 private static final CatalogOperation catalogOperations = mock(CatalogOperation.class);
123 // private static final ToscaOperationFacade toscaOperationFacade = mock(ToscaOperationFacade.class);
124 private static final ToscaOperationFacade toscaOperationFacade = Mockito.spy(new ToscaOperationFacade());
127 private static final ResponseFormat responseFormat = mock(ResponseFormat.class);
128 private static final ResponseFormat notFoundResponseFormat = mock(ResponseFormat.class);
129 private static final ResponseFormat badRequestResponseFormat = mock(ResponseFormat.class);
130 private static final ResponseFormat invalidServiceStateResponseFormat = mock(ResponseFormat.class);
131 private static final AccessValidations accessValidationsMock = mock(AccessValidations.class);
132 private static final ComponentValidations componentValidationsMock = mock(ComponentValidations.class);
133 private static final IGraphLockOperation graphLockOperation = mock(IGraphLockOperation.class);
134 private static final HealingJanusGraphGenericDao
135 janusGraphGenericDao = mock(HealingJanusGraphGenericDao.class);
136 private static final HealingPipelineDao HEALING_PIPELINE_DAO = mock(HealingPipelineDao.class);
137 private static GraphVertex serviceVertex;
138 private static GraphVertex resourceVertex;
139 private static GraphVertex resourceVertexVspArchived;
141 private static HealingJanusGraphDao janusGraphDao;
144 @PropertySource("classpath:dao.properties")
145 static class TestSpringConfig {
146 private ArchiveOperation archiveOperation;
147 private GraphVertex catalogVertex;
150 ArchiveEndpoint archiveEndpoint() {
151 UserBusinessLogic userBusinessLogic = mock(UserBusinessLogic.class);
152 ComponentsUtils componentsUtils = mock(ComponentsUtils.class);
153 return new ArchiveEndpoint(userBusinessLogic, componentsUtils, archiveBusinessLogic());
157 ComponentExceptionMapper componentExceptionMapper() {
158 return new ComponentExceptionMapper(componentUtils);
162 StorageExceptionMapper storageExceptionMapper() {
163 return new StorageExceptionMapper(componentUtils);
167 DefaultExceptionMapper defaultExceptionMapper() {
168 return new DefaultExceptionMapper();
172 ArchiveBusinessLogic archiveBusinessLogic() {
173 return new ArchiveBusinessLogic(janusGraphDao(), accessValidations(), archiveOperation(), toscaOperationFacade(), componentUtils, catalogOperations);
177 ArchiveOperation archiveOperation() {
178 this.archiveOperation = new ArchiveOperation(janusGraphDao(), graphLockOperation());
179 GraphTestUtils.clearGraph(janusGraphDao);
181 return this.archiveOperation;
185 ComponentValidations componentValidations() {
186 return componentValidationsMock;
190 AccessValidations accessValidations() {
191 return accessValidationsMock;
195 ToscaOperationFacade toscaOperationFacade() {
196 return toscaOperationFacade;
200 TopologyTemplateOperation topologyTemplateOperation() {
201 return new TopologyTemplateOperation();
205 NodeTypeOperation nodeTypeOpertaion() {
206 return new NodeTypeOperation(null);
210 NodeTemplateOperation nodeTemplateOperation() {
211 return new NodeTemplateOperation();
215 GroupsOperation groupsOperation() {
216 return new GroupsOperation();
220 HealingJanusGraphDao janusGraphDao() {
221 janusGraphDao = new HealingJanusGraphDao(healingPipelineDao(), janusGraphClient());
222 return janusGraphDao;
226 JanusGraphClient janusGraphClient() {
227 return new JanusGraphClient(janusGraphClientStrategy());
231 JanusGraphClientStrategy janusGraphClientStrategy() {
232 return new DAOJanusGraphStrategy();
236 CategoryOperation categoryOperation() {
237 return new CategoryOperation();
241 IGraphLockOperation graphLockOperation() {
242 return graphLockOperation;
246 JanusGraphGenericDao janusGraphGenericDao() {
247 return janusGraphGenericDao;
251 HealingPipelineDao healingPipelineDao(){
252 return HEALING_PIPELINE_DAO;
256 ContainerInstanceTypesData containerInstanceTypesData() {
257 return new ContainerInstanceTypesData();
260 private void initGraphForTest() {
261 //Create Catalog Root
262 catalogVertex = GraphTestUtils.createRootCatalogVertex(janusGraphDao);
263 //Create Archive Root
264 GraphTestUtils.createRootArchiveVertex(janusGraphDao);
266 createSingleVersionServiceAndResource();
269 private void createSingleVersionServiceAndResource() {
270 //Create Service for Scenario 1 Tests (1 Service)
271 serviceVertex = GraphTestUtils.createServiceVertex(janusGraphDao, propsForHighestVersion());
274 Map<GraphPropertyEnum, Object> props = propsForHighestVersion();
275 props.put(GraphPropertyEnum.IS_VSP_ARCHIVED, false);
276 props.put(GraphPropertyEnum.CSAR_UUID, CSAR_UUID1);
277 resourceVertex = GraphTestUtils.createResourceVertex(janusGraphDao, props, ResourceTypeEnum.VF);
279 props = propsForHighestVersion();
280 props.put(GraphPropertyEnum.IS_VSP_ARCHIVED, true);
281 props.put(GraphPropertyEnum.CSAR_UUID, CSAR_UUID2);
282 resourceVertexVspArchived = GraphTestUtils.createResourceVertex(janusGraphDao, props, ResourceTypeEnum.VF);
284 //Connect Service/Resource to Catalog Root
285 janusGraphDao.createEdge(catalogVertex, serviceVertex, EdgeLabelEnum.CATALOG_ELEMENT, null);
286 janusGraphDao.createEdge(catalogVertex, resourceVertex, EdgeLabelEnum.CATALOG_ELEMENT, null);
289 private Map<GraphPropertyEnum, Object> propsForHighestVersion(){
290 Map<GraphPropertyEnum, Object> props = new HashMap<>();
291 props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
296 public static final HttpServletRequest request = mock(HttpServletRequest.class);
299 private static final User adminUser = new User("admin", "admin", "admin", "admin@email.com", Role.ADMIN.name(), System.currentTimeMillis());
300 private static final User designerUser = new User("designer", "designer", "designer", "designer@email.com", Role.DESIGNER.name(), System
301 .currentTimeMillis());
302 private static final User otherUser = new User("other", "other", "other", "other@email.com", Role.TESTER.name(), System.currentTimeMillis());
305 public static void setup() {
306 //Needed for User Authorization
307 //========================================================================================================================
308 when(servletContext.getAttribute(Constants.WEB_APPLICATION_CONTEXT_WRAPPER_ATTR)).thenReturn(webAppContextWrapper);
309 when(webAppContextWrapper.getWebAppContext(servletContext)).thenReturn(webApplicationContext);
310 when(webApplicationContext.getBean(ServletUtils.class)).thenReturn(servletUtils);
311 when(servletUtils.getUserAdmin()).thenReturn(userAdmin);
312 when(servletUtils.getComponentsUtils()).thenReturn(componentUtils);
313 when(componentUtils.getResponseFormat(ActionStatus.RESTRICTED_OPERATION)).thenReturn(responseFormat);
314 when(componentUtils.getResponseFormat(eq(ActionStatus.INVALID_SERVICE_STATE), any())).thenReturn(invalidServiceStateResponseFormat);
315 when(responseFormat.getStatus()).thenReturn(HttpStatus.UNAUTHORIZED.value());
317 ComponentException ce = new ByResponseFormatComponentException(responseFormat);
318 doThrow(ce).when(accessValidationsMock).userIsAdminOrDesigner(eq(otherUser.getUserId()), any());
320 //Needed for error configuration
321 when(notFoundResponseFormat.getStatus()).thenReturn(HttpStatus.NOT_FOUND.value());
322 when(invalidServiceStateResponseFormat.getStatus()).thenReturn(HttpStatus.CONFLICT.value());
323 when(badRequestResponseFormat.getStatus()).thenReturn(HttpStatus.BAD_REQUEST.value());
324 when(componentUtils.getResponseFormat(eq(ActionStatus.RESOURCE_NOT_FOUND), (String[]) any())).thenReturn(notFoundResponseFormat);
325 when(componentUtils.getResponseFormat(eq(ActionStatus.MISSING_X_ECOMP_INSTANCE_ID), (String[]) any())).thenReturn(badRequestResponseFormat);
327 when(graphLockOperation.lockComponent(anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK);
328 when(userAdmin.getUser(adminUser.getUserId(), false)).thenReturn(adminUser);
329 when(userAdmin.getUser(designerUser.getUserId(), false)).thenReturn(designerUser);
330 when(userAdmin.getUser(otherUser.getUserId(), false)).thenReturn(otherUser);
331 //========================================================================================================================
333 String appConfigDir = "src/test/resources/config";
334 ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
335 ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
337 org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
338 configuration.setJanusGraphInMemoryGraph(true);
340 org.openecomp.sdc.be.config.Configuration.HeatDeploymentArtifactTimeout heatDeploymentArtifactTimeout = new org.openecomp.sdc.be.config.Configuration.HeatDeploymentArtifactTimeout();
341 heatDeploymentArtifactTimeout.setDefaultMinutes(30);;
342 configuration.setHeatArtifactDeploymentTimeout(heatDeploymentArtifactTimeout);
343 configurationManager.setConfiguration(configuration);
345 configurationManager.setConfiguration(configuration);
346 ExternalConfiguration.setAppName("catalog-be");
350 public void getArchivedComponents_Empty() {
351 assertOnGetArchivedComponents(null, 0);
355 public void archiveAndGetArchivedService_SingleService() {
356 Component serviceComponent = mock(Component.class);
357 final String serviceUniqueId = serviceVertex.getUniqueId();
358 when(toscaOperationFacade.getToscaElement(serviceUniqueId)).thenReturn(Either.left(serviceComponent));
359 when(catalogOperations.updateCatalog(ChangeTypeEnum.ARCHIVE, serviceComponent)).thenReturn(ActionStatus.OK);
360 archiveService(serviceUniqueId, HttpStatus.OK.value());
361 assertOnGetArchivedComponents(ComponentTypeEnum.SERVICE_PARAM_NAME, 1);
362 //restoreService(serviceUniqueId, 200);
366 public void archiveAndGetArchivedResource_SingleResource() {
367 Component component = mock(Component.class);
368 final String uniqueId = resourceVertex.getUniqueId();
369 when(toscaOperationFacade.getToscaElement(uniqueId)).thenReturn(Either.left(component));
370 when(catalogOperations.updateCatalog(ChangeTypeEnum.ARCHIVE, component)).thenReturn(ActionStatus.OK);
371 archiveResource(uniqueId, HttpStatus.OK.value());
372 assertOnGetArchivedComponents(ComponentTypeEnum.RESOURCE_PARAM_NAME, 1);
373 //restoreResource(uniqueId, 200);
377 public void attemptArchiveCheckedOutService() {
378 checkoutComponent(serviceVertex);
379 archiveService(serviceVertex.getUniqueId(), HttpStatus.CONFLICT.value());
383 public void testOnArchivedVsps(){
384 String path = "/v1/catalog/notif/vsp/archived";
385 List<String> csarIds = new LinkedList<>();
386 csarIds.add("123456");
387 csarIds.add(CSAR_UUID2); //An archived CSAR ID
388 Response response = target()
390 .request(MediaType.APPLICATION_JSON)
391 .accept(MediaType.APPLICATION_JSON)
392 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
393 .post(Entity.json(csarIds));
395 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
396 assertOnVertexProp(resourceVertexVspArchived.getUniqueId(), true);
400 public void testOnRestoredVsps(){
401 String path = "/v1/catalog/notif/vsp/restored";
402 List<String> csarIds = new LinkedList<>();
403 csarIds.add("123456");
404 csarIds.add(CSAR_UUID1); //Non archived CSAR_ID
405 Response response = target()
407 .request(MediaType.APPLICATION_JSON)
408 .accept(MediaType.APPLICATION_JSON)
409 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
410 .post(Entity.json(csarIds));
412 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
413 assertOnVertexProp(resourceVertex.getUniqueId(), false);
420 public void archiveWithInvalidUid() {
421 archiveService("fakeUid", HttpStatus.NOT_FOUND.value());
425 public void restoreWithInvalidUid() {
426 restoreService("fakeUid", HttpStatus.NOT_FOUND.value());
430 public void archiveWithTester() {
431 String path = String.format("/v1/catalog/services/%s/%s", serviceVertex.getUniqueId(), "archive");
432 Response response = target()
435 .accept(MediaType.APPLICATION_JSON)
436 .header(Constants.USER_ID_HEADER, otherUser.getUserId())
439 assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
442 private void checkoutComponent(GraphVertex component) {
443 Either<GraphVertex, JanusGraphOperationStatus> vE = janusGraphDao.getVertexById(component.getUniqueId());
444 GraphVertex v = vE.left().value();
445 v.addMetadataProperty(GraphPropertyEnum.STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
446 v.setJsonMetadataField(JsonPresentationFields.LIFECYCLE_STATE, LifecycleStateEnum.NOT_CERTIFIED_CHECKOUT);
447 janusGraphDao.updateVertex(v);
448 janusGraphDao.commit();
451 private void assertOnVertexProp(String componentId, Object expectedValue) {
452 Either<GraphVertex, JanusGraphOperationStatus> vE = janusGraphDao.getVertexById(componentId);
453 GraphVertex v = vE.left().value();
454 assertThat(v.getMetadataProperty(GraphPropertyEnum.IS_VSP_ARCHIVED)).isEqualTo(expectedValue);
457 private void archiveService(String id, int expectedStatus){ archiveOrRestoreService(id, ArchiveOperation.Action.ARCHIVE, expectedStatus); }
458 private void restoreService(String id, int expectedStatus){ archiveOrRestoreService(id, ArchiveOperation.Action.RESTORE, expectedStatus); }
460 private void archiveResource(String id, int expectedStatus){ archiveOrRestoreResource(id, ArchiveOperation.Action.ARCHIVE, expectedStatus); }
461 private void restoreResource(String id, int expectedStatus){ archiveOrRestoreResource(id, ArchiveOperation.Action.RESTORE, expectedStatus); }
463 private void archiveOrRestoreService(String compUid, ArchiveOperation.Action action, int expectedStatus) {
464 String path = String.format("/v1/catalog/services/%s/%s", compUid, action.name().toLowerCase());
465 Response response = target()
468 .accept(MediaType.APPLICATION_JSON)
469 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
472 assertThat(response.getStatus()).isEqualTo(expectedStatus);
475 private void archiveOrRestoreResource(String compUid, ArchiveOperation.Action action, int expectedStatus) {
476 String path = String.format("/v1/catalog/resources/%s/%s", compUid, action.name().toLowerCase());
477 Response response = target()
480 .accept(MediaType.APPLICATION_JSON)
481 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
484 assertThat(response.getStatus()).isEqualTo(expectedStatus);
487 private void assertOnGetArchivedComponents(String componentType, int expectedCount) {
488 String path = "/v1/catalog/archive";
490 Response response = target()
493 .accept(MediaType.APPLICATION_JSON)
494 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
497 Map<String, List<CatalogComponent>> archivedComponents = response.readEntity(new GenericType<Map<String, List<CatalogComponent>>>() { });
498 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
500 if (componentType == null) {
501 assertThat(archivedComponents).isEmpty();
503 assertThat(archivedComponents.get(componentType)).hasSize(expectedCount);
509 protected Application configure() {
510 ApplicationContext context = new AnnotationConfigApplicationContext(TestSpringConfig.class);
511 return new ResourceConfig(ArchiveEndpoint.class)
512 .register(DefaultExceptionMapper.class)
513 .register(ComponentExceptionMapper.class)
514 .register(StorageExceptionMapper.class)
515 .property("contextConfig", context);