tags the implicit lock is skipped on are configured via RepositoryProperties.skipImplicitLockForTags list. By default skip tags are the ones with names: "skip-implicit-lock", "skip_implicit_lock", "SKIP_IMPLICIT_LOCK", "SKIP-IMPLICIT-LOCK" + this commit centralize the implicit lock enable/disable logic Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -505,7 +505,7 @@ public interface DistributionSetManagement
|
|||||||
* if set or tag with given ID does not exist
|
* if set or tag with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
|
||||||
DistributionSet unAssignTag(long id, long tagId);
|
DistributionSet unassignTag(long id, long tagId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a distribution set meta data value if corresponding entry exists.
|
* Updates a distribution set meta data value if corresponding entry exists.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository;
|
package org.eclipse.hawkbit.repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -68,4 +69,7 @@ public class RepositoryProperties {
|
|||||||
private long dsInvalidationLockTimeout = 5;
|
private long dsInvalidationLockTimeout = 5;
|
||||||
|
|
||||||
private boolean implicitTenantCreateAllowed;
|
private boolean implicitTenantCreateAllowed;
|
||||||
|
|
||||||
|
private List<String> skipImplicitLockForTags =
|
||||||
|
List.of("skip-implicit-lock", "skip_implicit_lock", "SKIP_IMPLICIT_LOCK", "SKIP-IMPLICIT-LOCK");
|
||||||
}
|
}
|
||||||
@@ -164,6 +164,7 @@ import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
|||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
|
||||||
|
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
||||||
import org.eclipse.persistence.config.PersistenceUnitProperties;
|
import org.eclipse.persistence.config.PersistenceUnitProperties;
|
||||||
import org.hibernate.validator.BaseHibernateValidatorConfiguration;
|
import org.hibernate.validator.BaseHibernateValidatorConfiguration;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
@@ -532,25 +533,24 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
|||||||
*/
|
*/
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
DistributionSetManagement distributionSetManagement(final EntityManager entityManager,
|
DistributionSetManagement distributionSetManagement(
|
||||||
|
final EntityManager entityManager,
|
||||||
final DistributionSetRepository distributionSetRepository,
|
final DistributionSetRepository distributionSetRepository,
|
||||||
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
||||||
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
||||||
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
||||||
final TargetRepository targetRepository,
|
final TargetRepository targetRepository,
|
||||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||||
final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware,
|
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
final VirtualPropertyReplacer virtualPropertyReplacer, final SoftwareModuleRepository softwareModuleRepository,
|
||||||
final SoftwareModuleRepository softwareModuleRepository,
|
|
||||||
final DistributionSetTagRepository distributionSetTagRepository,
|
final DistributionSetTagRepository distributionSetTagRepository,
|
||||||
final AfterTransactionCommitExecutor afterCommit,
|
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||||
final JpaProperties properties) {
|
|
||||||
return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement,
|
return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement,
|
||||||
systemManagement, distributionSetTypeManagement, quotaManagement, distributionSetMetadataRepository,
|
systemManagement, distributionSetTypeManagement, quotaManagement, distributionSetMetadataRepository,
|
||||||
targetRepository, targetFilterQueryRepository, actionRepository, eventPublisherHolder, tenantAware,
|
targetRepository, targetFilterQueryRepository, actionRepository,
|
||||||
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository, afterCommit,
|
TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement),
|
||||||
properties.getDatabase());
|
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository,
|
||||||
|
properties.getDatabase(), repositoryProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.management;
|
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 static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
@@ -373,8 +372,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
final JpaDistributionSet distributionSet =
|
final JpaDistributionSet distributionSet =
|
||||||
(JpaDistributionSet) distributionSetManagement.getValidAndComplete(dsId);
|
(JpaDistributionSet) distributionSetManagement.getValidAndComplete(dsId);
|
||||||
|
|
||||||
// implicit lock
|
if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
|
||||||
if (!distributionSet.isLocked() && getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
|
|
||||||
// without new transaction DS changed event is not thrown
|
// without new transaction DS changed event is not thrown
|
||||||
DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> {
|
DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> {
|
||||||
distributionSetManagement.lock(distributionSet.getId());
|
distributionSetManagement.lock(distributionSet.getId());
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -29,11 +30,11 @@ import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
|
|||||||
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
|
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
|
||||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||||
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
|
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
|
||||||
import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate;
|
import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate;
|
||||||
import org.eclipse.hawkbit.repository.builder.GenericDistributionSetUpdate;
|
import org.eclipse.hawkbit.repository.builder.GenericDistributionSetUpdate;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent;
|
|
||||||
import org.eclipse.hawkbit.repository.exception.DeletedException;
|
import org.eclipse.hawkbit.repository.exception.DeletedException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
@@ -45,7 +46,6 @@ import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
||||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||||
@@ -62,6 +62,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
|
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -73,9 +74,8 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
|||||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.model.Statistic;
|
import org.eclipse.hawkbit.repository.model.Statistic;
|
||||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -85,11 +85,14 @@ import org.springframework.data.jpa.domain.Specification;
|
|||||||
import org.springframework.orm.jpa.vendor.Database;
|
import org.springframework.orm.jpa.vendor.Database;
|
||||||
import org.springframework.retry.annotation.Backoff;
|
import org.springframework.retry.annotation.Backoff;
|
||||||
import org.springframework.retry.annotation.Retryable;
|
import org.springframework.retry.annotation.Retryable;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JPA implementation of {@link DistributionSetManagement}.
|
* JPA implementation of {@link DistributionSetManagement}.
|
||||||
*
|
*
|
||||||
@@ -99,51 +102,36 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
public class JpaDistributionSetManagement implements DistributionSetManagement {
|
public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||||
|
|
||||||
private final EntityManager entityManager;
|
private final EntityManager entityManager;
|
||||||
|
|
||||||
private final DistributionSetRepository distributionSetRepository;
|
private final DistributionSetRepository distributionSetRepository;
|
||||||
|
|
||||||
private final DistributionSetTagManagement distributionSetTagManagement;
|
private final DistributionSetTagManagement distributionSetTagManagement;
|
||||||
|
|
||||||
private final SystemManagement systemManagement;
|
private final SystemManagement systemManagement;
|
||||||
|
|
||||||
private final DistributionSetTypeManagement distributionSetTypeManagement;
|
private final DistributionSetTypeManagement distributionSetTypeManagement;
|
||||||
|
|
||||||
private final QuotaManagement quotaManagement;
|
private final QuotaManagement quotaManagement;
|
||||||
|
|
||||||
private final DistributionSetMetadataRepository distributionSetMetadataRepository;
|
private final DistributionSetMetadataRepository distributionSetMetadataRepository;
|
||||||
private final TargetRepository targetRepository;
|
private final TargetRepository targetRepository;
|
||||||
|
|
||||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||||
|
|
||||||
private final ActionRepository actionRepository;
|
private final ActionRepository actionRepository;
|
||||||
|
private final TenantConfigHelper tenantConfigHelper;
|
||||||
private final EventPublisherHolder eventPublisherHolder;
|
|
||||||
|
|
||||||
private final TenantAware tenantAware;
|
|
||||||
|
|
||||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||||
|
|
||||||
private final SoftwareModuleRepository softwareModuleRepository;
|
private final SoftwareModuleRepository softwareModuleRepository;
|
||||||
|
|
||||||
private final DistributionSetTagRepository distributionSetTagRepository;
|
private final DistributionSetTagRepository distributionSetTagRepository;
|
||||||
|
|
||||||
private final AfterTransactionCommitExecutor afterCommit;
|
|
||||||
|
|
||||||
private final Database database;
|
private final Database database;
|
||||||
|
private final RepositoryProperties repositoryProperties;
|
||||||
|
|
||||||
public JpaDistributionSetManagement(final EntityManager entityManager,
|
public JpaDistributionSetManagement(
|
||||||
|
final EntityManager entityManager,
|
||||||
final DistributionSetRepository distributionSetRepository,
|
final DistributionSetRepository distributionSetRepository,
|
||||||
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
||||||
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
||||||
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
||||||
final TargetRepository targetRepository,
|
final TargetRepository targetRepository,
|
||||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||||
final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware,
|
final TenantConfigHelper tenantConfigHelper,
|
||||||
final VirtualPropertyReplacer virtualPropertyReplacer,
|
final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||||
final SoftwareModuleRepository softwareModuleRepository,
|
final SoftwareModuleRepository softwareModuleRepository,
|
||||||
final DistributionSetTagRepository distributionSetTagRepository,
|
final DistributionSetTagRepository distributionSetTagRepository,
|
||||||
final AfterTransactionCommitExecutor afterCommit,
|
final Database database,
|
||||||
final Database database) {
|
final RepositoryProperties repositoryProperties) {
|
||||||
this.entityManager = entityManager;
|
this.entityManager = entityManager;
|
||||||
this.distributionSetRepository = distributionSetRepository;
|
this.distributionSetRepository = distributionSetRepository;
|
||||||
this.distributionSetTagManagement = distributionSetTagManagement;
|
this.distributionSetTagManagement = distributionSetTagManagement;
|
||||||
@@ -154,13 +142,12 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
this.targetRepository = targetRepository;
|
this.targetRepository = targetRepository;
|
||||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||||
this.actionRepository = actionRepository;
|
this.actionRepository = actionRepository;
|
||||||
this.eventPublisherHolder = eventPublisherHolder;
|
this.tenantConfigHelper = tenantConfigHelper;
|
||||||
this.tenantAware = tenantAware;
|
|
||||||
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
this.virtualPropertyReplacer = virtualPropertyReplacer;
|
||||||
this.softwareModuleRepository = softwareModuleRepository;
|
this.softwareModuleRepository = softwareModuleRepository;
|
||||||
this.distributionSetTagRepository = distributionSetTagRepository;
|
this.distributionSetTagRepository = distributionSetTagRepository;
|
||||||
this.afterCommit = afterCommit;
|
|
||||||
this.database = database;
|
this.database = database;
|
||||||
|
this.repositoryProperties = repositoryProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -679,7 +666,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
@Transactional
|
@Transactional
|
||||||
@Retryable(include = {
|
@Retryable(include = {
|
||||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||||
public DistributionSet unAssignTag(final long id, final long dsTagId) {
|
public DistributionSet unassignTag(final long id, final long dsTagId) {
|
||||||
final JpaDistributionSet set = (JpaDistributionSet) getWithDetails(id)
|
final JpaDistributionSet set = (JpaDistributionSet) getWithDetails(id)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
|
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
|
||||||
|
|
||||||
@@ -830,6 +817,36 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
|||||||
distributionSetRepository.save(jpaSet);
|
distributionSetRepository.save(jpaSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if shall implicitly lock a distribution set
|
||||||
|
boolean isImplicitLockApplicable(final DistributionSet distributionSet) {
|
||||||
|
final JpaDistributionSet jpaDistributionSet = (JpaDistributionSet) distributionSet;
|
||||||
|
if (jpaDistributionSet.isLocked()) {
|
||||||
|
// already locked
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
|
||||||
|
// implicit lock disabled
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> skipForTags = repositoryProperties.getSkipImplicitLockForTags();
|
||||||
|
if (!ObjectUtils.isEmpty(skipForTags)) {
|
||||||
|
final Set<DistributionSetTag> tags = ((JpaDistributionSet)jpaDistributionSet).getTags();
|
||||||
|
if (!ObjectUtils.isEmpty(tags)) {
|
||||||
|
for (final DistributionSetTag tag : tags) {
|
||||||
|
if (skipForTags.contains(tag.getName())) {
|
||||||
|
// has a skip tag
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally - implicit lock is applicable
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private JpaDistributionSet getById(final long id) {
|
private JpaDistributionSet getById(final long id) {
|
||||||
return distributionSetRepository
|
return distributionSetRepository
|
||||||
.findById(id)
|
.findById(id)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
package org.eclipse.hawkbit.repository.jpa.management;
|
package org.eclipse.hawkbit.repository.jpa.management;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupCreate.addSuccessAndErrorConditionsAndActions;
|
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.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -59,6 +58,7 @@ import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction;
|
import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification;
|
import org.eclipse.hawkbit.repository.jpa.specifications.RolloutSpecification;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.WeightValidationHelper;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -75,7 +75,6 @@ import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus;
|
|||||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.utils.TenantConfigHelper;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -144,8 +143,6 @@ public class JpaRolloutManagement implements RolloutManagement {
|
|||||||
private final ContextAware contextAware;
|
private final ContextAware contextAware;
|
||||||
private final Database database;
|
private final Database database;
|
||||||
|
|
||||||
private final TenantConfigHelper tenantConfigHelper;
|
|
||||||
|
|
||||||
public JpaRolloutManagement(final TargetManagement targetManagement,
|
public JpaRolloutManagement(final TargetManagement targetManagement,
|
||||||
final DistributionSetManagement distributionSetManagement, final EventPublisherHolder eventPublisherHolder,
|
final DistributionSetManagement distributionSetManagement, final EventPublisherHolder eventPublisherHolder,
|
||||||
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
|
final VirtualPropertyReplacer virtualPropertyReplacer, final Database database,
|
||||||
@@ -162,8 +159,6 @@ public class JpaRolloutManagement implements RolloutManagement {
|
|||||||
this.systemSecurityContext = systemSecurityContext;
|
this.systemSecurityContext = systemSecurityContext;
|
||||||
this.eventPublisherHolder = eventPublisherHolder;
|
this.eventPublisherHolder = eventPublisherHolder;
|
||||||
this.contextAware = contextAware;
|
this.contextAware = contextAware;
|
||||||
|
|
||||||
tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -229,8 +224,7 @@ public class JpaRolloutManagement implements RolloutManagement {
|
|||||||
}
|
}
|
||||||
rollout.setTotalTargets(totalTargets);
|
rollout.setTotalTargets(totalTargets);
|
||||||
|
|
||||||
// implicit lock
|
if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
|
||||||
if (!distributionSet.isLocked() && tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
|
|
||||||
distributionSetManagement.lock(distributionSet.getId());
|
distributionSetManagement.lock(distributionSet.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.management;
|
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.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -77,20 +75,15 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
|
|
||||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||||
private final TargetManagement targetManagement;
|
private final TargetManagement targetManagement;
|
||||||
|
|
||||||
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
private final VirtualPropertyReplacer virtualPropertyReplacer;
|
||||||
|
|
||||||
private final DistributionSetManagement distributionSetManagement;
|
private final DistributionSetManagement distributionSetManagement;
|
||||||
private final QuotaManagement quotaManagement;
|
private final QuotaManagement quotaManagement;
|
||||||
private final TenantConfigurationManagement tenantConfigurationManagement;
|
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||||
private final RepositoryProperties repositoryProperties;
|
private final RepositoryProperties repositoryProperties;
|
||||||
private final SystemSecurityContext systemSecurityContext;
|
private final SystemSecurityContext systemSecurityContext;
|
||||||
private final ContextAware contextAware;
|
private final ContextAware contextAware;
|
||||||
|
|
||||||
private final Database database;
|
private final Database database;
|
||||||
|
|
||||||
private final TenantConfigHelper tenantConfigHelper;
|
|
||||||
|
|
||||||
public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFilterQueryRepository,
|
public JpaTargetFilterQueryManagement(final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||||
final TargetManagement targetManagement, final VirtualPropertyReplacer virtualPropertyReplacer,
|
final TargetManagement targetManagement, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||||
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||||
@@ -107,8 +100,6 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
this.repositoryProperties = repositoryProperties;
|
this.repositoryProperties = repositoryProperties;
|
||||||
this.systemSecurityContext = systemSecurityContext;
|
this.systemSecurityContext = systemSecurityContext;
|
||||||
this.contextAware = contextAware;
|
this.contextAware = contextAware;
|
||||||
|
|
||||||
tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -285,8 +276,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
|||||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
|
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
|
||||||
.getValidAndComplete(update.getDsId());
|
.getValidAndComplete(update.getDsId());
|
||||||
|
|
||||||
// implicit lock
|
if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
|
||||||
if (!distributionSet.isLocked() && tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
|
|
||||||
distributionSetManagement.lock(distributionSet.getId());
|
distributionSetManagement.lock(distributionSet.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
|
||||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.data.domain.Pageable;
|
import org.springframework.data.domain.Pageable;
|
||||||
@@ -219,7 +218,7 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
|||||||
assertThat(distributionSetManagement.assignTag(Collections.singletonList(permitted.getId()), dsTag.getId()))
|
assertThat(distributionSetManagement.assignTag(Collections.singletonList(permitted.getId()), dsTag.getId()))
|
||||||
.hasSize(1);
|
.hasSize(1);
|
||||||
// verify distributionSetManagement#unAssignTag on permitted target
|
// verify distributionSetManagement#unAssignTag on permitted target
|
||||||
assertThat(distributionSetManagement.unAssignTag(permitted.getId(), dsTag.getId()).getId())
|
assertThat(distributionSetManagement.unassignTag(permitted.getId(), dsTag.getId()).getId())
|
||||||
.isEqualTo(permitted.getId());
|
.isEqualTo(permitted.getId());
|
||||||
|
|
||||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||||
@@ -237,7 +236,7 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
|||||||
|
|
||||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||||
assertThatThrownBy(() -> {
|
assertThatThrownBy(() -> {
|
||||||
distributionSetManagement.unAssignTag(readOnly.getId(), dsTag.getId());
|
distributionSetManagement.unassignTag(readOnly.getId(), dsTag.getId());
|
||||||
}).as("Missing update permissions for target to toggle tag assignment.")
|
}).as("Missing update permissions for target to toggle tag assignment.")
|
||||||
.isInstanceOf(InsufficientPermissionException.class);
|
.isInstanceOf(InsufficientPermissionException.class);
|
||||||
|
|
||||||
@@ -256,7 +255,7 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
|||||||
|
|
||||||
// assignment is denied for hiddenTarget since it's hidden
|
// assignment is denied for hiddenTarget since it's hidden
|
||||||
assertThatThrownBy(() -> {
|
assertThatThrownBy(() -> {
|
||||||
distributionSetManagement.unAssignTag(hidden.getId(), dsTag.getId());
|
distributionSetManagement.unassignTag(hidden.getId(), dsTag.getId());
|
||||||
}).as("Missing update permissions for target to toggle tag assignment.")
|
}).as("Missing update permissions for target to toggle tag assignment.")
|
||||||
.isInstanceOf(EntityNotFoundException.class);
|
.isInstanceOf(EntityNotFoundException.class);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import jakarta.validation.ConstraintViolationException;
|
|||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.assertj.core.api.Condition;
|
import org.assertj.core.api.Condition;
|
||||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||||
|
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||||
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
|
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent;
|
||||||
@@ -67,6 +68,7 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
|||||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
@@ -142,10 +144,10 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
() -> distributionSetManagement.toggleTagAssignment(singletonList(set.getId()), NOT_EXIST_ID),
|
() -> distributionSetManagement.toggleTagAssignment(singletonList(set.getId()), NOT_EXIST_ID),
|
||||||
"DistributionSetTag");
|
"DistributionSetTag");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> distributionSetManagement.unAssignTag(set.getId(), NOT_EXIST_IDL),
|
verifyThrownExceptionBy(() -> distributionSetManagement.unassignTag(set.getId(), NOT_EXIST_IDL),
|
||||||
"DistributionSetTag");
|
"DistributionSetTag");
|
||||||
|
|
||||||
verifyThrownExceptionBy(() -> distributionSetManagement.unAssignTag(NOT_EXIST_IDL, dsTag.getId()),
|
verifyThrownExceptionBy(() -> distributionSetManagement.unassignTag(NOT_EXIST_IDL, dsTag.getId()),
|
||||||
"DistributionSet");
|
"DistributionSet");
|
||||||
|
|
||||||
verifyThrownExceptionBy(
|
verifyThrownExceptionBy(
|
||||||
@@ -424,7 +426,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
.isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements());
|
.isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements());
|
||||||
|
|
||||||
final JpaDistributionSet unAssignDS = (JpaDistributionSet) distributionSetManagement
|
final JpaDistributionSet unAssignDS = (JpaDistributionSet) distributionSetManagement
|
||||||
.unAssignTag(assignDS.get(0), findDistributionSetTag.getId());
|
.unassignTag(assignDS.get(0), findDistributionSetTag.getId());
|
||||||
assertThat(unAssignDS.getId()).as("unassigned ds is wrong").isEqualTo(assignDS.get(0));
|
assertThat(unAssignDS.getId()).as("unassigned ds is wrong").isEqualTo(assignDS.get(0));
|
||||||
assertThat(unAssignDS.getTags().size()).as("unassigned ds has wrong tag size").isZero();
|
assertThat(unAssignDS.getTags().size()).as("unassigned ds has wrong tag size").isZero();
|
||||||
assertThat(distributionSetTagManagement.getByName(TAG1_NAME)).isPresent();
|
assertThat(distributionSetTagManagement.getByName(TAG1_NAME)).isPresent();
|
||||||
@@ -1042,11 +1044,9 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(softwareModuleCount).isNotEqualTo(0);
|
assertThat(softwareModuleCount).isNotEqualTo(0);
|
||||||
distributionSetManagement.lock(distributionSet.getId());
|
distributionSetManagement.lock(distributionSet.getId());
|
||||||
assertThat(
|
assertThat(
|
||||||
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked)
|
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false))
|
||||||
.orElse(false))
|
|
||||||
.isTrue();
|
.isTrue();
|
||||||
|
|
||||||
|
|
||||||
// try add
|
// try add
|
||||||
assertThatExceptionOfType(LockedException.class)
|
assertThatExceptionOfType(LockedException.class)
|
||||||
.as("Attempt to modify a locked DS software modules should throw an exception")
|
.as("Attempt to modify a locked DS software modules should throw an exception")
|
||||||
@@ -1066,6 +1066,32 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
.isEqualTo(softwareModuleCount);
|
.isEqualTo(softwareModuleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Autowired RepositoryProperties repositoryProperties;
|
||||||
|
@Test
|
||||||
|
@Description("Test implicit locks for a DS and skip tags.")
|
||||||
|
void isImplicitLockApplicableDistributionSet() {
|
||||||
|
final JpaDistributionSetManagement distributionSetManagement =
|
||||||
|
(JpaDistributionSetManagement)this.distributionSetManagement;
|
||||||
|
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-non-skip");
|
||||||
|
// assert that implicit lock is applicable for non skip tags
|
||||||
|
assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSet)).isTrue();
|
||||||
|
|
||||||
|
assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotEqualTo(0);
|
||||||
|
final List<DistributionSetTag> skipTags = distributionSetTagManagement.create(
|
||||||
|
repositoryProperties.getSkipImplicitLockForTags().stream()
|
||||||
|
.map(skipTag -> entityFactory.tag().create().name(skipTag))
|
||||||
|
.toList());
|
||||||
|
// assert that implicit lock locks for every skip tag
|
||||||
|
skipTags.forEach(skipTag -> {
|
||||||
|
DistributionSet distributionSetWithSkipTag =
|
||||||
|
testdataFactory.createDistributionSet("ds-skip-" + skipTag.getName());
|
||||||
|
distributionSetManagement.assignTag(List.of(distributionSetWithSkipTag.getId()), skipTag.getId());
|
||||||
|
distributionSetWithSkipTag = distributionSetManagement.get(distributionSetWithSkipTag.getId()).orElseThrow();
|
||||||
|
// assert that implicit lock isn't applicable for skip tags
|
||||||
|
assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSetWithSkipTag)).isFalse();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Locks an incomplete DS. Expected behaviour is to throw an exception and to do not lock it.")
|
@Description("Locks an incomplete DS. Expected behaviour is to throw an exception and to do not lock it.")
|
||||||
void lockIncompleteDistributionSetFails() {
|
void lockIncompleteDistributionSetFails() {
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
|
|||||||
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
|
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
|
||||||
@PathVariable("distributionsetId") final Long distributionsetId) {
|
@PathVariable("distributionsetId") final Long distributionsetId) {
|
||||||
log.debug("Unassign ds {} for ds tag {}", distributionsetId, distributionsetTagId);
|
log.debug("Unassign ds {} for ds tag {}", distributionsetId, distributionsetTagId);
|
||||||
this.distributionSetManagement.unAssignTag(distributionsetId, distributionsetTagId);
|
this.distributionSetManagement.unassignTag(distributionsetId, distributionsetTagId);
|
||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user