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,62 @@
<!-- 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 -->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-parent</artifactId>
<version>0.2.0-SNAPSHOT</version>
</parent>
<artifactId>hawkbit-system-resource</artifactId>
<name>hawkBit :: REST Resources</name>
<dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-system-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-rest-core</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ru.yandex.qatools.allure</groupId>
<artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

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