Refactor tenant configuration management (#2840)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -27,17 +27,17 @@ import org.springframework.core.Ordered;
|
||||
public class ExceptionMappingAspectHandler implements Ordered {
|
||||
|
||||
/**
|
||||
* Catches exceptions of the {@link TransactionManager} and wrap them to custom exceptions.
|
||||
* Catches exceptions the {@link TransactionManager} and wrap them to custom exceptions.
|
||||
*
|
||||
* @param ex the thrown and catched exception
|
||||
* @throws Throwable
|
||||
* @param e the thrown and caught exception
|
||||
* @throws Throwable the mapped exception
|
||||
*/
|
||||
@AfterThrowing(pointcut = "execution( * org.eclipse.hawkbit.repository.jpa.management.*Management.*(..))", throwing = "ex")
|
||||
@AfterThrowing(pointcut = "execution( * org.eclipse.hawkbit.repository.jpa.management.*Management.*(..))", throwing = "e")
|
||||
// Exception for squid:S00112, squid:S1162
|
||||
// It is a AspectJ proxy which deals with exceptions.
|
||||
@SuppressWarnings({ "squid:S00112", "squid:S1162" })
|
||||
public void catchAndWrapJpaExceptionsService(final Exception ex) throws Throwable {
|
||||
throw ExceptionMapper.map(ex);
|
||||
public void catchAndWrapJpaExceptionsService(final Exception e) throws Throwable {
|
||||
throw ExceptionMapper.map(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,19 +16,17 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationPrope
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.POLLING_TIME;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.NonNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.hawkbit.auth.SpPermission;
|
||||
import org.eclipse.hawkbit.context.AccessContext;
|
||||
@@ -95,7 +93,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(final ContextRefreshedEvent event) {
|
||||
public void onApplicationEvent(@NonNull final ContextRefreshedEvent event) {
|
||||
// Sets the proxy / bean from the context in order to be used via proxy and onore things like @PreAuthorize and @Transactional
|
||||
TenantConfigHelper.setTenantConfigurationManagement(applicationContext.getBean(JpaTenantConfigurationManagement.class));
|
||||
}
|
||||
@@ -104,25 +102,25 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public <T extends Serializable> TenantConfigurationValue<T> addOrUpdateConfiguration(final String keyName, final T value) {
|
||||
return addOrUpdateConfiguration0(Map.of(keyName, value)).values().iterator().next();
|
||||
public void addOrUpdateConfiguration(final String keyName, final Object value) {
|
||||
addOrUpdateConfiguration0(Map.of(keyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public <T extends Serializable> Map<String, TenantConfigurationValue<T>> addOrUpdateConfiguration(final Map<String, T> configurations) {
|
||||
return addOrUpdateConfiguration0(configurations);
|
||||
public void addOrUpdateConfiguration(final Map<String, Object> configurations) {
|
||||
addOrUpdateConfiguration0(configurations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Serializable> TenantConfigurationValue<T> getConfigurationValue(final String keyName) {
|
||||
public <T> TenantConfigurationValue<T> getConfigurationValue(final String keyName) {
|
||||
return getConfigurationValue0(keyName, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Serializable> TenantConfigurationValue<T> getConfigurationValue(final String keyName, final Class<T> propertyType) {
|
||||
public <T> TenantConfigurationValue<T> getConfigurationValue(final String keyName, final Class<T> propertyType) {
|
||||
return getConfigurationValue0(keyName, propertyType);
|
||||
}
|
||||
|
||||
@@ -178,56 +176,47 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
}
|
||||
|
||||
private void checkAccess(final String keyName) {
|
||||
if (AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY.equalsIgnoreCase(keyName)) {
|
||||
if (!AccessContext.isCurrentThreadSystemCode() && !SpPermission.hasPermission(READ_GATEWAY_SECURITY_TOKEN)) {
|
||||
throw new InsufficientPermissionException(
|
||||
"Can't read gateway security token! " + READ_GATEWAY_SECURITY_TOKEN + " is required!");
|
||||
}
|
||||
if (AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY.equalsIgnoreCase(keyName)
|
||||
&& !AccessContext.isCurrentThreadSystemCode() && !SpPermission.hasPermission(READ_GATEWAY_SECURITY_TOKEN)) {
|
||||
throw new InsufficientPermissionException("Can't read gateway security token! " + READ_GATEWAY_SECURITY_TOKEN + " is required!");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Serializable> Map<String, TenantConfigurationValue<T>> addOrUpdateConfiguration0(final Map<String, T> configurations) {
|
||||
final List<JpaTenantConfiguration> configurationList = new ArrayList<>();
|
||||
configurations.forEach((keyName, value) -> {
|
||||
final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(keyName);
|
||||
private void addOrUpdateConfiguration0(final Map<String, Object> configurations) {
|
||||
tenantConfigurationRepository.saveAll(configurations.entrySet().stream().map(e -> {
|
||||
final TenantConfigurationKey configurationKey = tenantConfigurationProperties.fromKeyName(e.getKey());
|
||||
|
||||
final Class<?> targetType = configurationKey.getDataType();
|
||||
Object convertedValue = getConvertedValue(value, targetType);
|
||||
validateConfigurationValue(value, configurationKey, convertedValue);
|
||||
final Object convertedValue;
|
||||
try {
|
||||
convertedValue = CONVERSION_SERVICE.convert(e.getValue(), targetType);
|
||||
} catch (final ConversionException | IllegalArgumentException ex) {
|
||||
throw new TenantConfigurationValidatorException(String.format(
|
||||
"Cannot convert the value %s of type %s to the type %s defined by the configuration key.",
|
||||
e.getValue(), e.getValue().getClass(), targetType));
|
||||
}
|
||||
final String valueToString = Optional.ofNullable(convertedValue)
|
||||
.map(Object::toString)
|
||||
.orElse(null);
|
||||
validateConfigurationValue(configurationKey, convertedValue);
|
||||
|
||||
JpaTenantConfiguration tenantConfiguration = tenantConfigurationRepository.findByKey(configurationKey.getKeyName());
|
||||
if (tenantConfiguration == null) {
|
||||
tenantConfiguration = new JpaTenantConfiguration(configurationKey.getKeyName(), convertedValue.toString());
|
||||
tenantConfiguration = new JpaTenantConfiguration(configurationKey.getKeyName(), valueToString);
|
||||
} else {
|
||||
tenantConfiguration.setValue(convertedValue.toString());
|
||||
tenantConfiguration.setValue(valueToString);
|
||||
}
|
||||
|
||||
assertValueChangeIsAllowed(keyName, tenantConfiguration);
|
||||
configurationList.add(tenantConfiguration);
|
||||
});
|
||||
return tenantConfigurationRepository.saveAll(configurationList).
|
||||
stream().
|
||||
collect(Collectors.toMap(
|
||||
JpaTenantConfiguration::getKey,
|
||||
updatedTenantConfiguration -> TenantConfigurationValue.<T> builder()
|
||||
.global(false)
|
||||
.createdBy(updatedTenantConfiguration.getCreatedBy())
|
||||
.createdAt(updatedTenantConfiguration.getCreatedAt())
|
||||
.lastModifiedAt(updatedTenantConfiguration.getLastModifiedAt())
|
||||
.lastModifiedBy(updatedTenantConfiguration.getLastModifiedBy())
|
||||
.value(CONVERSION_SERVICE.convert(
|
||||
updatedTenantConfiguration.getValue(),
|
||||
(Class<T>) configurations.get(updatedTenantConfiguration.getKey()).getClass()))
|
||||
.build()));
|
||||
assertValueChangeIsAllowed(e.getKey(), tenantConfiguration);
|
||||
return tenantConfiguration;
|
||||
}).toList());
|
||||
}
|
||||
|
||||
private <T extends Serializable> void validateConfigurationValue(final T value, final TenantConfigurationKey configurationKey,
|
||||
final Object convertedValue) {
|
||||
configurationKey.validate(convertedValue, applicationContext);
|
||||
private void validateConfigurationValue(final TenantConfigurationKey configurationKey, final Object value) {
|
||||
configurationKey.validate(value, applicationContext);
|
||||
// additional validation for specific configuration keys
|
||||
if (POLLING_TIME.equals(configurationKey.getKeyName())) {
|
||||
final PollingTime pollingTime = new PollingTime(value.toString());
|
||||
final PollingTime pollingTime = new PollingTime(String.valueOf(value));
|
||||
if (!ObjectUtils.isEmpty(pollingTime.getOverrides())) {
|
||||
// validate that the QL strings are valid RSQL queries,
|
||||
// nevertheless always when parse them we shall be prepared to catch exceptions if the parsers
|
||||
@@ -237,62 +226,36 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
}
|
||||
}
|
||||
|
||||
private static <T extends Serializable> Object getConvertedValue(final T value, final Class<?> targetType) {
|
||||
Object convertedValue = value;
|
||||
if (!targetType.isAssignableFrom(value.getClass())) {
|
||||
try {
|
||||
// if not assignable and it is a number - try conversion
|
||||
// for example tries to assign Integer to Long
|
||||
if (value instanceof Number number && Number.class.isAssignableFrom(targetType)) {
|
||||
log.debug("Type {} not assignable from {} . Will try conversion.", targetType, value.getClass());
|
||||
convertedValue = CONVERSION_SERVICE.convert(number, targetType);
|
||||
if (convertedValue == null) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Failed to convert %s. Convertor returned null as a result", value));
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Value %s is not a Number but %s and cannot perform conversion converted.", value, value.getClass()));
|
||||
}
|
||||
} catch (final ConversionException | IllegalArgumentException ex) {
|
||||
throw new TenantConfigurationValidatorException(String.format(
|
||||
"Cannot convert the value %s of type %s to the type %s defined by the configuration key.",
|
||||
value, value.getClass(), targetType));
|
||||
}
|
||||
}
|
||||
return convertedValue;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Serializable> TenantConfigurationValue<T> getConfigurationValue0(final String keyName, final Class<T> propertyType) {
|
||||
private <T> TenantConfigurationValue<T> getConfigurationValue0(final String keyName, final Class<T> propertyType) {
|
||||
checkAccess(keyName);
|
||||
|
||||
final TenantConfigurationKey key = tenantConfigurationProperties.fromKeyName(keyName);
|
||||
if (propertyType != null) {
|
||||
final Class<T> type;
|
||||
if (propertyType == null) {
|
||||
type = (Class<T>) key.getDataType();
|
||||
} else {
|
||||
validateTenantConfigurationDataType(key, propertyType);
|
||||
type = propertyType;
|
||||
}
|
||||
|
||||
final TenantConfiguration tenantConfiguration = TenantAwareCacheManager.getInstance().getCache(CACHE_TENANT_CONFIGURATION_NAME)
|
||||
final TenantConfiguration tenantConfiguration = TenantAwareCacheManager.getInstance()
|
||||
.getCache(CACHE_TENANT_CONFIGURATION_NAME)
|
||||
.get(key.getKeyName(), () -> tenantConfigurationRepository.findByKey(key.getKeyName()));
|
||||
return buildTenantConfigurationValueByKey(key, propertyType == null ? (Class<T>) key.getDataType() : propertyType, tenantConfiguration);
|
||||
}
|
||||
|
||||
private <T extends Serializable> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(
|
||||
final TenantConfigurationKey configurationKey, final Class<T> propertyType, final TenantConfiguration tenantConfiguration) {
|
||||
if (tenantConfiguration != null) {
|
||||
return TenantConfigurationValue.<T> builder().global(false)
|
||||
return TenantConfigurationValue.<T> builder()
|
||||
.global(false)
|
||||
.createdBy(tenantConfiguration.getCreatedBy())
|
||||
.createdAt(tenantConfiguration.getCreatedAt())
|
||||
.lastModifiedAt(tenantConfiguration.getLastModifiedAt())
|
||||
.lastModifiedBy(tenantConfiguration.getLastModifiedBy())
|
||||
.value(CONVERSION_SERVICE.convert(tenantConfiguration.getValue(), propertyType)).build();
|
||||
} else if (configurationKey.getDefaultValue() != null) {
|
||||
return TenantConfigurationValue.<T> builder().global(true)
|
||||
.createdBy(null)
|
||||
.createdAt(null)
|
||||
.lastModifiedAt(null)
|
||||
.lastModifiedBy(null)
|
||||
.value(getGlobalConfigurationValue0(configurationKey.getKeyName(), propertyType)).build();
|
||||
.value(CONVERSION_SERVICE.convert(tenantConfiguration.getValue(), type))
|
||||
.build();
|
||||
} else if (key.getDefaultValue() != null) {
|
||||
return TenantConfigurationValue.<T> builder()
|
||||
.global(true)
|
||||
.value(getGlobalConfigurationValue0(key.getKeyName(), type))
|
||||
.build();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@@ -342,7 +305,9 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
|
||||
private void assertAutoCloseValueChange(final String key) {
|
||||
if (REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED.equals(key)
|
||||
&& Boolean.TRUE.equals(getConfigurationValue0(MULTI_ASSIGNMENTS_ENABLED, Boolean.class).getValue())) {
|
||||
&& Boolean.TRUE.equals(Optional.ofNullable(getConfigurationValue0(MULTI_ASSIGNMENTS_ENABLED, Boolean.class))
|
||||
.map(TenantConfigurationValue::getValue)
|
||||
.orElse(null))) {
|
||||
log.debug("The property '{}' must not be changed because the Multi-Assignments feature is currently enabled.", key);
|
||||
throw new TenantConfigurationValueChangeNotAllowedException();
|
||||
}
|
||||
@@ -350,7 +315,7 @@ public class JpaTenantConfigurationManagement implements TenantConfigurationMana
|
||||
|
||||
private void assertBatchAssignmentValueChange(final String key, final JpaTenantConfiguration valueChange) {
|
||||
if (BATCH_ASSIGNMENTS_ENABLED.equals(key) && Boolean.parseBoolean(valueChange.getValue())) {
|
||||
JpaTenantConfiguration multiConfig = tenantConfigurationRepository.findByKey(MULTI_ASSIGNMENTS_ENABLED);
|
||||
final JpaTenantConfiguration multiConfig = tenantConfigurationRepository.findByKey(MULTI_ASSIGNMENTS_ENABLED);
|
||||
if (multiConfig != null && Boolean.parseBoolean(multiConfig.getValue())) {
|
||||
log.debug(
|
||||
"The Batch-Assignments '{}' feature cannot be enabled as it contradicts with the Multi-Assignments feature, which is already enabled .",
|
||||
|
||||
@@ -188,7 +188,7 @@ class AutoActionCleanupTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(actionRepository.count()).isEqualTo(3);
|
||||
|
||||
// wait for expiry to elapse
|
||||
Thread.sleep(800);
|
||||
waitMillis(800);
|
||||
|
||||
autoActionCleanup.run();
|
||||
|
||||
|
||||
@@ -77,16 +77,19 @@ class DistributedLockTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Bean
|
||||
LockRepository lockRepository0(final DataSource dataSource, final LockProperties lockProperties, final PlatformTransactionManager txManager) {
|
||||
LockRepository lockRepository0(final DataSource dataSource, final LockProperties lockProperties,
|
||||
final PlatformTransactionManager txManager) {
|
||||
return lockRepository(dataSource, lockProperties, txManager);
|
||||
}
|
||||
|
||||
@Bean
|
||||
LockRepository lockRepository1(final DataSource dataSource, final LockProperties lockProperties, final PlatformTransactionManager txManager) {
|
||||
LockRepository lockRepository1(final DataSource dataSource, final LockProperties lockProperties,
|
||||
final PlatformTransactionManager txManager) {
|
||||
return lockRepository(dataSource, lockProperties, txManager);
|
||||
}
|
||||
|
||||
private LockRepository lockRepository(final DataSource dataSource, final LockProperties lockProperties, final PlatformTransactionManager txManager) {
|
||||
private LockRepository lockRepository(final DataSource dataSource, final LockProperties lockProperties,
|
||||
final PlatformTransactionManager txManager) {
|
||||
final DefaultLockRepository repository = new DistributedLockRepository(dataSource, lockProperties, txManager);
|
||||
repository.setPrefix("SP_");
|
||||
return repository;
|
||||
@@ -96,7 +99,7 @@ class DistributedLockTest extends AbstractJpaIntegrationTest {
|
||||
/**
|
||||
* Test to verify that lock is kept while ping runs
|
||||
*/
|
||||
@SuppressWarnings({"java:S2925"})
|
||||
@SuppressWarnings({ "java:S2925" })
|
||||
@Test
|
||||
void keepLockAlive() {
|
||||
final LockRegistry lockRegistry0 = new JdbcLockRegistry(lockRepository0);
|
||||
@@ -119,13 +122,13 @@ class DistributedLockTest extends AbstractJpaIntegrationTest {
|
||||
final AtomicBoolean lock11Locked = new AtomicBoolean(); // state of the lock11
|
||||
log.info("Starting test");
|
||||
// service 0 must be able to lock lockKey0
|
||||
assertThat(lock00.tryLock()).isTrue();
|
||||
assertThat(lock00.tryLock()).isTrue();
|
||||
try {
|
||||
assertThat(lockRepository0.isAcquired(path0)).isTrue(); // check db state
|
||||
|
||||
|
||||
final Thread lockThread1 = new Thread(() -> {
|
||||
// asserts lockKey1 is free and could be locked
|
||||
assertThat(lock11.tryLock()).isTrue();
|
||||
assertThat(lock11.tryLock()).isTrue();
|
||||
assertThat(lockRepository1.isAcquired(path1)).isTrue(); // check db state
|
||||
|
||||
try {
|
||||
@@ -140,20 +143,14 @@ class DistributedLockTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(lock01.tryLock()).isFalse();
|
||||
assertThat(lockRepository1.isAcquired(path0)).isFalse(); // check db state
|
||||
|
||||
try {
|
||||
Thread.sleep(Math.min(1, lockProperties.getTtl() / 4));
|
||||
} catch (final InterruptedException e) {
|
||||
if (Thread.interrupted()) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
waitMillis(Math.min(1, lockProperties.getTtl() / 4));
|
||||
}
|
||||
} catch (final AssertionError e) {
|
||||
} catch (final AssertionError e) {
|
||||
log.error("lockRepository1 has locked lockKey0 which has to be in lockRepository0 possession!", e);
|
||||
lock01Obtained.set(true);
|
||||
lock01.unlock();
|
||||
}
|
||||
|
||||
|
||||
assertThat(lockRepository0.isAcquired(path1)).isFalse(); // check db state
|
||||
assertThat(lockRepository1.isAcquired(path1)).isTrue(); // check db state
|
||||
} finally {
|
||||
@@ -183,13 +180,7 @@ class DistributedLockTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(Math.min(1, lockProperties.getTtl() / 4));
|
||||
} catch (final InterruptedException e) {
|
||||
if (Thread.interrupted()) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
waitMillis(Math.min(1, lockProperties.getTtl() / 4));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +196,7 @@ class DistributedLockTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(lock01Obtained).isFalse();
|
||||
// assert that service 1 has been able to acquire the lock 1
|
||||
assertThat(lock11Obtained).isTrue();
|
||||
|
||||
|
||||
assertThat(lockRepository0.isAcquired(path0)).isTrue(); // check db state
|
||||
assertThat(lockRepository1.isAcquired(path0)).isFalse(); // check db state
|
||||
} finally {
|
||||
|
||||
@@ -18,6 +18,8 @@ import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.NonNull;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidTenantConfigurationKeyException;
|
||||
import org.eclipse.hawkbit.repository.exception.TenantConfigurationValidatorException;
|
||||
@@ -28,6 +30,7 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.T
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.opentest4j.AssertionFailedError;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
@@ -48,7 +51,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment env) {
|
||||
public void setEnvironment(@NonNull final Environment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
@@ -86,12 +89,20 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(
|
||||
TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, newConfigurationValue2);
|
||||
|
||||
// sometimes it reads old value, maybe if read too early. wait to settle up?
|
||||
waitMillis(100);
|
||||
|
||||
// verify that new configuration value is used
|
||||
final TenantConfigurationValue<String> updatedConfigurationValue2 = tenantConfigurationManagement
|
||||
.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
||||
|
||||
assertThat(updatedConfigurationValue2.isGlobal()).isFalse();
|
||||
assertThat(updatedConfigurationValue2.getValue()).isEqualTo(newConfigurationValue2);
|
||||
try {
|
||||
assertThat(updatedConfigurationValue2.getValue()).isEqualTo(newConfigurationValue2);
|
||||
} catch (final AssertionFailedError e) {
|
||||
Awaitility.await().atMost(Duration.ofSeconds(20)).pollInterval(Duration.ofMillis(100))
|
||||
.untilAsserted(() -> assertThat(updatedConfigurationValue2.getValue()).isEqualTo(newConfigurationValue2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +128,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
*/
|
||||
@Test
|
||||
void batchUpdateTenantSpecificConfiguration() {
|
||||
final Map<String, Serializable> configuration = new HashMap<>() {{
|
||||
final Map<String, Object> configuration = new HashMap<>() {{
|
||||
put(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, "token_123");
|
||||
put(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, true);
|
||||
}};
|
||||
@@ -165,7 +176,7 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
*/
|
||||
@Test
|
||||
void batchWrongTenantConfigurationValueTypeThrowsException() {
|
||||
final Map<String, Serializable> configuration = new HashMap<>() {{
|
||||
final Map<String, Object> configuration = new HashMap<>() {{
|
||||
put(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, "token_123");
|
||||
put(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED, true);
|
||||
put(TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED, "wrong");
|
||||
@@ -216,12 +227,19 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
* Test that an Exception is thrown, when an integer is stored but a string expected.
|
||||
*/
|
||||
@Test
|
||||
void storesIntegerWhenStringIsExpected() {
|
||||
final String configKey = TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
||||
final Integer wrongDatType = 123;
|
||||
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDatType))
|
||||
void storesStringWhenIntegerIsExpected() {
|
||||
final String configKey = TenantConfigurationKey.ACTION_CLEANUP_ON_QUOTA_HIT_PERCENTAGE;
|
||||
final String wrongDataType = "123f";
|
||||
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataType))
|
||||
.as("Should not have worked as integer is not a string")
|
||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||
|
||||
final Integer correctDataType = 123;
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, String.valueOf(correctDataType));
|
||||
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, Integer.class).getValue()).isEqualTo(correctDataType);
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, correctDataType);
|
||||
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, Integer.class).getValue()).isEqualTo(correctDataType);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,10 +258,9 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
* Test that an Exception is thrown, when an integer is stored as PollingTime.
|
||||
*/
|
||||
@Test
|
||||
void storesIntegerWhenPollingIntervalIsExpected() {
|
||||
void storesBadPollingIntervalIsExpected() {
|
||||
final String configKey = TenantConfigurationKey.POLLING_TIME;
|
||||
final Integer wrongDataType = 123;
|
||||
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataType))
|
||||
assertThatThrownBy(() -> tenantConfigurationManagement.addOrUpdateConfiguration(configKey, "wrongDataType"))
|
||||
.as("Should not have worked as integer is not a time field")
|
||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||
}
|
||||
@@ -350,16 +367,6 @@ class TenantConfigurationManagementTest extends AbstractJpaIntegrationTest imple
|
||||
Assertions.assertEquals(2592000000L, autoCleanupDaysInMs);
|
||||
}
|
||||
|
||||
@Test
|
||||
void throwExceptionIfTryingToConvertOtherValueThanNumber() {
|
||||
final String configKey = TenantConfigurationKey.ACTION_CLEANUP_AUTO_EXPIRY;
|
||||
// set auto cleanup for 1 day in String ms
|
||||
assertThatThrownBy(() ->
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, "86400000"))
|
||||
.as("Cannot convert the value 86400000 of type String to the type Long defined by the configuration key.")
|
||||
.isInstanceOf(TenantConfigurationValidatorException.class);
|
||||
}
|
||||
|
||||
private static Duration getDurationByTimeValues(final long hours, final long minutes, final long seconds) {
|
||||
return Duration.ofHours(hours).plusMinutes(minutes).plusSeconds(seconds);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.eclipse.hawkbit.context.AccessContext;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
Reference in New Issue
Block a user