Skip to content

Commit

Permalink
[eclipse-hawkbit#1651] Implement tenant level config for Distribution…
Browse files Browse the repository at this point in the history
…Set implicit lock (enabled by default)

Signed-off-by: Marinov Avgustin <[email protected]>
  • Loading branch information
avgustinmm committed Mar 8, 2024
1 parent f942d77 commit 7a2c9d3
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ public interface TenantConfiguration extends TenantAwareBaseEntity {
* @return value of the entry
*/
String getValue();

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@
import lombok.Builder;
import lombok.Data;

import java.io.Serial;
import java.io.Serializable;

/**
* Represents a tenant configuration value including some meta data
*
* @param <T>
* type of the configuration value
* @param <T> type of the configuration value
*/
@Data
@Builder
public final class TenantConfigurationValue<T extends Serializable> implements Serializable {

@Serial
private static final long serialVersionUID = 1L;

private T value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import java.util.HashMap;
import java.util.Map;

import lombok.Data;
import lombok.ToString;
import org.eclipse.hawkbit.ControllerPollProperties;
import org.eclipse.hawkbit.HawkbitServerProperties.Anonymous.Download;
import org.eclipse.hawkbit.repository.exception.InvalidTenantConfigurationKeyException;
Expand All @@ -24,20 +26,14 @@

/**
* Properties for tenant configuration default values.
*
*/
@Data
@ToString
@ConfigurationProperties("hawkbit.server.tenant")
public class TenantConfigurationProperties {

private final Map<String, TenantConfigurationKey> configuration = new HashMap<>();

/**
* @return full map of all configured tenant properties
*/
public Map<String, TenantConfigurationKey> getConfiguration() {
return configuration;
}

/**
* @return full list of {@link TenantConfigurationKey}s
*/
Expand All @@ -46,8 +42,7 @@ public Collection<TenantConfigurationKey> getConfigurationKeys() {
}

/**
* @param keyName
* name of the TenantConfigurationKey
* @param keyName name of the TenantConfigurationKey
* @return the TenantConfigurationKey with the name keyName
*/
public TenantConfigurationKey fromKeyName(final String keyName) {
Expand All @@ -59,8 +54,9 @@ public TenantConfigurationKey fromKeyName(final String keyName) {
/**
* Tenant specific configurations which can be configured for each tenant
* separately by means of override of the system defaults.
*
*/
@Data
@ToString
public static class TenantConfigurationKey {

/**
Expand Down Expand Up @@ -158,49 +154,16 @@ public static class TenantConfigurationKey {
*/
public static final String USER_CONFIRMATION_ENABLED = "user.confirmation.flow.enabled";

/**
* Switch to enable/disable the implicit locking
*/
public static final String IMPLICIT_LOCK_ENABLED = "implicit.lock.enabled";

private String keyName;
private String defaultValue = "";
private Class<?> dataType = String.class;
private Class<? extends TenantConfigurationValidator> validator = TenantConfigurationStringValidator.class;

public String getKeyName() {
return keyName;
}

public void setKeyName(final String keyName) {
this.keyName = keyName;
}

/**
*
* @return the data type of the tenant configuration value. (e.g.
* Integer.class, String.class)
*/
@SuppressWarnings("unchecked")
public <T> Class<T> getDataType() {
return (Class<T>) dataType;
}

public void setDataType(final Class<?> dataType) {
this.dataType = dataType;
}

public String getDefaultValue() {
return defaultValue;
}

public void setDefaultValue(final String defaultValue) {
this.defaultValue = defaultValue;
}

public Class<? extends TenantConfigurationValidator> getValidator() {
return validator;
}

public void setValidator(final Class<? extends TenantConfigurationValidator> validator) {
this.validator = validator;
}

/**
* validates if a object matches the allowed data format of the
* corresponding key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.security.SystemSecurityContext;

import java.io.Serializable;

/**
* A collection of static helper methods for the tenant configuration
*/
Expand Down Expand Up @@ -43,14 +45,18 @@ public static TenantConfigHelper usingContext(final SystemSecurityContext system
return new TenantConfigHelper(systemSecurityContext, tenantConfigurationManagement);
}

public <T extends Serializable> T getConfigValue(final String key, final Class<T> valueType) {
return systemSecurityContext
.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue());
}

/**
* Is multi-assignments enabled for the current tenant
*
* @return is active
*/
public boolean isMultiAssignmentsEnabled() {
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement
.getConfigurationValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class).getValue());
return getConfigValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class);
}

/**
Expand All @@ -59,7 +65,6 @@ public boolean isMultiAssignmentsEnabled() {
* @return is enabled
*/
public boolean isConfirmationFlowEnabled() {
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement
.getConfigurationValue(USER_CONFIRMATION_ENABLED, Boolean.class).getValue());
return getConfigValue(USER_CONFIRMATION_ENABLED, Boolean.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@ToString(callSuper = true)
@Accessors(fluent = true)
public class GenericDistributionSetUpdate extends AbstractDistributionSetUpdateCreate<DistributionSetUpdate>
implements DistributionSetUpdate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/
@Data
@EqualsAndHashCode(callSuper = true)
@ToString
@ToString(callSuper = true)
@Accessors(fluent = true)
public class GenericSoftwareModuleUpdate extends AbstractSoftwareModuleUpdateCreate<SoftwareModuleUpdate>
implements SoftwareModuleUpdate {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,9 @@ hawkbit.server.tenant.configuration.user-confirmation-enabled.defaultValue=false
hawkbit.server.tenant.configuration.user-confirmation-enabled.dataType=java.lang.Boolean
hawkbit.server.tenant.configuration.user-confirmation-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator

hawkbit.server.tenant.configuration.implicit-lock-enabled.keyName=user.confirmation.flow.enabled
hawkbit.server.tenant.configuration.implicit-lock-enabled.defaultValue=true
hawkbit.server.tenant.configuration.implicit-lock-enabled.dataType=java.lang.Boolean
hawkbit.server.tenant.configuration.implicit-lock-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator

# Default tenant configuration - END
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
*/
package org.eclipse.hawkbit.repository.jpa.management;

import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED;

import java.io.Serializable;
Expand Down Expand Up @@ -371,8 +372,9 @@ private DistributionSetAssignmentResult assignDistributionSetToTargets(final Str
final AbstractDsAssignmentStrategy assignmentStrategy) {
final JpaDistributionSet distributionSet =
(JpaDistributionSet) distributionSetManagement.getValidAndComplete(dsId);

// implicit lock
if (!distributionSet.isLocked()) {
if (!distributionSet.isLocked() && getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
// without new transaction DS changed event is not thrown
DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> {
distributionSetManagement.lock(distributionSet.getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
package org.eclipse.hawkbit.repository.jpa.management;

import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
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;
Expand Down Expand Up @@ -75,6 +75,7 @@
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
Expand Down Expand Up @@ -143,6 +144,8 @@ public class JpaRolloutManagement implements RolloutManagement {
private final ContextAware contextAware;
private final Database database;

private final TenantConfigHelper tenantConfigHelper;

public JpaRolloutManagement(final TargetManagement targetManagement,
final DistributionSetManagement distributionSetManagement, final EventPublisherHolder eventPublisherHolder,
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
Expand All @@ -159,6 +162,8 @@ public JpaRolloutManagement(final TargetManagement targetManagement,
this.systemSecurityContext = systemSecurityContext;
this.eventPublisherHolder = eventPublisherHolder;
this.contextAware = contextAware;

tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}

@Override
Expand Down Expand Up @@ -225,7 +230,7 @@ private JpaRollout createRollout(final JpaRollout rollout) {
rollout.setTotalTargets(totalTargets);

// implicit lock
if (!distributionSet.isLocked()) {
if (!distributionSet.isLocked() && tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
distributionSetManagement.lock(distributionSet.getId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
*/
package org.eclipse.hawkbit.repository.jpa.management;

import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -87,6 +89,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme

private final Database database;

private final TenantConfigHelper tenantConfigHelper;

public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFilterQueryRepository,
final TargetManagement targetManagement, final VirtualPropertyReplacer virtualPropertyReplacer,
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
Expand All @@ -103,6 +107,8 @@ public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFi
this.repositoryProperties = repositoryProperties;
this.systemSecurityContext = systemSecurityContext;
this.contextAware = contextAware;

tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}

@Override
Expand Down Expand Up @@ -278,8 +284,9 @@ public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdat
assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.getDsId());
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
.getValidAndComplete(update.getDsId());

// implicit lock
if (!distributionSet.isLocked()) {
if (!distributionSet.isLocked() && tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
distributionSetManagement.lock(distributionSet.getId());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
* **pollingOverdueTime** - String, The configuration key 'pollingOverdueTime' defines the period of time after the SP server will recognize a target, which is not performing pull requests anymore.
* **multi.assignments.enabled** - Boolean, The configuration key 'multi.assignments.enabled' defines if multiple distribution sets can be assigned to the same targets.
* **batch.assignments.enabled** - Boolean, The configuration key 'batch.assignments.enabled' defines if distribution set can be assigned to multiple targets in a single batch message.
* **implicit.lock.enabled** - Boolean (true by default), The configuration key 'implicit.lock.enabled' defines if distribution set and their software modules shall be implicitly locked when assigned to target, rollout or target filter.
""", example = """
{
"value" : "",
Expand Down

0 comments on commit 7a2c9d3

Please sign in to comment.