Added REST interfaces for tenant configuration

- added GET, DELETE and PUT function on configuration value interfaces
- changed Exception in TenantConfigurationManagement for correct mapping to HTTP Status
- added function to get global configurations from TenantConfigurationManagement, to have
  only one class for handling these configuration values

Signed-off-by: Nonnenmacher Fabian <fabian.nonnenmacher@bosch-si.com>
This commit is contained in:
Fabian Nonnenmacher
2016-01-28 18:44:31 +01:00
committed by Nonnenmacher Fabian
parent 4be880587a
commit ec79e9bd19
20 changed files with 389 additions and 246 deletions

View File

@@ -181,7 +181,11 @@ public enum SpServerError {
* *
*/ */
SP_CONFIGURATION_VALUE_INVALID("hawkbit.server.error.configValueInvalid", SP_CONFIGURATION_VALUE_INVALID("hawkbit.server.error.configValueInvalid",
"The given configuration value is invalid."); "The given configuration value is invalid."),
/**
*
*/
SP_CONFIGURATION_KEY_INVALID("hawkbit.server.error.configKeyInvalid", "The given configuration key is invalid.");
/** /**
* *

View File

@@ -74,6 +74,10 @@ public abstract class SpServerRtException extends RuntimeException {
this.error = error; this.error = error;
} }
/**
*
* @return the SpServerError
*/
public SpServerError getError() { public SpServerError getError() {
return error; return error;
} }

View File

@@ -0,0 +1,55 @@
package org.eclipse.hawkbit.tenancy.configuration;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.exception.SpServerRtException;
/**
* The {@link #InvalidTenantConfigurationKeyException} is thrown when an invalid
* configuration key is used.
*
*/
public class InvalidTenantConfigurationKeyException extends SpServerRtException {
private static final long serialVersionUID = 1L;
private static final SpServerError THIS_ERROR = SpServerError.SP_CONFIGURATION_KEY_INVALID;
/**
* Default constructor.
*/
public InvalidTenantConfigurationKeyException() {
super(THIS_ERROR);
}
/**
* Parameterized constructor.
*
* @param cause
* of the exception
*/
public InvalidTenantConfigurationKeyException(final Throwable cause) {
super(THIS_ERROR, cause);
}
/**
* Parameterized constructor.
*
* @param message
* of the exception
* @param cause
* of the exception
*/
public InvalidTenantConfigurationKeyException(final String message, final Throwable cause) {
super(message, THIS_ERROR, cause);
}
/**
* Parameterized constructor.
*
* @param message
* of the exception
*/
public InvalidTenantConfigurationKeyException(final String message) {
super(message, THIS_ERROR);
}
}

View File

@@ -9,12 +9,13 @@
package org.eclipse.hawkbit.tenancy.configuration; package org.eclipse.hawkbit.tenancy.configuration;
import java.util.Arrays; import java.util.Arrays;
import java.util.NoSuchElementException;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationPollingDurationValidator; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationPollingDurationValidator;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationStringValidator; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationStringValidator;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidator; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidator;
import org.eclipse.hawkbit.tenancy.configuration.validator.exceptions.TenantConfigurationValidatorException; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
/** /**
@@ -121,7 +122,8 @@ public enum TenantConfigurationKey {
/** /**
* *
* @return the datatype of the tenant configuration value * @return the data type of the tenant configuration value. (e.g.
* Integer.class, String.class)
*/ */
public Class<?> getDataType() { public Class<?> getDataType() {
return dataType; return dataType;
@@ -150,9 +152,21 @@ public enum TenantConfigurationKey {
} }
} }
public static TenantConfigurationKey fromKeyName(final String keyName) { /**
* @param keyName
* name of the TenantConfigurationKey
* @return the TenantConfigurationKey with the name keyName
* @throws InvalidTenantConfigurationKeyException
* if there is no TenantConfigurationKey with the name keyName
*/
public static TenantConfigurationKey fromKeyName(final String keyName)
throws InvalidTenantConfigurationKeyException {
try {
return Arrays.stream(TenantConfigurationKey.values()).filter(conf -> conf.getKeyName().equals(keyName)) return Arrays.stream(TenantConfigurationKey.values()).filter(conf -> conf.getKeyName().equals(keyName))
.findFirst().get(); .findFirst().get();
} catch (final NoSuchElementException e) {
throw new InvalidTenantConfigurationKeyException("The given configuration key name does not exist.");
}
} }
} }

View File

@@ -1,7 +1,5 @@
package org.eclipse.hawkbit.tenancy.configuration.validator; package org.eclipse.hawkbit.tenancy.configuration.validator;
import org.eclipse.hawkbit.tenancy.configuration.validator.exceptions.TenantConfigurationValidatorException;
/** /**
* specific tenant configuration validator, which validates that the given value is a booleans. * specific tenant configuration validator, which validates that the given value is a booleans.
*/ */

View File

@@ -5,7 +5,6 @@ import java.time.format.DateTimeParseException;
import org.eclipse.hawkbit.ControllerPollProperties; import org.eclipse.hawkbit.ControllerPollProperties;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.validator.exceptions.TenantConfigurationValidatorException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
/** /**

View File

@@ -1,7 +1,5 @@
package org.eclipse.hawkbit.tenancy.configuration.validator; package org.eclipse.hawkbit.tenancy.configuration.validator;
import org.eclipse.hawkbit.tenancy.configuration.validator.exceptions.TenantConfigurationValidatorException;
/** /**
* specific tenant configuration validator, which validates Strings. * specific tenant configuration validator, which validates Strings.
*/ */

View File

@@ -1,7 +1,5 @@
package org.eclipse.hawkbit.tenancy.configuration.validator; package org.eclipse.hawkbit.tenancy.configuration.validator;
import org.eclipse.hawkbit.tenancy.configuration.validator.exceptions.TenantConfigurationValidatorException;
/** /**
* base interface for clases which can validate tenant configuration values. * base interface for clases which can validate tenant configuration values.
* *

View File

@@ -1,4 +1,4 @@
package org.eclipse.hawkbit.tenancy.configuration.validator.exceptions; package org.eclipse.hawkbit.tenancy.configuration.validator;
import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.exception.SpServerRtException; import org.eclipse.hawkbit.exception.SpServerRtException;

View File

@@ -3,6 +3,7 @@ package org.eclipse.hawkbit.repository;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
@@ -16,6 +17,9 @@ import org.springframework.data.jpa.repository.Modifying;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
/**
* Central tenant configuration management operations of the SP server.
*/
@Transactional(readOnly = true) @Transactional(readOnly = true)
@Validated @Validated
public class TenantConfigurationManagement implements EnvironmentAware { public class TenantConfigurationManagement implements EnvironmentAware {
@@ -32,6 +36,12 @@ public class TenantConfigurationManagement implements EnvironmentAware {
private Environment environment; private Environment environment;
/**
* Get Singleton instance, needed for classes which are not managed in
* Spring context
*
* @return singleton instance of TenantConfigurationManagement
*/
public static TenantConfigurationManagement getInstance() { public static TenantConfigurationManagement getInstance() {
return INSTANCE; return INSTANCE;
} }
@@ -42,7 +52,7 @@ public class TenantConfigurationManagement implements EnvironmentAware {
* configuration the global default value hold in the {@link Environment}. * configuration the global default value hold in the {@link Environment}.
* *
* @param <T> * @param <T>
* * the type of the configuration value
* @param configurationKey * @param configurationKey
* the key of the configuration * the key of the configuration
* @param propertyType * @param propertyType
@@ -52,17 +62,21 @@ public class TenantConfigurationManagement implements EnvironmentAware {
* configuration stored or from the fallback default values or * configuration stored or from the fallback default values or
* {@code null} in case key has not been configured and not default * {@code null} in case key has not been configured and not default
* value exists * value exists
* @throws TenantConfigurationValidatorException
* if the {@code propertyType} and the value in general does not
* match the expected type and format defined by the Key
* @throws ConversionFailedException * @throws ConversionFailedException
* if the property cannot be converted to the given * if the property cannot be converted to the given
* {@code propertyType} * {@code propertyType}
*/ */
@Cacheable(value = "tenantConfiguration", key = "#configurationKey.getKeyName()") @Cacheable(value = "tenantConfiguration", key = "#configurationKey.getKeyName()")
public <T> TenantConfigurationValue<T> getConfigurationValue(final TenantConfigurationKey configurationKey, public <T> TenantConfigurationValue<T> getConfigurationValue(final TenantConfigurationKey configurationKey,
final Class<T> propertyType) { final Class<T> propertyType) throws TenantConfigurationValidatorException {
if (configurationKey.getDataType() != propertyType) { if (!configurationKey.getDataType().isAssignableFrom(propertyType)) {
throw new IllegalAccessError(String.format("The key %s does not handle values in the type %s.", throw new TenantConfigurationValidatorException(
configurationKey.getKeyName(), propertyType)); String.format("Cannot parse the database value of type %s into the type %s.",
configurationKey.getDataType(), propertyType));
} }
final TenantConfiguration tenantConfiguration = tenantConfigurationRepository final TenantConfiguration tenantConfiguration = tenantConfigurationRepository
@@ -76,42 +90,132 @@ public class TenantConfigurationManagement implements EnvironmentAware {
.value(conversionService.convert(tenantConfiguration.getValue(), propertyType)).build(); .value(conversionService.convert(tenantConfiguration.getValue(), propertyType)).build();
} else if (configurationKey.getDefaultKeyName() != null) { } else if (configurationKey.getDefaultKeyName() != null) {
final T valueInProperties = environment.getProperty(configurationKey.getDefaultKeyName(), propertyType);
return TenantConfigurationValue.<T> builder().isGlobal(true).createdBy(null).createdAt(null) return TenantConfigurationValue.<T> builder().isGlobal(true).createdBy(null).createdAt(null)
.lastModifiedAt(null).lastModifiedBy(null).value(valueInProperties != null ? valueInProperties .lastModifiedAt(null).lastModifiedBy(null)
: conversionService.convert(configurationKey.getDefaultValue(), propertyType)) .value(getGlobalConfigurationValue(configurationKey, propertyType)).build();
.build();
} }
return null; return null;
} }
/** /**
* Adds or updates a specific configuration for a specific tenant. * Retrieves a configuration value from the e.g. tenant overwritten
* configuration values or in case the tenant does not a have a specific
* configuration the global default value hold in the {@link Environment}.
* *
* @param tenantConf * @param configurationKey
* the tenant configuration object which contains the key and * the key of the configuration
* value of the specific configuration to update * @return the converted configuration value either from the tenant specific
* @return the added or updated TenantConfiguration * configuration stored or from the fallback default values or
* {@code null} in case key has not been configured and not default
* value exists
* @throws TenantConfigurationValidatorException
* if the {@code propertyType} and the value in general does not
* match the expected type and format defined by the Key
* @throws ConversionFailedException
* if the property cannot be converted to the given
* {@code propertyType}
*/ */
@CacheEvict(value = "tenantConfiguration", key = "#tenantConf.getKey()") public TenantConfigurationValue<?> getConfigurationValue(final TenantConfigurationKey configurationKey)
@Transactional throws TenantConfigurationValidatorException {
@Modifying return getConfigurationValue(configurationKey, configurationKey.getDataType());
public void addOrUpdateConfiguration(final TenantConfigurationKey tenantConfkey, final Object value) {
tenantConfkey.validate(applicationContext, value);
TenantConfiguration tenantConfiguration = tenantConfigurationRepository.findByKey(tenantConfkey.getKeyName());
if (tenantConfiguration != null) {
tenantConfiguration.setValue(value.toString());
} else {
tenantConfiguration = new TenantConfiguration(tenantConfkey.getKeyName(), value.toString());
}
tenantConfigurationRepository.save(tenantConfiguration);
} }
/** /**
* Deletes a specific configuration for the current tenant. * returns the global configuration property either defined in the property
* file or an default value otherwise.
*
* @param <T>
* the type of the configuration value
* @param configurationKey
* the key of the configuration
* @param propertyType
* the type of the configuration value, e.g. {@code String.class}
* , {@code Integer.class}, etc
* @return the global configured value
* @throws TenantConfigurationValidatorException
* if the {@code propertyType} and the value in the property
* file or the default value does not match the expected type
* and format defined by the Key
* @throws ConversionFailedException
* if the property cannot be converted to the given
* {@code propertyType}
*/
@Cacheable(value = "tenantConfiguration", key = "#configurationKey.getKeyName()")
public <T> T getGlobalConfigurationValue(final TenantConfigurationKey configurationKey, final Class<T> propertyType)
throws TenantConfigurationValidatorException {
if (!configurationKey.getDataType().isAssignableFrom(propertyType)) {
throw new TenantConfigurationValidatorException(
String.format("Cannot parse the database value of type %s into the type %s.",
configurationKey.getDataType(), propertyType));
}
final T valueInProperties = environment.getProperty(configurationKey.getDefaultKeyName(), propertyType);
if (valueInProperties != null) {
return valueInProperties;
}
return conversionService.convert(configurationKey.getDefaultValue(), propertyType);
}
/**
* Adds or updates a specific configuration for a specific tenant.
*
*
* @param configurationKey
* the key of the configuration
* @param value
* the configuration value which will be written into the
* database.
* @return the configuration value which was just written into the database.
* @throws TenantConfigurationValidatorException
* if the {@code propertyType} and the value in general does not
* match the expected type and format defined by the Key
* @throws ConversionFailedException
* if the property cannot be converted to the given
*/
@CacheEvict(value = "tenantConfiguration", key = "#configurationKey.getKeyName()")
@Transactional
@Modifying
public <T> TenantConfigurationValue<T> addOrUpdateConfiguration(final TenantConfigurationKey configurationKey,
final T value) {
if (!configurationKey.getDataType().isAssignableFrom(value.getClass())) {
throw new TenantConfigurationValidatorException(String.format(
"Cannot parse the value %s of type %s into the type %s defined by the configuration key.", value,
value.getClass(), configurationKey.getDataType()));
}
configurationKey.validate(applicationContext, value);
TenantConfiguration tenantConfiguration = tenantConfigurationRepository
.findByKey(configurationKey.getKeyName());
if (tenantConfiguration != null)
{
tenantConfiguration.setValue(value.toString());
} else
{
tenantConfiguration = new TenantConfiguration(configurationKey.getKeyName(), value.toString());
}
final TenantConfiguration updatedTenantConfiguration = tenantConfigurationRepository.save(tenantConfiguration);
final Class<T> clazzT = (Class<T>) value.getClass();
return TenantConfigurationValue.<T> builder().isGlobal(false)
.createdBy(updatedTenantConfiguration.getCreatedBy())
.createdAt(updatedTenantConfiguration.getCreatedAt())
.lastModifiedAt(updatedTenantConfiguration.getLastModifiedAt())
.lastModifiedBy(updatedTenantConfiguration.getLastModifiedBy())
.value(conversionService.convert(updatedTenantConfiguration.getValue(), clazzT)).build();
}
/**
* Deletes a specific configuration for the current tenant. Does nothing in
* case there is no tenant specific configuration value.
* *
* @param configurationKey * @param configurationKey
* the configuration key to be deleted * the configuration key to be deleted
@@ -123,12 +227,6 @@ public class TenantConfigurationManagement implements EnvironmentAware {
tenantConfigurationRepository.deleteByKey(configurationKey.getKeyName()); tenantConfigurationRepository.deleteByKey(configurationKey.getKeyName());
} }
// @Transactional
// public List<TenantConfiguration> getTenantConfigurations() {
//
// return tenantConfigurationRepository.findAll();
// }
@Override @Override
public void setEnvironment(final Environment environment) { public void setEnvironment(final Environment environment) {
this.environment = environment; this.environment = environment;

View File

@@ -11,8 +11,10 @@ import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.validator.exceptions.TenantConfigurationValidatorException; import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
import org.springframework.core.convert.ConversionFailedException;
import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Features;
@@ -84,7 +86,7 @@ public class TenantConfigurationManagementTest extends AbstractIntegrationTestWi
.isEqualTo(value2); .isEqualTo(value2);
} }
@Test(expected = TenantConfigurationValidatorException.class) @Test(expected = ConversionFailedException.class)
@Description("Tests that the get configuration throws exception in case the value cannot be automatically converted from String to Boolean") @Description("Tests that the get configuration throws exception in case the value cannot be automatically converted from String to Boolean")
public void wrongTenantConfigurationValueTypeThrowsException() { public void wrongTenantConfigurationValueTypeThrowsException() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED; final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED;
@@ -179,10 +181,16 @@ public class TenantConfigurationManagementTest extends AbstractIntegrationTestWi
assertThat(duration).isEqualTo(durationHelper.formattedStringToDuration(storedDurationString)); assertThat(duration).isEqualTo(durationHelper.formattedStringToDuration(storedDurationString));
} }
@Test(expected = IllegalAccessError.class) @Test
@Description("Request a config value in a wrong Value") @Description("Request a config value in a wrong Value")
public void requestConfigValueWithWrongType() { public void requestConfigValueWithWrongType() {
tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, Object.class); try {
tenantConfigurationManagement.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL,
Object.class);
Assert.fail("");
} catch (final TenantConfigurationValidatorException e) {
}
} }
@Test @Test

View File

@@ -1,105 +0,0 @@
package org.eclipse.hawkbit.rest.resource.model.system;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A json annotated rest model for System Configuration for PUT.
*/
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SystemConfigurationRequestBodyPut {
@JsonProperty
private String pollingTime;
@JsonProperty
private String pollingOverdueTime;
@JsonProperty
private String defaultDistributionSetType;
@JsonProperty
private Map<String, Object> authenticationConfiguration;
/**
* Gets the polling time.
*
* @return the polling time
*/
public String getPollingTime() {
return pollingTime;
}
/**
* Sets the polling time.
*
* @param pollingTime
* the new polling time
*/
public void setPollingTime(String pollingTime) {
this.pollingTime = pollingTime;
}
/**
* Gets the polling overdue time.
*
* @return the polling overdue time
*/
public String getPollingOverdueTime() {
return pollingOverdueTime;
}
/**
* Sets the polling overdue time.
*
* @param pollingOverdueTime
* the new polling overdue time
*/
public void setPollingOverdueTime(String pollingOverdueTime) {
this.pollingOverdueTime = pollingOverdueTime;
}
/**
* Gets the default distribution set type.
*
* @return the default distribution set type
*/
public String getDefaultDistributionSetType() {
return defaultDistributionSetType;
}
/**
* Sets the default distribution set type.
*
* @param defaultDistributionSetType
* the new default distribution set type
*/
public void setDefaultDistributionSetType(String defaultDistributionSetType) {
this.defaultDistributionSetType = defaultDistributionSetType;
}
/**
* Gets the authentication configuration.
*
* @return the authentication configuration
*/
public Map<String, Object> getAuthenticationConfiguration() {
return authenticationConfiguration;
}
/**
* Sets the authentication configuration.
*
* @param authenticationConfiguration
* the authentication configuration
*/
public void setAuthenticationConfiguration(Map<String, Object> authenticationConfiguration) {
this.authenticationConfiguration = authenticationConfiguration;
}
}

View File

@@ -1,40 +0,0 @@
package org.eclipse.hawkbit.rest.resource.model.system;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A json annotated rest model for SysteConfiguration to RESTful API
* representation.
*
*/
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class SystemConfigurationRest {
@JsonProperty
private Map<String, TenantConfigurationValueRest> configuration;
/**
* Sets the authentication configuration.
*
* @param configuration
* the authentication configuration
*/
public void setConfiguration(final Map<String, TenantConfigurationValueRest> configuration) {
this.configuration = configuration;
}
/**
* Gets the authentication configuration.
*
* @return the authentication configuration
*/
public Map<String, TenantConfigurationValueRest> getConfiguration() {
return this.configuration;
}
}

View File

@@ -21,7 +21,7 @@ import com.fasterxml.jackson.annotation.JsonInclude.Include;
public class TenantConfigurationRest { public class TenantConfigurationRest {
private String key; private String key;
private String value; private Object value;
/** /**
* @return the key * @return the key
@@ -41,7 +41,7 @@ public class TenantConfigurationRest {
/** /**
* @return the value * @return the value
*/ */
public String getValue() { public Object getValue() {
return value; return value;
} }
@@ -49,7 +49,7 @@ public class TenantConfigurationRest {
* @param value * @param value
* the value to set * the value to set
*/ */
public void setValue(final String value) { public void setValue(final Object value) {
this.value = value; this.value = value;
} }
} }

View File

@@ -0,0 +1,35 @@
package org.eclipse.hawkbit.rest.resource.model.system;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* A json annotated rest model for System Configuration for PUT.
*/
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class TenantConfigurationValueRequest {
@JsonProperty
private Object value;
/**
*
* @return the value of the TenantConfigurationValueRequest
*/
public Object getValue() {
return value;
}
/**
* Sets teh TenantConfigurationValueRequest
*
* @param value
*/
public void setValue(final Object value) {
this.value = value;
}
}

View File

@@ -66,6 +66,7 @@ public class ResponseExceptionHandler {
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ENTITY_LOCKED, HttpStatus.LOCKED); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ENTITY_LOCKED, HttpStatus.LOCKED);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ROLLOUT_ILLEGAL_STATE, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_ROLLOUT_ILLEGAL_STATE, HttpStatus.BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_INVALID, HttpStatus.BAD_REQUEST); ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_VALUE_INVALID, HttpStatus.BAD_REQUEST);
ERROR_TO_HTTP_STATUS.put(SpServerError.SP_CONFIGURATION_KEY_INVALID, HttpStatus.BAD_REQUEST);
} }
private static HttpStatus getStatusOrDefault(final SpServerError error) { private static HttpStatus getStatusOrDefault(final SpServerError error) {

View File

@@ -148,8 +148,8 @@ public class SystemManagementResource {
public ResponseEntity<Void> addUpdateConfig(@RequestBody final TenantConfigurationRest configuration, public ResponseEntity<Void> addUpdateConfig(@RequestBody final TenantConfigurationRest configuration,
@PathVariable final String key) { @PathVariable final String key) {
// TODO Quick and dirty to stay compatible, but these rest interface // TODO Quick and dirty solution to stay compatible, but these rest
// won't be necessary in future // interface won't be necessary in future
Object value; Object value;
if (configuration.getValue().equals(Boolean.TRUE)) { if (configuration.getValue().equals(Boolean.TRUE)) {

View File

@@ -5,50 +5,55 @@ import java.util.Map;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.rest.resource.model.system.SystemConfigurationRest;
import org.eclipse.hawkbit.rest.resource.model.system.TenantConfigurationValueRest; import org.eclipse.hawkbit.rest.resource.model.system.TenantConfigurationValueRest;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A mapper which maps repository model to RESTful model representation and
* back.
*/
final public class SystemMapper { final public class SystemMapper {
private static final Logger LOG = LoggerFactory.getLogger(SystemMapper.class);
private SystemMapper() { private SystemMapper() {
// Utility class // Utility class
} }
private static DurationHelper dh = new DurationHelper(); /**
* @param tenantConfigurationManagement
public static SystemConfigurationRest toResponse( * instance of TenantConfigurationManagement
* @return a map of all existing configuration values
*/
public static Map<String, TenantConfigurationValueRest> toResponse(
final TenantConfigurationManagement tenantConfigurationManagement) { final TenantConfigurationManagement tenantConfigurationManagement) {
final SystemConfigurationRest sysconf = new SystemConfigurationRest(); final Map<String, TenantConfigurationValueRest> configurationMap = new HashMap<String, TenantConfigurationValueRest>();
final Map<String, TenantConfigurationValueRest> authconf = new HashMap<String, TenantConfigurationValueRest>();
for (final TenantConfigurationKey key : TenantConfigurationKey.values()) { for (final TenantConfigurationKey key : TenantConfigurationKey.values()) {
final TenantConfigurationValueRest value = toResponse( configurationMap.put(key.getKeyName(),
tenantConfigurationManagement.getConfigurationValue(key, key.getDataType())); toResponse(tenantConfigurationManagement.getConfigurationValue(key)));
authconf.put(key.getKeyName(), value);
}
sysconf.setConfiguration(authconf);
return sysconf;
} }
public static TenantConfigurationValueRest toResponse(final TenantConfigurationValue<?> confValue) { return configurationMap;
final TenantConfigurationValueRest response = new TenantConfigurationValueRest(); }
response.setValue(confValue.getValue()); /**
response.setGlobal(confValue.isGlobal()); * maps a TenantConfigurationValue from the repository model to a
response.setCreatedAt(confValue.getCreatedAt()); * TenantConfigurationValueRest, the RESTful model.
response.setCreatedBy(confValue.getCreatedBy()); *
response.setLastModifiedAt(confValue.getLastModifiedAt()); * @param repoConfValue
response.setLastModifiedBy(confValue.getLastModifiedBy()); * configuration value as repository model
* @return configuration value as RESTful model
*/
public static TenantConfigurationValueRest toResponse(final TenantConfigurationValue<?> repoConfValue) {
final TenantConfigurationValueRest restConfValue = new TenantConfigurationValueRest();
return response; restConfValue.setValue(repoConfValue.getValue());
restConfValue.setGlobal(repoConfValue.isGlobal());
restConfValue.setCreatedAt(repoConfValue.getCreatedAt());
restConfValue.setCreatedBy(repoConfValue.getCreatedBy());
restConfValue.setLastModifiedAt(repoConfValue.getLastModifiedAt());
restConfValue.setLastModifiedBy(repoConfValue.getLastModifiedBy());
return restConfValue;
} }
} }

View File

@@ -1,46 +1,115 @@
package org.eclipse.hawkbit.rest.resource; package org.eclipse.hawkbit.rest.resource;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import java.util.Map;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.rest.resource.model.system.SystemConfigurationRequestBodyPut; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.rest.resource.model.system.SystemConfigurationRest; import org.eclipse.hawkbit.rest.resource.model.system.TenantConfigurationValueRequest;
import org.eclipse.hawkbit.rest.resource.model.system.TenantConfigurationValueRest;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/**
* REST Resource handling tenant specific configuration operations.
*
*
*
*
*/
@RestController @RestController
@RequestMapping(RestConstants.SYSTEM_V1_REQUEST_MAPPING) @RequestMapping(RestConstants.SYSTEM_V1_REQUEST_MAPPING)
public class SystemResource { public class SystemResource {
private static final Logger LOGGER = LoggerFactory.getLogger(SystemResource.class); private static final Logger LOG = LoggerFactory.getLogger(SystemResource.class);
@Autowired @Autowired
private TenantConfigurationManagement tenantConfigurationManagement; private TenantConfigurationManagement tenantConfigurationManagement;
@Autowired /**
private DistributionSetManagement distributionSetManagement; * @return a Map of all configuration values.
*/
@RequestMapping(method = RequestMethod.GET, value = "/conf", produces = { "application/hal+json", @RequestMapping(method = RequestMethod.GET, value = "/conf", produces = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE }) MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<SystemConfigurationRest> getSystemConfiguration() { public ResponseEntity<Map<String, TenantConfigurationValueRest>> getSystemConfiguration() {
return new ResponseEntity<>(SystemMapper.toResponse(tenantConfigurationManagement), HttpStatus.OK); return new ResponseEntity<>(SystemMapper.toResponse(tenantConfigurationManagement), HttpStatus.OK);
} }
@RequestMapping(method = RequestMethod.PUT, value = "/conf", consumes = { "application/hal+json", /**
* 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.
*/
@RequestMapping(method = RequestMethod.DELETE, value = "/conf/{keyName}", produces = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<Void> deleteConfigurationValue(@PathVariable 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.OK);
}
/**
* 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.
*/
@RequestMapping(method = RequestMethod.GET, value = "/conf/{keyName}", produces = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<TenantConfigurationValueRest> getConfigurationValue(@PathVariable final String keyName) {
final TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
LOG.debug("{} config value getted, return status {}", keyName, HttpStatus.OK);
return new ResponseEntity<>(
SystemMapper.toResponse(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.
*/
@RequestMapping(method = RequestMethod.PUT, value = "/conf/{keyName}", consumes = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE }) MediaType.APPLICATION_JSON_VALUE }, produces = { "application/hal+json", MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<SystemConfigurationRest> updateSoftwareModuleType( public ResponseEntity<TenantConfigurationValueRest> updateConfigurationValue(@PathVariable final String keyName,
@RequestBody final SystemConfigurationRequestBodyPut systemConReq) { @RequestBody final TenantConfigurationValueRequest configurationValueRest) {
// systemManagement.updateTenantConfiguration(systemConReq); final TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
return new ResponseEntity<>(SystemMapper.toResponse(tenantConfigurationManagement), HttpStatus.OK); final TenantConfigurationValue<Object> updatedValue = tenantConfigurationManagement
.addOrUpdateConfiguration(configKey, configurationValueRest.getValue());
return new ResponseEntity<>(SystemMapper.toResponse(updatedValue), HttpStatus.OK);
} }
} }

View File

@@ -62,8 +62,10 @@ public class PollingConfigurationView extends BaseConfigurationView
minDuration = durationHelper.formattedStringToDuration(controllerPollProperties.getMinPollingTime()); minDuration = durationHelper.formattedStringToDuration(controllerPollProperties.getMinPollingTime());
maxDuration = durationHelper.formattedStringToDuration(controllerPollProperties.getMaxPollingTime()); maxDuration = durationHelper.formattedStringToDuration(controllerPollProperties.getMaxPollingTime());
globalPollTime = durationHelper.formattedStringToDuration(controllerPollProperties.getPollingTime()); globalPollTime = durationHelper.formattedStringToDuration(tenantConfigurationManagement
globalOverdueTime = durationHelper.formattedStringToDuration(controllerPollProperties.getPollingOverdueTime()); .getGlobalConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class));
globalOverdueTime = durationHelper.formattedStringToDuration(tenantConfigurationManagement
.getGlobalConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class));
final TenantConfigurationValue<String> pollTimeConfValue = tenantConfigurationManagement final TenantConfigurationValue<String> pollTimeConfValue = tenantConfigurationManagement
.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class); .getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class);