Custom Tenant configuration. (#395)

* Tenant configuration configurable.
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2016-12-23 07:19:46 +01:00
committed by GitHub
parent 4d35413f71
commit feb3369858
53 changed files with 730 additions and 447 deletions

View File

@@ -18,6 +18,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.transaction.annotation.Isolation;
@@ -78,6 +79,9 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
@Autowired
protected TenantAwareCacheManager cacheManager;
@Autowired
protected TenantConfigurationProperties tenantConfigurationProperties;
@Transactional(readOnly = true, isolation = Isolation.READ_UNCOMMITTED)
public List<Action> findActionsByRolloutAndStatus(final Rollout rollout, final Action.Status actionStatus) {
return actionRepository.findByRolloutAndStatus((JpaRollout) rollout, actionStatus);

View File

@@ -9,17 +9,17 @@
package org.eclipse.hawkbit.repository.jpa;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.fest.assertions.api.Assertions.fail;
import java.io.Serializable;
import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.tenancy.configuration.DurationHelper;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.InvalidTenantConfigurationKeyException;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationValidatorException;
import org.junit.Assert;
import org.junit.Test;
@@ -35,13 +35,13 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Tests that tenant specific configuration can be persisted and in case the tenant does not have specific configuration the default from environment is used instead.")
public void storeTenantSpecificConfigurationAsString() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME;
final String envPropertyDefault = environment.getProperty(configKey.getDefaultKeyName());
final String envPropertyDefault = environment
.getProperty("hawkbit.server.ddi.security.authentication.gatewaytoken.key");
assertThat(envPropertyDefault).isNotNull();
// get the configuration from the system management
final TenantConfigurationValue<String> defaultConfigValue = tenantConfigurationManagement
.getConfigurationValue(configKey, String.class);
final TenantConfigurationValue<String> defaultConfigValue = tenantConfigurationManagement.getConfigurationValue(
TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, String.class);
assertThat(defaultConfigValue.isGlobal()).isEqualTo(true);
assertThat(defaultConfigValue.getValue()).isEqualTo(envPropertyDefault);
@@ -49,11 +49,13 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
// update the tenant specific configuration
final String newConfigurationValue = "thisIsAnotherTokenName";
assertThat(newConfigurationValue).isNotEqualTo(defaultConfigValue.getValue());
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, newConfigurationValue);
tenantConfigurationManagement.addOrUpdateConfiguration(
TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, newConfigurationValue);
// verify that new configuration value is used
final TenantConfigurationValue<String> updatedConfigurationValue = tenantConfigurationManagement
.getConfigurationValue(configKey, String.class);
.getConfigurationValue(TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY,
String.class);
assertThat(updatedConfigurationValue.isGlobal()).isEqualTo(false);
assertThat(updatedConfigurationValue.getValue()).isEqualTo(newConfigurationValue);
@@ -63,7 +65,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Tests that the tenant specific configuration can be updated")
public void updateTenantSpecifcConfiguration() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME;
final String configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY;
final String value1 = "firstValue";
final String value2 = "secondValue";
@@ -81,7 +83,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Tests that the configuration value can be converted from String to Integer automatically")
public void storeAndUpdateTenantSpecificConfigurationAsBoolean() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED;
final String configKey = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED;
final Boolean value1 = true;
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, value1);
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, Boolean.class).getValue())
@@ -95,7 +97,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Tests that the get configuration throws exception in case the value cannot be automatically converted from String to Boolean")
public void wrongTenantConfigurationValueTypeThrowsException() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED;
final String configKey = TenantConfigurationKey.AUTHENTICATION_MODE_HEADER_ENABLED;
final String value1 = "thisIsNotABoolean";
// add value as String
@@ -110,13 +112,13 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Tests that a deletion of a tenant specific configuration deletes it from the database.")
public void deleteConfigurationReturnNullConfiguration() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY;
final String configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY;
// gateway token does not have default value so no configuration value
// is should be available
// should be available
final String defaultConfigValue = tenantConfigurationManagement.getConfigurationValue(configKey, String.class)
.getValue();
assertThat(defaultConfigValue).isNull();
assertThat(defaultConfigValue).isEmpty();
// update the tenant specific configuration
final String newConfigurationValue = "thisIsAnotherValueForPolling";
@@ -131,14 +133,14 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
// delete the tenant specific configuration
tenantConfigurationManagement.deleteConfiguration(configKey);
// ensure that now gateway token is set again, because is deleted and
// must be null now
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue()).isNull();
// must be empty now
assertThat(tenantConfigurationManagement.getConfigurationValue(configKey, String.class).getValue()).isEmpty();
}
@Test
@Description("Test that an Exception is thrown, when an integer is stored but a string expected.")
public void storesIntegerWhenStringIsExpected() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME;
final String configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY;
final Integer wrongDataype = 123;
try {
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataype);
@@ -151,7 +153,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Test that an Exception is thrown, when an integer is stored but a boolean expected.")
public void storesIntegerWhenBooleanIsExpected() {
final TenantConfigurationKey configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED;
final String configKey = TenantConfigurationKey.AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED;
final Integer wrongDataype = 123;
try {
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataype);
@@ -164,7 +166,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Test that an Exception is thrown, when an integer is stored as PollingTime.")
public void storesIntegerWhenPollingIntervalIsExpected() {
final TenantConfigurationKey configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final Integer wrongDataype = 123;
try {
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongDataype);
@@ -177,7 +179,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Test that an Exception is thrown, when an invalid formatted string is stored as PollingTime.")
public void storesWrongFormattedStringAsPollingInterval() {
final TenantConfigurationKey configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String wrongFormatted = "wrongFormatted";
try {
tenantConfigurationManagement.addOrUpdateConfiguration(configKey, wrongFormatted);
@@ -190,7 +192,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Test that an Exception is thrown, when an invalid formatted string is stored as PollingTime.")
public void storesTooSmallDurationAsPollingInterval() {
final TenantConfigurationKey configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String tooSmallDuration = DurationHelper
.durationToFormattedString(DurationHelper.getDurationByTimeValues(0, 0, 1));
@@ -205,7 +207,7 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Stores a correct formatted PollignTime and reads it again.")
public void storesCorrectDurationAsPollingInterval() {
final TenantConfigurationKey configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final Duration duration = DurationHelper.getDurationByTimeValues(1, 2, 0);
assertThat(duration).isEqualTo(Duration.ofHours(1).plusMinutes(2));
@@ -233,9 +235,9 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Verifies that every TenenatConfiguraationKeyName exists only once")
public void verifyThatAllKeysAreDifferent() {
final Map<String, Void> keynames = new HashMap<String, Void>();
final Map<String, Void> keynames = new HashMap<>();
Arrays.stream(TenantConfigurationKey.values()).forEach(key -> {
tenantConfigurationProperties.getConfigurationKeys().forEach(key -> {
if (keynames.containsKey(key.getKeyName())) {
throw new IllegalStateException("The key names are not unique");
@@ -248,9 +250,20 @@ public class TenantConfigurationManagementTest extends AbstractJpaIntegrationTes
@Test
@Description("Get TenantConfigurationKeyByName")
public void getTenantConfigurationKeyByName() {
final TenantConfigurationKey configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
final String configKey = TenantConfigurationKey.POLLING_TIME_INTERVAL;
assertThat(TenantConfigurationKey.fromKeyName(configKey.getKeyName())).isEqualTo(configKey);
assertThat(tenantConfigurationProperties.fromKeyName(configKey).getKeyName()).isEqualTo(configKey);
}
@Test
@Description("Tenant configuration which is not declared throws exception")
public void storeTenantConfigurationWhichIsNotDeclaredThrowsException() {
final String configKeyWhichDoesNotExists = "configKeyWhichDoesNotExists";
try {
tenantConfigurationManagement.addOrUpdateConfiguration(configKeyWhichDoesNotExists, "value");
fail("Expected InvalidTenantConfigurationKeyException for tenant configuration key which is not declared");
} catch (final InvalidTenantConfigurationKeyException e) {
// expected exception
}
}
}

View File

@@ -40,7 +40,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -61,7 +61,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
public class RSQLUtilityTest {
@Spy
private VirtualPropertyResolver macroResolver = new VirtualPropertyResolver();
private final VirtualPropertyResolver macroResolver = new VirtualPropertyResolver();
@Mock
private TenantConfigurationManagement confMgmt;
@@ -78,9 +78,9 @@ public class RSQLUtilityTest {
private Attribute attribute;
private static final TenantConfigurationValue<String> TEST_POLLING_TIME_INTERVAL = TenantConfigurationValue
.<String>builder().value("00:05:00").build();
.<String> builder().value("00:05:00").build();
private static final TenantConfigurationValue<String> TEST_POLLING_OVERDUE_TIME_INTERVAL = TenantConfigurationValue
.<String>builder().value("00:07:37").build();
.<String> builder().value("00:07:37").build();
@Test
public void wrongRsqlSyntaxThrowSyntaxException() {
@@ -111,8 +111,7 @@ public class RSQLUtilityTest {
String wrongRSQL = TargetFields.ATTRIBUTE + "==abc";
try {
RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock,
criteriaBuilderMock);
criteriaQueryMock, criteriaBuilderMock);
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
} catch (final RSQLParameterUnsupportedFieldException e) {
}
@@ -120,8 +119,7 @@ public class RSQLUtilityTest {
wrongRSQL = TargetFields.ATTRIBUTE + ".unkwon.wrong==abc";
try {
RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock,
criteriaBuilderMock);
criteriaQueryMock, criteriaBuilderMock);
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
} catch (final RSQLParameterUnsupportedFieldException e) {
}
@@ -141,8 +139,7 @@ public class RSQLUtilityTest {
String wrongRSQL = TargetFields.ASSIGNEDDS + "==abc";
try {
RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock,
criteriaBuilderMock);
criteriaQueryMock, criteriaBuilderMock);
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
} catch (final RSQLParameterUnsupportedFieldException e) {
}
@@ -150,8 +147,7 @@ public class RSQLUtilityTest {
wrongRSQL = TargetFields.ASSIGNEDDS + ".unknownField==abc";
try {
RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock,
criteriaBuilderMock);
criteriaQueryMock, criteriaBuilderMock);
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
} catch (final RSQLParameterUnsupportedFieldException e) {
}
@@ -159,8 +155,7 @@ public class RSQLUtilityTest {
wrongRSQL = TargetFields.ASSIGNEDDS + ".unknownField.ToMuch==abc";
try {
RSQLUtility.parse(wrongRSQL, TargetFields.class, null).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock,
criteriaBuilderMock);
criteriaQueryMock, criteriaBuilderMock);
fail("Missing expected RSQLParameterSyntaxException because of wrong RSQL syntax");
} catch (final RSQLParameterUnsupportedFieldException e) {
}
@@ -174,7 +169,7 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.get("version")).thenReturn(baseSoftwareModuleRootMock);
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.<String>greaterThanOrEqualTo(any(Expression.class), any(String.class)))
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
.thenReturn(mock(Predicate.class));
// test
@@ -192,7 +187,7 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.<String>greaterThanOrEqualTo(any(Expression.class), any(String.class)))
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
.thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock))))
.thenReturn(pathOfString(baseSoftwareModuleRootMock));
@@ -213,7 +208,7 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.<String>greaterThanOrEqualTo(any(Expression.class), any(String.class)))
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
.thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.upper(eq(pathOfString(baseSoftwareModuleRootMock))))
.thenReturn(pathOfString(baseSoftwareModuleRootMock));
@@ -234,7 +229,7 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.get("name")).thenReturn(baseSoftwareModuleRootMock);
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) SoftwareModule.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.<String>greaterThanOrEqualTo(any(Expression.class), any(String.class)))
when(criteriaBuilderMock.<String> greaterThanOrEqualTo(any(Expression.class), any(String.class)))
.thenReturn(mock(Predicate.class));
// test
RSQLUtility.parse(correctRsql, SoftwareModuleFields.class, null).toPredicate(baseSoftwareModuleRootMock,
@@ -255,8 +250,7 @@ public class RSQLUtilityTest {
// test
RSQLUtility.parse(correctRsql, TestFieldEnum.class, null).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock,
criteriaBuilderMock);
criteriaQueryMock, criteriaBuilderMock);
// verfication
verify(criteriaBuilderMock, times(1)).and(any(Predicate.class));
@@ -291,16 +285,17 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.get("testfield")).thenReturn(baseSoftwareModuleRootMock);
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.<String>lessThanOrEqualTo(any(Expression.class), eq(overduePropPlaceholder)))
when(criteriaBuilderMock.<String> lessThanOrEqualTo(any(Expression.class), eq(overduePropPlaceholder)))
.thenReturn(mock(Predicate.class));
// test
RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup())
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup()).toPredicate(baseSoftwareModuleRootMock,
criteriaQueryMock, criteriaBuilderMock);
// verification
verify(macroResolver).lookup(overdueProp);
// the macro is already replaced when passed to #lessThanOrEqualTo -> the method is never invoked with the
// the macro is already replaced when passed to #lessThanOrEqualTo ->
// the method is never invoked with the
// placeholder:
verify(criteriaBuilderMock, never()).lessThanOrEqualTo(eq(pathOfString(baseSoftwareModuleRootMock)),
eq(overduePropPlaceholder));
@@ -316,16 +311,17 @@ public class RSQLUtilityTest {
when(baseSoftwareModuleRootMock.get("testfield")).thenReturn(baseSoftwareModuleRootMock);
when(baseSoftwareModuleRootMock.getJavaType()).thenReturn((Class) String.class);
when(criteriaBuilderMock.equal(any(Root.class), anyString())).thenReturn(mock(Predicate.class));
when(criteriaBuilderMock.<String>lessThanOrEqualTo(any(Expression.class), eq(overduePropPlaceholder)))
when(criteriaBuilderMock.<String> lessThanOrEqualTo(any(Expression.class), eq(overduePropPlaceholder)))
.thenReturn(mock(Predicate.class));
// test
Predicate result = RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup())
final Predicate result = RSQLUtility.parse(correctRsql, TestFieldEnum.class, setupMacroLookup())
.toPredicate(baseSoftwareModuleRootMock, criteriaQueryMock, criteriaBuilderMock);
// verification
verify(macroResolver).lookup(overdueProp);
// the macro is unknown and hence never replaced -> #lessThanOrEqualTo is invoked with the placeholder:
// the macro is unknown and hence never replaced -> #lessThanOrEqualTo
// is invoked with the placeholder:
verify(criteriaBuilderMock).lessThanOrEqualTo(eq(pathOfString(baseSoftwareModuleRootMock)),
eq(overduePropPlaceholder));
}
@@ -353,7 +349,9 @@ public class RSQLUtilityTest {
/*
* (non-Javadoc)
*
* @see org.eclipse.hawkbit.server.rest.resource.model.FieldNameProvider# getFieldName()
* @see
* org.eclipse.hawkbit.server.rest.resource.model.FieldNameProvider#
* getFieldName()
*/
@Override
public String getFieldName() {

View File

@@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.TimestampCalculator;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,7 +41,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
public class VirtualPropertyResolverTest {
@Spy
private VirtualPropertyResolver resolverUnderTest = new VirtualPropertyResolver();
private final VirtualPropertyResolver resolverUnderTest = new VirtualPropertyResolver();
@Mock
private TenantConfigurationManagement confMgmt;
@@ -59,66 +59,65 @@ public class VirtualPropertyResolverTest {
public void before() {
nowTestTime = Instant.now().toEpochMilli();
when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class))
.thenReturn(TEST_POLLING_TIME_INTERVAL);
.thenReturn(TEST_POLLING_TIME_INTERVAL);
when(confMgmt.getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class))
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
.thenReturn(TEST_POLLING_OVERDUE_TIME_INTERVAL);
mockStatic(TimestampCalculator.class);
when(TimestampCalculator.getTenantConfigurationManagement()).thenReturn(confMgmt);
substitutor = new StrSubstitutor(resolverUnderTest,
StrSubstitutor.DEFAULT_PREFIX,
substitutor = new StrSubstitutor(resolverUnderTest, StrSubstitutor.DEFAULT_PREFIX,
StrSubstitutor.DEFAULT_SUFFIX, StrSubstitutor.DEFAULT_ESCAPE);
}
}
@Test
@Description("Tests resolution of NOW_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.")
public void resolveNowTimestampPlaceholder() {
String placeholder = "${NOW_TS}";
String testString = "lhs=lt=" + placeholder;
final String placeholder = "${NOW_TS}";
final String testString = "lhs=lt=" + placeholder;
String resolvedPlaceholders = substitutor.replace(testString);
final String resolvedPlaceholders = substitutor.replace(testString);
assertThat("NOW_TS has to be resolved!", resolvedPlaceholders, not(containsString(placeholder)));
}
@Test
@Description("Tests resolution of OVERDUE_TS by using a StrSubstitutor configured with the VirtualPropertyResolver.")
public void resolveOverdueTimestampPlaceholder() {
String placeholder = "${OVERDUE_TS}";
String testString = "lhs=lt=" + placeholder;
final String placeholder = "${OVERDUE_TS}";
final String testString = "lhs=lt=" + placeholder;
String resolvedPlaceholders = substitutor.replace(testString);
final String resolvedPlaceholders = substitutor.replace(testString);
assertThat("OVERDUE_TS has to be resolved!", resolvedPlaceholders, not(containsString(placeholder)));
}
@Test
@Description("Tests case insensititity of VirtualPropertyResolver.")
public void resolveOverdueTimestampPlaceholderLowerCase() {
String placeholder = "${overdue_ts}";
String testString = "lhs=lt=" + placeholder;
final String placeholder = "${overdue_ts}";
final String testString = "lhs=lt=" + placeholder;
String resolvedPlaceholders = substitutor.replace(testString);
final String resolvedPlaceholders = substitutor.replace(testString);
assertThat("overdue_ts has to be resolved!", resolvedPlaceholders, not(containsString(placeholder)));
}
@Test
@Description("Tests VirtualPropertyResolver with a placeholder unknown to VirtualPropertyResolver.")
public void handleUnknownPlaceholder() {
String placeholder = "${unknown}";
String testString = "lhs=lt=" + placeholder;
final String placeholder = "${unknown}";
final String testString = "lhs=lt=" + placeholder;
String resolvedPlaceholders = substitutor.replace(testString);
final String resolvedPlaceholders = substitutor.replace(testString);
assertThat("unknown should not be resolved!", resolvedPlaceholders, containsString(placeholder));
}
@Test
@Description("Tests escape mechanism for placeholders (syntax is $${SOME_PLACEHOLDER}).")
public void handleEscapedPlaceholder() {
String placeholder = "${OVERDUE_TS}";
String escaptedPlaceholder = StrSubstitutor.DEFAULT_ESCAPE + placeholder;
String testString = "lhs=lt=" + escaptedPlaceholder;
final String placeholder = "${OVERDUE_TS}";
final String escaptedPlaceholder = StrSubstitutor.DEFAULT_ESCAPE + placeholder;
final String testString = "lhs=lt=" + escaptedPlaceholder;
String resolvedPlaceholders = substitutor.replace(testString);
final String resolvedPlaceholders = substitutor.replace(testString);
assertThat("Escaped OVERDUE_TS should not be resolved!", resolvedPlaceholders, containsString(placeholder));
}
}

View File

@@ -13,9 +13,6 @@ logging.level.org.eclipse.persistence=ERROR
spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value}
spring.data.mongodb.port=28017
hawkbit.server.ddi.security.authentication.header.enabled=true
hawkbit.server.ddi.security.authentication.gatewaytoken.name=TestToken
multipart.max-file-size=5MB
hawkbit.server.security.dos.maxStatusEntriesPerAction=100
@@ -38,4 +35,48 @@ flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
# DDI configuration
hawkbit.controller.pollingTime=00:01:00
hawkbit.controller.pollingOverdueTime=00:01:00
hawkbit.controller.pollingOverdueTime=00:01:00
# DDI and download security
hawkbit.server.ddi.security.authentication.header.authority=
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
hawkbit.server.download.anonymous.enabled=false
hawkbit.server.ddi.security.authentication.header.enabled=true
hawkbit.server.ddi.security.authentication.gatewaytoken.name=TestToken
hawkbit.server.ddi.security.authentication.gatewaytoken.key=
# Default tenant configuration properties
hawkbit.server.tenant.configuration.authentication-header-enabled.keyName=authentication.header.enabled
hawkbit.server.tenant.configuration.authentication-header-enabled.defaultValue=${hawkbit.server.ddi.security.authentication.header.enabled}
hawkbit.server.tenant.configuration.authentication-header-enabled.dataType=java.lang.Boolean
hawkbit.server.tenant.configuration.authentication-header-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator
hawkbit.server.tenant.configuration.authentication-header-authority.keyName=authentication.header.authority
hawkbit.server.tenant.configuration.authentication-header-authority.defaultValue=${hawkbit.server.ddi.security.authentication.header.authority}
hawkbit.server.tenant.configuration.authentication-targettoken-enabled.keyName=authentication.targettoken.enabled
hawkbit.server.tenant.configuration.authentication-targettoken-enabled.defaultValue=${hawkbit.server.ddi.security.authentication.targettoken.enabled}
hawkbit.server.tenant.configuration.authentication-targettoken-enabled.dataType=java.lang.Boolean
hawkbit.server.tenant.configuration.authentication-targettoken-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator
hawkbit.server.tenant.configuration.authentication-gatewaytoken-enabled.keyName=authentication.gatewaytoken.enabled
hawkbit.server.tenant.configuration.authentication-gatewaytoken-enabled.defaultValue=${hawkbit.server.ddi.security.authentication.gatewaytoken.enabled}
hawkbit.server.tenant.configuration.authentication-gatewaytoken-enabled.dataType=java.lang.Boolean
hawkbit.server.tenant.configuration.authentication-gatewaytoken-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator
hawkbit.server.tenant.configuration.authentication-gatewaytoken-key.keyName=authentication.gatewaytoken.key
hawkbit.server.tenant.configuration.authentication-gatewaytoken-key.defaultValue=${hawkbit.server.ddi.security.authentication.gatewaytoken.key}
hawkbit.server.tenant.configuration.polling-time.keyName=pollingTime
hawkbit.server.tenant.configuration.polling-time.defaultValue=${hawkbit.controller.pollingTime}
hawkbit.server.tenant.configuration.polling-time.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationPollingDurationValidator
hawkbit.server.tenant.configuration.polling-overdue-time.keyName=pollingOverdueTime
hawkbit.server.tenant.configuration.polling-overdue-time.defaultValue=${hawkbit.controller.pollingOverdueTime}
hawkbit.server.tenant.configuration.polling-overdue-time.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationPollingDurationValidator
hawkbit.server.tenant.configuration.anonymous-download-enabled.keyName=anonymous.download.enabled
hawkbit.server.tenant.configuration.anonymous-download-enabled.defaultValue=${hawkbit.server.download.anonymous.enabled}
hawkbit.server.tenant.configuration.anonymous-download-enabled.dataType=java.lang.Boolean
hawkbit.server.tenant.configuration.anonymous-download-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator