[#1651] Implement skip DistributionSet implicit lock on DS tags (#1680)

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:
Avgustin Marinov
2024-03-08 14:58:31 +02:00
committed by GitHub
parent 3f060e84a3
commit 936e6d6d66
10 changed files with 110 additions and 82 deletions

View File

@@ -505,7 +505,7 @@ public interface DistributionSetManagement
* if set or tag with given ID does not exist
*/
@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.

View File

@@ -9,6 +9,7 @@
*/
package org.eclipse.hawkbit.repository;
import java.util.List;
import java.util.concurrent.TimeUnit;
import lombok.Data;
@@ -68,4 +69,7 @@ public class RepositoryProperties {
private long dsInvalidationLockTimeout = 5;
private boolean implicitTenantCreateAllowed;
private List<String> skipImplicitLockForTags =
List.of("skip-implicit-lock", "skip_implicit_lock", "SKIP_IMPLICIT_LOCK", "SKIP-IMPLICIT-LOCK");
}

View File

@@ -164,6 +164,7 @@ import org.eclipse.hawkbit.security.SecurityTokenGenerator;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.tenancy.UserAuthoritiesResolver;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.hibernate.validator.BaseHibernateValidatorConfiguration;
import org.springframework.beans.BeansException;
@@ -532,25 +533,24 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
*/
@Bean
@ConditionalOnMissingBean
DistributionSetManagement distributionSetManagement(final EntityManager entityManager,
final DistributionSetRepository distributionSetRepository,
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
final DistributionSetMetadataRepository distributionSetMetadataRepository,
final TargetRepository targetRepository,
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware,
final VirtualPropertyReplacer virtualPropertyReplacer,
final SoftwareModuleRepository softwareModuleRepository,
final DistributionSetTagRepository distributionSetTagRepository,
final AfterTransactionCommitExecutor afterCommit,
final JpaProperties properties) {
DistributionSetManagement distributionSetManagement(
final EntityManager entityManager,
final DistributionSetRepository distributionSetRepository,
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
final DistributionSetMetadataRepository distributionSetMetadataRepository,
final TargetRepository targetRepository,
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement,
final VirtualPropertyReplacer virtualPropertyReplacer, final SoftwareModuleRepository softwareModuleRepository,
final DistributionSetTagRepository distributionSetTagRepository,
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement,
systemManagement, distributionSetTypeManagement, quotaManagement, distributionSetMetadataRepository,
targetRepository, targetFilterQueryRepository, actionRepository, eventPublisherHolder, tenantAware,
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository, afterCommit,
properties.getDatabase());
targetRepository, targetFilterQueryRepository, actionRepository,
TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement),
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository,
properties.getDatabase(), repositoryProperties);
}
/**

View File

@@ -9,7 +9,6 @@
*/
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;
@@ -373,8 +372,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final JpaDistributionSet distributionSet =
(JpaDistributionSet) distributionSetManagement.getValidAndComplete(dsId);
// implicit lock
if (!distributionSet.isLocked() && getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
// without new transaction DS changed event is not thrown
DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> {
distributionSetManagement.lock(distributionSet.getId());

View File

@@ -15,6 +15,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Supplier;
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.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate;
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.EntityAlreadyExistsException;
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.builder.JpaDistributionSetCreate;
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.JpaDistributionSet;
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.specifications.DistributionSetSpecification;
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.model.Action;
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.SoftwareModule;
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.tenancy.TenantAware;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page;
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.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;
/**
* JPA implementation of {@link DistributionSetManagement}.
*
@@ -99,51 +102,36 @@ import org.springframework.validation.annotation.Validated;
public class JpaDistributionSetManagement implements DistributionSetManagement {
private final EntityManager entityManager;
private final DistributionSetRepository distributionSetRepository;
private final DistributionSetTagManagement distributionSetTagManagement;
private final SystemManagement systemManagement;
private final DistributionSetTypeManagement distributionSetTypeManagement;
private final QuotaManagement quotaManagement;
private final DistributionSetMetadataRepository distributionSetMetadataRepository;
private final TargetRepository targetRepository;
private final TargetFilterQueryRepository targetFilterQueryRepository;
private final ActionRepository actionRepository;
private final EventPublisherHolder eventPublisherHolder;
private final TenantAware tenantAware;
private final TenantConfigHelper tenantConfigHelper;
private final VirtualPropertyReplacer virtualPropertyReplacer;
private final SoftwareModuleRepository softwareModuleRepository;
private final DistributionSetTagRepository distributionSetTagRepository;
private final AfterTransactionCommitExecutor afterCommit;
private final Database database;
private final RepositoryProperties repositoryProperties;
public JpaDistributionSetManagement(final EntityManager entityManager,
public JpaDistributionSetManagement(
final EntityManager entityManager,
final DistributionSetRepository distributionSetRepository,
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
final DistributionSetMetadataRepository distributionSetMetadataRepository,
final TargetRepository targetRepository,
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware,
final TenantConfigHelper tenantConfigHelper,
final VirtualPropertyReplacer virtualPropertyReplacer,
final SoftwareModuleRepository softwareModuleRepository,
final DistributionSetTagRepository distributionSetTagRepository,
final AfterTransactionCommitExecutor afterCommit,
final Database database) {
final Database database,
final RepositoryProperties repositoryProperties) {
this.entityManager = entityManager;
this.distributionSetRepository = distributionSetRepository;
this.distributionSetTagManagement = distributionSetTagManagement;
@@ -154,13 +142,12 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
this.targetRepository = targetRepository;
this.targetFilterQueryRepository = targetFilterQueryRepository;
this.actionRepository = actionRepository;
this.eventPublisherHolder = eventPublisherHolder;
this.tenantAware = tenantAware;
this.tenantConfigHelper = tenantConfigHelper;
this.virtualPropertyReplacer = virtualPropertyReplacer;
this.softwareModuleRepository = softwareModuleRepository;
this.distributionSetTagRepository = distributionSetTagRepository;
this.afterCommit = afterCommit;
this.database = database;
this.repositoryProperties = repositoryProperties;
}
@Override
@@ -679,7 +666,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
@Transactional
@Retryable(include = {
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)
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
@@ -830,6 +817,36 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
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) {
return distributionSetRepository
.findById(id)
@@ -847,4 +864,4 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
throw new EntityNotFoundException(DistributionSetTag.class, tagId);
}
}
}
}

View File

@@ -10,7 +10,6 @@
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;
@@ -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.rsql.RSQLUtility;
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.WeightValidationHelper;
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.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;
@@ -144,8 +143,6 @@ 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,
@@ -162,8 +159,6 @@ public class JpaRolloutManagement implements RolloutManagement {
this.systemSecurityContext = systemSecurityContext;
this.eventPublisherHolder = eventPublisherHolder;
this.contextAware = contextAware;
tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@Override
@@ -229,8 +224,7 @@ public class JpaRolloutManagement implements RolloutManagement {
}
rollout.setTotalTargets(totalTargets);
// implicit lock
if (!distributionSet.isLocked() && tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
distributionSetManagement.lock(distributionSet.getId());
}

View File

@@ -9,8 +9,6 @@
*/
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;
@@ -77,20 +75,15 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
private final TargetFilterQueryRepository targetFilterQueryRepository;
private final TargetManagement targetManagement;
private final VirtualPropertyReplacer virtualPropertyReplacer;
private final DistributionSetManagement distributionSetManagement;
private final QuotaManagement quotaManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
private final RepositoryProperties repositoryProperties;
private final SystemSecurityContext systemSecurityContext;
private final ContextAware contextAware;
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,
@@ -107,8 +100,6 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
this.repositoryProperties = repositoryProperties;
this.systemSecurityContext = systemSecurityContext;
this.contextAware = contextAware;
tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@Override
@@ -285,8 +276,7 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
.getValidAndComplete(update.getDsId());
// implicit lock
if (!distributionSet.isLocked() && tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) {
if (((JpaDistributionSetManagement)distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
distributionSetManagement.lock(distributionSet.getId());
}

View File

@@ -31,7 +31,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Pageable;
@@ -219,7 +218,7 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
assertThat(distributionSetManagement.assignTag(Collections.singletonList(permitted.getId()), dsTag.getId()))
.hasSize(1);
// 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());
// 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)
assertThatThrownBy(() -> {
distributionSetManagement.unAssignTag(readOnly.getId(), dsTag.getId());
distributionSetManagement.unassignTag(readOnly.getId(), dsTag.getId());
}).as("Missing update permissions for target to toggle tag assignment.")
.isInstanceOf(InsufficientPermissionException.class);
@@ -256,7 +255,7 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
// assignment is denied for hiddenTarget since it's hidden
assertThatThrownBy(() -> {
distributionSetManagement.unAssignTag(hidden.getId(), dsTag.getId());
distributionSetManagement.unassignTag(hidden.getId(), dsTag.getId());
}).as("Missing update permissions for target to toggle tag assignment.")
.isInstanceOf(EntityNotFoundException.class);
}

View File

@@ -31,6 +31,7 @@ import jakarta.validation.ConstraintViolationException;
import org.apache.commons.lang3.RandomStringUtils;
import org.assertj.core.api.Condition;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
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.util.WithUser;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
@@ -142,10 +144,10 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
() -> distributionSetManagement.toggleTagAssignment(singletonList(set.getId()), NOT_EXIST_ID),
"DistributionSetTag");
verifyThrownExceptionBy(() -> distributionSetManagement.unAssignTag(set.getId(), NOT_EXIST_IDL),
verifyThrownExceptionBy(() -> distributionSetManagement.unassignTag(set.getId(), NOT_EXIST_IDL),
"DistributionSetTag");
verifyThrownExceptionBy(() -> distributionSetManagement.unAssignTag(NOT_EXIST_IDL, dsTag.getId()),
verifyThrownExceptionBy(() -> distributionSetManagement.unassignTag(NOT_EXIST_IDL, dsTag.getId()),
"DistributionSet");
verifyThrownExceptionBy(
@@ -424,7 +426,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
.isEqualTo(distributionSetManagement.findByTag(PAGE, tag.getId()).getNumberOfElements());
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.getTags().size()).as("unassigned ds has wrong tag size").isZero();
assertThat(distributionSetTagManagement.getByName(TAG1_NAME)).isPresent();
@@ -1042,11 +1044,9 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
assertThat(softwareModuleCount).isNotEqualTo(0);
distributionSetManagement.lock(distributionSet.getId());
assertThat(
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked)
.orElse(false))
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false))
.isTrue();
// try add
assertThatExceptionOfType(LockedException.class)
.as("Attempt to modify a locked DS software modules should throw an exception")
@@ -1066,6 +1066,32 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
.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
@Description("Locks an incomplete DS. Expected behaviour is to throw an exception and to do not lock it.")
void lockIncompleteDistributionSetFails() {

View File

@@ -202,7 +202,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
@PathVariable("distributionsetTagId") final Long distributionsetTagId,
@PathVariable("distributionsetId") final Long distributionsetId) {
log.debug("Unassign ds {} for ds tag {}", distributionsetId, distributionsetTagId);
this.distributionSetManagement.unAssignTag(distributionsetId, distributionsetTagId);
this.distributionSetManagement.unassignTag(distributionsetId, distributionsetTagId);
return ResponseEntity.ok().build();
}