Rename and split rest resources ddi, mgmt and system

Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
SirWayne
2016-04-20 17:33:03 +02:00
parent 8a22ea3df3
commit c3c405c986
169 changed files with 3081 additions and 1871 deletions

View File

@@ -0,0 +1,30 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
/**
* Annotation to enable {@link ComponentScan} in the resource package to setup
* all {@link Controller} annotated classes and setup the System API.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
public @interface EnableSystemApi {
}

View File

@@ -0,0 +1,136 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.report.model.SystemUsageReport;
import org.eclipse.hawkbit.report.model.TenantUsage;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.system.json.model.systemmanagement.SystemCache;
import org.eclipse.hawkbit.system.json.model.systemmanagement.SystemStatisticsRest;
import org.eclipse.hawkbit.system.json.model.systemmanagement.SystemTenantServiceUsage;
import org.eclipse.hawkbit.system.rest.api.SystemManagementRestApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RestController;
/**
* {@link SystemManagement} capabilities by REST.
*
*/
@RestController
public class SystemManagementResource implements SystemManagementRestApi {
private static final Logger LOGGER = LoggerFactory.getLogger(SystemManagementResource.class);
@Autowired
private SystemManagement systemManagement;
@Autowired
private CacheManager cacheManager;
/**
* Deletes the tenant data of a given tenant. USE WITH CARE!
*
* @param tenant
* to delete
* @return HttpStatus.OK
*/
@Override
public ResponseEntity<Void> deleteTenant(final String tenant) {
systemManagement.deleteTenant(tenant);
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* Collects and returns system usage statistics. It provides a system wide
* overview and tenant based stats.
*
* @return system usage statistics
*/
@Override
public ResponseEntity<SystemStatisticsRest> getSystemUsageStats() {
final SystemUsageReport report = systemManagement.getSystemUsageStatistics();
final SystemStatisticsRest result = new SystemStatisticsRest().setOverallActions(report.getOverallActions())
.setOverallArtifacts(report.getOverallArtifacts())
.setOverallArtifactVolumeInBytes(report.getOverallArtifactVolumeInBytes())
.setOverallTargets(report.getOverallTargets()).setOverallTenants(report.getTenants().size());
result.setTenantStats(
report.getTenants().stream().map(SystemManagementResource::convertTenant).collect(Collectors.toList()));
return ResponseEntity.ok(result);
}
private static SystemTenantServiceUsage convertTenant(final TenantUsage tenant) {
final SystemTenantServiceUsage result = new SystemTenantServiceUsage(tenant.getTenantName());
result.setActions(tenant.getActions());
result.setArtifacts(tenant.getArtifacts());
result.setOverallArtifactVolumeInBytes(tenant.getOverallArtifactVolumeInBytes());
result.setTargets(tenant.getTargets());
return result;
}
/**
* Returns a list of all caches.
*
* @return a list of caches for all tenants
*/
@Override
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
public ResponseEntity<Collection<SystemCache>> getCaches() {
final Collection<String> cacheNames = cacheManager.getCacheNames();
return ResponseEntity
.ok(cacheNames.stream().map(cacheManager::getCache).map(this::cacheRest).collect(Collectors.toList()));
}
/**
* Invalidates all caches for all tenants.
*
* @return a list of cache names which has been invalidated
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
@Override
public ResponseEntity<Collection<String>> invalidateCaches() {
final Collection<String> cacheNames = cacheManager.getCacheNames();
LOGGER.info("Invalidating caches {}", cacheNames);
cacheNames.forEach(cacheName -> cacheManager.getCache(cacheName).clear());
return ResponseEntity.ok(cacheNames);
}
private SystemCache cacheRest(final Cache cache) {
final Object nativeCache = cache.getNativeCache();
if (nativeCache instanceof com.google.common.cache.Cache) {
return guavaCache(cache, nativeCache);
} else {
return new SystemCache(cache.getName(), Collections.emptyList());
}
}
@SuppressWarnings("unchecked")
private SystemCache guavaCache(final Cache cache, final Object nativeCache) {
final com.google.common.cache.Cache<Object, Object> guavaCache = (com.google.common.cache.Cache<Object, Object>) nativeCache;
final List<String> keys = guavaCache.asMap().keySet().stream().map(key -> key.toString())
.collect(Collectors.toList());
return new SystemCache(cache.getName(), keys);
}
}

View File

@@ -0,0 +1,73 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.system.json.model.system.SystemTenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
/**
* A mapper which maps repository model to RESTful model representation and
* back.
*/
public class SystemMapper {
private SystemMapper() {
// Utility class
}
/**
* @param tenantConfigurationManagement
* instance of TenantConfigurationManagement
* @return a map of all existing configuration values
*/
public static Map<String, SystemTenantConfigurationValue> toResponse(
final TenantConfigurationManagement tenantConfigurationManagement) {
final Map<String, SystemTenantConfigurationValue> configurationMap = new HashMap<>();
for (final TenantConfigurationKey key : TenantConfigurationKey.values()) {
configurationMap.put(key.getKeyName(),
toResponse(key.getKeyName(), tenantConfigurationManagement.getConfigurationValue(key)));
}
return configurationMap;
}
/**
* maps a TenantConfigurationValue from the repository model to a
* SystemTenantConfigurationValue, the RESTful model.
*
* @param repoConfValue
* configuration value as repository model
* @return configuration value as RESTful model
*/
public static SystemTenantConfigurationValue toResponse(final String key,
final TenantConfigurationValue<?> repoConfValue) {
final SystemTenantConfigurationValue restConfValue = new SystemTenantConfigurationValue();
restConfValue.setValue(repoConfValue.getValue());
restConfValue.setGlobal(repoConfValue.isGlobal());
restConfValue.setCreatedAt(repoConfValue.getCreatedAt());
restConfValue.setCreatedBy(repoConfValue.getCreatedBy());
restConfValue.setLastModifiedAt(repoConfValue.getLastModifiedAt());
restConfValue.setLastModifiedBy(repoConfValue.getLastModifiedBy());
restConfValue.add(linkTo(methodOn(SystemResource.class).getConfigurationValue(key)).withRel("self"));
return restConfValue;
}
}

View File

@@ -0,0 +1,125 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.util.Map;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.system.json.model.system.SystemTenantConfigurationValue;
import org.eclipse.hawkbit.system.json.model.system.SystemTenantConfigurationValueRequest;
import org.eclipse.hawkbit.system.rest.api.SystemRestApi;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.ResourceSupport;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
/**
* REST Resource handling tenant specific configuration operations.
*
*
*
*
*/
@RestController
public class SystemResource implements SystemRestApi {
private static final Logger LOG = LoggerFactory.getLogger(SystemResource.class);
@Autowired
private TenantConfigurationManagement tenantConfigurationManagement;
@Override
public ResponseEntity<ResourceSupport> getSystem() {
final ResourceSupport resourceSupport = new ResourceSupport();
resourceSupport.add(linkTo(methodOn(SystemResource.class).getSystemConfiguration()).withRel("configs"));
return ResponseEntity.ok(resourceSupport);
}
/**
* @return a Map of all configuration values.
*/
@Override
public ResponseEntity<Map<String, SystemTenantConfigurationValue>> getSystemConfiguration() {
return new ResponseEntity<>(SystemMapper.toResponse(tenantConfigurationManagement), HttpStatus.OK);
}
/**
* Handles the DELETE request of deleting a tenant specific configuration
* value within SP.
*
* @param keyName
* the Name of the configuration key
* @return If the given configuration value exists and could be deleted Http
* OK. In any failure the JsonResponseExceptionHandler is handling
* the response.
*/
@Override
public ResponseEntity<Void> deleteConfigurationValue(final String keyName) {
final TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
tenantConfigurationManagement.deleteConfiguration(configKey);
LOG.debug("{} config value deleted, return status {}", keyName, HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
/**
* Handles the GET request of deleting a tenant specific configuration value
* within SP.
*
* @param keyName
* the Name of the configuration key
* @return If the given configuration value exists and could be get Http OK.
* In any failure the JsonResponseExceptionHandler is handling the
* response.
*/
@Override
public ResponseEntity<SystemTenantConfigurationValue> getConfigurationValue(final String keyName) {
final TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
LOG.debug("{} config value getted, return status {}", keyName, HttpStatus.OK);
return new ResponseEntity<>(SystemMapper.toResponse(configKey.getKeyName(),
tenantConfigurationManagement.getConfigurationValue(configKey)), HttpStatus.OK);
}
/**
* Handles the GET request of deleting a tenant specific configuration value
* within SP.
*
* @param keyName
* the Name of the configuration key
* @param configurationValueRest
* the new value for the configuration
* @return If the given configuration value exists and could be get Http OK.
* In any failure the JsonResponseExceptionHandler is handling the
* response.
*/
@Override
public ResponseEntity<SystemTenantConfigurationValue> updateConfigurationValue(final String keyName,
final SystemTenantConfigurationValueRequest configurationValueRest) {
final TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
final TenantConfigurationValue<Object> updatedValue = tenantConfigurationManagement
.addOrUpdateConfiguration(configKey, configurationValueRest.getValue());
return new ResponseEntity<>(SystemMapper.toResponse(keyName, updatedValue), HttpStatus.OK);
}
}

View File

@@ -0,0 +1,55 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultHandler;
import org.springframework.test.web.servlet.result.PrintingResultHandler;
import org.springframework.util.CollectionUtils;
public abstract class MockMvcResultPrinter {
private static final Logger LOG = LoggerFactory.getLogger(MockMvcResultPrinter.class);
private MockMvcResultPrinter() {
}
/**
* Print {@link MvcResult} details to the "standard" output stream.
*/
public static ResultHandler print() {
return new ConsolePrintingResultHandler();
}
/**
* An {@link PrintingResultHandler} that writes to the "standard" output
* stream
*/
private static class ConsolePrintingResultHandler extends PrintingResultHandler {
public ConsolePrintingResultHandler() {
super(new ResultValuePrinter() {
@Override
public void printHeading(final String heading) {
LOG.debug(String.format("%20s:", heading));
}
@Override
public void printValue(final String label, Object value) {
if (value != null && value.getClass().isArray()) {
value = CollectionUtils.arrayToList(value);
}
LOG.debug(String.format("%20s = %s", label, value));
}
});
}
}
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import java.io.IOException;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Utility additions for the REST API tests.
*
*
*/
public final class ResourceUtility {
private static final ObjectMapper mapper = new ObjectMapper();
static ExceptionInfo convertException(final String jsonExceptionResponse)
throws JsonParseException, JsonMappingException, IOException {
return mapper.readValue(jsonExceptionResponse, ExceptionInfo.class);
}
}

View File

@@ -0,0 +1,174 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Random;
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.WithSpringAuthorityRule;
import org.eclipse.hawkbit.WithUser;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.junit.Test;
import org.springframework.http.MediaType;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
/**
*
*
*/
@Features("Component Tests - System API")
@Stories("System Management Resource")
public class SystemManagementResourceTest extends AbstractIntegrationTestWithMongoDB {
@Test
@WithUser(tenantId = "mytenant", authorities = { SpPermission.SYSTEM_ADMIN })
@Description("Tests that the system is able to collect statistics for the entire system.")
public void collectSystemStatistics() throws Exception {
createTestTenantsForSystemStatistics(2, 2000, 100, 2);
mvc.perform(get("/system/admin/usage").accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$tenantStats.[?(@.tenantName==tenant0)][0].targets", equalTo(100)))
.andExpect(jsonPath("$tenantStats.[?(@.tenantName==tenant0)][0].overallArtifactVolumeInBytes",
equalTo(2000)))
.andExpect(jsonPath("$tenantStats.[?(@.tenantName==tenant0)][0].artifacts", equalTo(1)))
.andExpect(jsonPath("$tenantStats.[?(@.tenantName==tenant0)][0].actions", equalTo(200)))
.andExpect(jsonPath("$overallTargets", equalTo(200)))
.andExpect(jsonPath("$overallArtifacts", equalTo(2)))
.andExpect(jsonPath("$overallArtifactVolumeInBytes", equalTo(4000)))
.andExpect(jsonPath("$overallActions", equalTo(400)))
.andExpect(jsonPath("$overallTenants", equalTo(4)));
}
@Test
@WithUser(tenantId = "mytenant", authorities = { SpPermission.DELETE_TARGET, SpPermission.DELETE_REPOSITORY,
SpPermission.CREATE_REPOSITORY, SpPermission.READ_REPOSITORY })
@Description("Tests that the system is not able to collect statistics for the entire system if the .")
public void collectSystemStatisticsWithMissingPermissionFails() throws Exception {
mvc.perform(get("/system/admin/usage").accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isForbidden());
}
@Test
@WithUser(tenantId = "mytenant", allSpPermissions = true)
@Description("Tests that a tenant can be deletd by API.")
public void deleteTenant() throws Exception {
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
distributionSetManagement);
assertThat(distributionSetManagement.findDistributionSetById(dsA.getId())).isNotNull();
mvc.perform(delete("/system/admin/tenants/mytenant")).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(distributionSetManagement.findDistributionSetById(dsA.getId())).isNull();
}
@Test
@WithUser(tenantId = "mytenant", authorities = { SpPermission.DELETE_TARGET, SpPermission.DELETE_REPOSITORY,
SpPermission.CREATE_REPOSITORY, SpPermission.READ_REPOSITORY })
@Description("Tenant deletion is only possible for SYSTEM_ADMINs. Repository or target delete is not sufficient.")
public void deleteTenantFailsMissingPermission() throws Exception {
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
distributionSetManagement);
assertThat(distributionSetManagement.findDistributionSetById(dsA.getId())).isNotNull();
mvc.perform(delete("/system/admin/tenants/mytenant")).andDo(MockMvcResultPrinter.print())
.andExpect(status().isForbidden());
assertThat(distributionSetManagement.findDistributionSetById(dsA.getId())).isNotNull();
}
@Test
public void getCachesReturnStatus200() throws Exception {
mvc.perform(get("/system/admin/caches")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
}
@Test
public void invalidateCachesReturnStatus200() throws Exception {
mvc.perform(delete("/system/admin/caches")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
}
private byte[] createTestTenantsForSystemStatistics(final int tenants, final int artifactSize, final int targets,
final int updates) throws Exception {
final Random randomgen = new Random();
final byte random[] = new byte[artifactSize];
randomgen.nextBytes(random);
for (int i = 0; i < tenants; i++) {
final String tenantname = "tenant" + i;
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("bumlux", tenantname), () -> {
systemManagement.getTenantMetadata(tenantname);
if (artifactSize > 0) {
createTestArtifact(random);
createDeletedTestArtifact(random);
}
if (targets > 0) {
final List<Target> createdTargets = createTestTargets(targets);
if (updates > 0) {
for (int x = 0; x < updates; x++) {
final DistributionSet ds = TestDataUtil.generateDistributionSet("to be deployed" + x,
softwareManagement, distributionSetManagement, true);
deploymentManagement.assignDistributionSet(ds, createdTargets);
}
}
}
return null;
});
}
return random;
}
private List<Target> createTestTargets(final int targets) {
return targetManagement
.createTargets(TestDataUtil.buildTargetFixtures(targets, "testTargetOfTenant", "testTargetOfTenant"));
}
private void createTestArtifact(final byte[] random) {
SoftwareModule sm = new SoftwareModule(softwareManagement.findSoftwareModuleTypeByKey("os"), "name 1",
"version 1", null, null);
sm = softwareModuleRepository.save(sm);
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), sm.getId(), "file1", false);
}
private void createDeletedTestArtifact(final byte[] random) {
final DistributionSet ds = TestDataUtil.generateDistributionSet("deleted garbage", softwareManagement,
distributionSetManagement, true);
ds.getModules().stream().forEach(module -> {
artifactManagement.createLocalArtifact(new ByteArrayInputStream(random), module.getId(), "file1", false);
softwareManagement.deleteSoftwareModule(module);
});
}
}

View File

@@ -0,0 +1,146 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.system.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.eclipse.hawkbit.AbstractIntegrationTest;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.eclipse.hawkbit.system.rest.api.SystemRestConstant;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@Features("Component Tests - System RESTful API")
@Stories("ConfigurationResource")
public class SystemResourceTest extends AbstractIntegrationTest {
private static String BASE_JSON_REQUEST_STRING = "{\"value\":\"%s\"}";
@Test
@Description("perform a GET request on all existing configurations.")
public void getConfigurationValues() throws Exception {
final ResultActions resultActions = mvc.perform(get(SystemRestConstant.SYSTEM_V1_REQUEST_MAPPING + "/configs/"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("$.*", hasSize(TenantConfigurationKey.values().length)));
for (final TenantConfigurationKey key : TenantConfigurationKey.values()) {
final TenantConfigurationValue<?> confValue = tenantConfigurationManagement.getConfigurationValue(key);
resultActions.andExpect(jsonPath("$.['" + key.getKeyName() + "'].value", equalTo(confValue.getValue())))
.andExpect(jsonPath("$.['" + key.getKeyName() + "'].global", equalTo(confValue.isGlobal())));
}
}
@Test
@Description("perform a GET request on a existing configuration key.")
public void getConfigurationValue() throws Exception {
final TenantConfigurationKey key = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME;
final String notGlobalValue = "notTheGlobalHeaderAuthoryName";
tenantConfigurationManagement.addOrUpdateConfiguration(key, notGlobalValue);
mvc.perform(get(SystemRestConstant.SYSTEM_V1_REQUEST_MAPPING + "/configs/{configId}/", key.getKeyName()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("value", equalTo(notGlobalValue))).andExpect(jsonPath("global", equalTo(false)))
.andExpect(jsonPath("createdAt", notNullValue())).andExpect(jsonPath("createdBy", notNullValue()));
}
@Test
@Description("perform a PUT request on a existing configuration key with a valid value.")
public void putConfigurationValue() throws Exception {
final TenantConfigurationKey key = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME;
final String testValue = "12:12:12";
mvc.perform(put(SystemRestConstant.SYSTEM_V1_REQUEST_MAPPING + "/configs/{configId}/", key.getKeyName())
.content(String.format(BASE_JSON_REQUEST_STRING, testValue)).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
assertThat(tenantConfigurationManagement.getConfigurationValue(key, String.class).getValue())
.isEqualTo(testValue);
}
@Test
@Description("perform a DELETE request on a existing configuration key.")
public void deleteConfigurationValue() throws Exception {
final TenantConfigurationKey key = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME;
final String notGlobalValue = "notTheGlobalHeaderAuthoryName";
tenantConfigurationManagement.addOrUpdateConfiguration(key, notGlobalValue);
assertThat(tenantConfigurationManagement.getConfigurationValue(key, String.class).isGlobal()).isEqualTo(false);
assertThat(tenantConfigurationManagement.getConfigurationValue(key, String.class).getValue())
.isEqualTo(notGlobalValue);
mvc.perform(delete(SystemRestConstant.SYSTEM_V1_REQUEST_MAPPING + "/configs/{configId}/", key.getKeyName()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNoContent());
assertThat(tenantConfigurationManagement.getConfigurationValue(key, String.class).isGlobal()).isEqualTo(true);
assertThat(tenantConfigurationManagement.getConfigurationValue(key, String.class).getValue())
.isNotEqualTo(notGlobalValue);
}
@Test
@Description("perform a (put) request on a not existing configuration key.")
public void putInvalidConfigurationKey() throws Exception {
final String notExistingKey = "notExistingKey";
final String testValue = "12:12:12";
final MvcResult mvcResult = mvc
.perform(put(SystemRestConstant.SYSTEM_V1_REQUEST_MAPPING + "/configs/{configId}", notExistingKey)
.content(String.format(BASE_JSON_REQUEST_STRING, testValue))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
// verify response json exception message
final ExceptionInfo exceptionInfo = ResourceUtility
.convertException(mvcResult.getResponse().getContentAsString());
assertThat(exceptionInfo.getErrorCode()).isEqualTo(SpServerError.SP_CONFIGURATION_KEY_INVALID.getKey());
}
@Test
@Description("perform a put request with a not matching configuration value.")
public void putInvalidConfigurationValue() throws Exception {
final TenantConfigurationKey key = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String testValue = "invalidFormattedDuration";
final MvcResult mvcResult = mvc
.perform(put(SystemRestConstant.SYSTEM_V1_REQUEST_MAPPING + "/configs/{configId}", key.getKeyName())
.content(String.format(BASE_JSON_REQUEST_STRING, testValue))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()).andReturn();
// verify response json exception message
final ExceptionInfo exceptionInfo = ResourceUtility
.convertException(mvcResult.getResponse().getContentAsString());
assertThat(exceptionInfo.getErrorCode()).isEqualTo(SpServerError.SP_CONFIGURATION_VALUE_INVALID.getKey());
}
}

View File

@@ -0,0 +1,63 @@
#
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
# http://www.eclipse.org/legal/epl-v10.html
#
# used if IM profile is disabled
security.ignored=true
# IM required for integration tests
spring.profiles.active=im,suiteembedded,artifactrepository,redis
server.port=12222
spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value}
spring.data.mongodb.port=28017
# supported: H2, MYSQL
hawkbit.server.database=H2
hawkbit.server.database.env=TEST
spring.main.show_banner=false
hawkbit.server.ddi.security.authentication.header=true
hawkbit.server.artifact.repo.upload.maxFileSize=5MB
hawkbit.server.security.dos.maxStatusEntriesPerAction=100
hawkbit.server.security.dos.maxAttributeEntriesPerTarget=10
spring.jpa.database=${hawkbit.server.database}
#spring.jpa.show-sql=true
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
# effective DB setting
spring.datasource.url=${${hawkbit.server.database}.spring.datasource.url}
spring.datasource.driverClassName=${${hawkbit.server.database}.spring.datasource.driverClassName}
spring.datasource.username=${${hawkbit.server.database}.spring.datasource.username}
spring.datasource.password=${${hawkbit.server.database}.spring.datasource.password}
# H2
##;AUTOCOMMIT=ON
H2.spring.datasource.url=jdbc:h2:mem:sp-db;DB_CLOSE_ON_EXIT=FALSE
#H2.spring.datasource.url=jdbc:h2:./db/sp-db;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE;MVCC=TRUE
H2.spring.datasource.driverClassName=org.h2.Driver
H2.spring.datasource.username=sa
H2.spring.datasource.password=sa
# MYSQL
MYSQL.spring.datasource.url=jdbc:mysql://localhost:3306/sp_test
MYSQL.spring.datasource.driverClassName=org.mariadb.jdbc.Driver
MYSQL.spring.datasource.username=root
MYSQL.spring.datasource.password=
# SP Controller configuration
hawkbit.controller.pollingTime=00:01:00
hawkbit.controller.pollingOverdueTime=00:01:00