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=========================================================
21 package org.openecomp.sdc.be.servlets;
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;
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;
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.*;
90 public class ArchiveEndpointTest extends JerseyTest {
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";
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);
110 private static final ICacheMangerOperation cacheManagerOperation = mock(ICacheMangerOperation.class);
111 private static GraphVertex serviceVertex;
112 private static GraphVertex resourceVertex;
113 private static GraphVertex resourceVertexVspArchived;
115 private static TitanDao titanDao;
118 static class TestSpringConfig {
119 private ArchiveOperation archiveOperation;
120 private GraphVertex catalogVertex;
123 ArchiveEndpoint archiveEndpoint() {
124 return new ArchiveEndpoint(archiveBusinessLogic());
128 ComponentExceptionMapper componentExceptionMapper() {
129 return new ComponentExceptionMapper(componentUtils);
133 StorageExceptionMapper storageExceptionMapper() {
134 return new StorageExceptionMapper(componentUtils);
138 DefaultExceptionMapper defaultExceptionMapper() {
139 return new DefaultExceptionMapper();
143 ArchiveBusinessLogic archiveBusinessLogic() {
144 return new ArchiveBusinessLogic(titanDao(), accessValidations(), archiveOperation(), toscaOperationFacade(), componentUtils);
148 ArchiveOperation archiveOperation() {
149 this.archiveOperation = new ArchiveOperation(titanDao(), graphLockOperation());
150 GraphTestUtils.clearGraph(titanDao);
152 return this.archiveOperation;
156 ComponentValidations componentValidations() {
157 return componentValidationsMock;
161 AccessValidations accessValidations() {
162 return accessValidationsMock;
166 ToscaOperationFacade toscaOperationFacade() {
167 return new ToscaOperationFacade();
171 TopologyTemplateOperation topologyTemplateOperation() {
172 return new TopologyTemplateOperation();
176 NodeTypeOperation nodeTypeOpertaion() {
177 return new NodeTypeOperation(null);
181 NodeTemplateOperation nodeTemplateOperation() {
182 return new NodeTemplateOperation();
186 GroupsOperation groupsOperation() {
187 return new GroupsOperation();
191 ICacheMangerOperation cacheMangerOperation() {
192 return cacheManagerOperation;
196 TitanDao titanDao() {
197 titanDao = new TitanDao(titanGraphClient());
202 TitanGraphClient titanGraphClient() {
203 return new TitanGraphClient(titanClientStrategy());
207 TitanClientStrategy titanClientStrategy() {
208 return new DAOTitanStrategy();
212 CategoryOperation categoryOperation() {
213 return new CategoryOperation();
217 IGraphLockOperation graphLockOperation() {
218 return graphLockOperation;
222 TitanGenericDao titanGenericDao() {
223 return titanGenericDao;
226 private void initGraphForTest() {
227 //Create Catalog Root
228 catalogVertex = GraphTestUtils.createRootCatalogVertex(titanDao);
229 //Create Archive Root
230 GraphTestUtils.createRootArchiveVertex(titanDao);
232 createSingleVersionServiceAndResource();
235 private void createSingleVersionServiceAndResource() {
236 //Create Service for Scenario 1 Tests (1 Service)
237 serviceVertex = GraphTestUtils.createServiceVertex(titanDao, propsForHighestVersion());
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);
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);
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);
255 private Map<GraphPropertyEnum, Object> propsForHighestVersion(){
256 Map<GraphPropertyEnum, Object> props = new HashMap<>();
257 props.put(GraphPropertyEnum.IS_HIGHEST_VERSION, true);
262 public static final HttpServletRequest request = mock(HttpServletRequest.class);
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());
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());
283 ComponentException ce = new ComponentException(responseFormat);
284 doThrow(ce).when(accessValidationsMock).userIsAdminOrDesigner(eq(otherUser.getUserId()), any());
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);
293 when(graphLockOperation.lockComponent(anyString(), any(NodeTypeEnum.class))).thenReturn(StorageOperationStatus.OK);
295 Either<User, ActionStatus> adminEither = Either.left(adminUser);
296 Either<User, ActionStatus> designerEither = Either.left(designerUser);
297 Either<User, ActionStatus> otherEither = Either.left(otherUser);
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 //========================================================================================================================
304 String appConfigDir = "src/test/resources/config";
305 ConfigurationSource configurationSource = new FSConfigurationSource(ExternalConfiguration.getChangeListener(), appConfigDir);
306 ConfigurationManager configurationManager = new ConfigurationManager(configurationSource);
308 org.openecomp.sdc.be.config.Configuration configuration = new org.openecomp.sdc.be.config.Configuration();
309 configuration.setTitanInMemoryGraph(true);
311 configurationManager.setConfiguration(configuration);
312 ExternalConfiguration.setAppName("catalog-be");
316 public void getArchivedComponents_Empty() {
317 assertOnGetArchivedComponents(null, 0);
321 public void archiveAndGetArchivedComponents_SingleComponent() {
322 archiveComponent(serviceVertex.getUniqueId(), HttpStatus.OK.value());
323 assertOnGetArchivedComponents(ComponentTypeEnum.SERVICE_PARAM_NAME, 1);
327 public void attemptArchiveCheckedOutService() {
328 checkoutComponent(serviceVertex);
329 archiveComponent(serviceVertex.getUniqueId(), HttpStatus.CONFLICT.value());
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()
340 .request(MediaType.APPLICATION_JSON)
341 .accept(MediaType.APPLICATION_JSON)
342 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
343 .post(Entity.json(csarIds));
345 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
346 assertOnVertexProp(resourceVertexVspArchived.getUniqueId(), true);
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()
357 .request(MediaType.APPLICATION_JSON)
358 .accept(MediaType.APPLICATION_JSON)
359 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
360 .post(Entity.json(csarIds));
362 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
363 assertOnVertexProp(resourceVertex.getUniqueId(), false);
370 public void archiveWithInvalidUid() {
371 archiveComponent("fakeUid", HttpStatus.NOT_FOUND.value());
375 public void restoreWithInvalidUid() {
376 restoreComponent("fakeUid", HttpStatus.NOT_FOUND.value());
380 public void archiveWithTester() {
381 String path = String.format("/v1/catalog/services/%s/%s", serviceVertex.getUniqueId(), "archive");
382 Response response = target()
385 .accept(MediaType.APPLICATION_JSON)
386 .header(Constants.USER_ID_HEADER, otherUser.getUserId())
389 assertThat(response.getStatus()).isEqualTo(HttpStatus.UNAUTHORIZED.value());
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);
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);
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); }
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()
415 .accept(MediaType.APPLICATION_JSON)
416 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
419 assertThat(response.getStatus()).isEqualTo(expectedStatus);
422 private void assertOnGetArchivedComponents(String componentType, int expectedCount) {
423 String path = "/v1/catalog/archive";
425 Response response = target()
428 .accept(MediaType.APPLICATION_JSON)
429 .header(Constants.USER_ID_HEADER, designerUser.getUserId())
432 Map<String, List<CatalogComponent>> archivedComponents = response.readEntity(new GenericType<Map<String, List<CatalogComponent>>>() { });
433 assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value());
435 if (componentType == null) {
436 assertThat(archivedComponents).isEmpty();
438 assertThat(archivedComponents.get(componentType)).hasSize(expectedCount);
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);