Implement TargetFilterQueryManagement with AbstractJpaRepositoryManagement (#2587)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-08-05 09:53:24 +03:00
committed by GitHub
parent 1824839a6f
commit 7b24981a1d
36 changed files with 736 additions and 1482 deletions

View File

@@ -14,7 +14,6 @@ import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder;
import org.springframework.validation.annotation.Validated;
@@ -26,17 +25,20 @@ import org.springframework.validation.annotation.Validated;
public class JpaEntityFactory implements EntityFactory {
private final TargetBuilder targetBuilder;
private final TargetFilterQueryBuilder targetFilterQueryBuilder;
private final RolloutBuilder rolloutBuilder;
@SuppressWarnings("java:S107")
public JpaEntityFactory(
final TargetBuilder targetBuilder, final TargetFilterQueryBuilder targetFilterQueryBuilder,
final RolloutBuilder rolloutBuilder) {
final TargetBuilder targetBuilder, final RolloutBuilder rolloutBuilder) {
this.targetBuilder = targetBuilder;
this.targetFilterQueryBuilder = targetFilterQueryBuilder;
this.rolloutBuilder = rolloutBuilder;
}
@Override
public TargetBuilder target() {
return targetBuilder;
}
@Override
public ActionStatusBuilder actionStatus() {
return new JpaActionStatusBuilder();
@@ -51,14 +53,4 @@ public class JpaEntityFactory implements EntityFactory {
public RolloutBuilder rollout() {
return rolloutBuilder;
}
@Override
public TargetBuilder target() {
return targetBuilder;
}
@Override
public TargetFilterQueryBuilder targetFilterQuery() {
return targetFilterQueryBuilder;
}
}

View File

@@ -44,7 +44,6 @@ import org.eclipse.hawkbit.repository.artifact.encryption.ArtifactEncryptionServ
import org.eclipse.hawkbit.repository.autoassign.AutoAssignExecutor;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.event.ApplicationEventFilter;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManager;
import org.eclipse.hawkbit.repository.event.remote.EventEntityManagerHolder;
@@ -58,7 +57,6 @@ import org.eclipse.hawkbit.repository.jpa.autocleanup.AutoCleanupScheduler;
import org.eclipse.hawkbit.repository.jpa.autocleanup.CleanupTask;
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetBuilder;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.jpa.cluster.DistributedLockRepository;
import org.eclipse.hawkbit.repository.jpa.cluster.LockProperties;
import org.eclipse.hawkbit.repository.jpa.event.JpaEventEntityManager;
@@ -316,16 +314,6 @@ public class JpaRepositoryConfiguration {
return new JpaRolloutBuilder(distributionSetManagement);
}
/**
* @param distributionSetManagement for loading
* {@link TargetFilterQuery#getAutoAssignDistributionSet()}
* @return TargetFilterQueryBuilder bean
*/
@Bean
TargetFilterQueryBuilder targetFilterQueryBuilder(final DistributionSetManagement<? extends DistributionSet> distributionSetManagement) {
return new JpaTargetFilterQueryBuilder(distributionSetManagement);
}
/**
* @return the {@link SystemSecurityContext} singleton bean which make it
* accessible in beans which cannot access the service directly, e.g.
@@ -436,10 +424,8 @@ public class JpaRepositoryConfiguration {
*/
@Bean
@ConditionalOnMissingBean
EntityFactory entityFactory(
final TargetBuilder targetBuilder, final TargetFilterQueryBuilder targetFilterQueryBuilder,
final RolloutBuilder rolloutBuilder) {
return new JpaEntityFactory(targetBuilder, targetFilterQueryBuilder, rolloutBuilder);
EntityFactory entityFactory(final TargetBuilder targetBuilder, final RolloutBuilder rolloutBuilder) {
return new JpaEntityFactory(targetBuilder, rolloutBuilder);
}
/**

View File

@@ -1,46 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.jpa.builder;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.GenericTargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Builder implementation for {@link TargetFilterQuery}.
*/
public class JpaTargetFilterQueryBuilder implements TargetFilterQueryBuilder {
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
public JpaTargetFilterQueryBuilder(final DistributionSetManagement<? extends DistributionSet> distributionSetManagement) {
this.distributionSetManagement = distributionSetManagement;
}
@Override
public TargetFilterQueryUpdate update(final long id) {
return new GenericTargetFilterQueryUpdate(id);
}
@Override
public AutoAssignDistributionSetUpdate updateAutoAssign(final long id) {
return new AutoAssignDistributionSetUpdate(id);
}
@Override
public TargetFilterQueryCreate create() {
return new JpaTargetFilterQueryCreate(distributionSetManagement);
}
}

View File

@@ -1,48 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository.jpa.builder;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.builder.AbstractTargetFilterQueryUpdateCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
/**
* Create/build implementation.
*/
public class JpaTargetFilterQueryCreate extends AbstractTargetFilterQueryUpdateCreate<TargetFilterQueryCreate>
implements TargetFilterQueryCreate {
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
JpaTargetFilterQueryCreate(final DistributionSetManagement<? extends DistributionSet> distributionSetManagement) {
this.distributionSetManagement = distributionSetManagement;
}
@Override
public JpaTargetFilterQuery build() {
return new JpaTargetFilterQuery(name, query,
getAutoAssignDistributionSetId().map(distributionSetManagement::getValidAndComplete).orElse(null),
getAutoAssignActionType().filter(JpaTargetFilterQueryCreate::isAutoAssignActionTypeValid).orElse(null),
weight, getConfirmationRequired().orElse(false));
}
private static boolean isAutoAssignActionTypeValid(final ActionType actionType) {
if (!TargetFilterQuery.ALLOWED_AUTO_ASSIGN_ACTION_TYPES.contains(actionType)) {
throw new InvalidAutoAssignActionTypeException();
}
return true;
}
}

View File

@@ -99,7 +99,6 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.RetryCallback;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.backoff.FixedBackOffPolicy;
@@ -122,28 +121,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
* Maximum amount of Actions that are started at once.
*/
private static final int ACTION_PAGE_LIMIT = 1000;
private static final String QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT =
"DELETE FROM sp_action " +
"WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" +
" AND status IN (%s)" +
" AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT;
private static final String QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT = "DELETE FROM sp_action " + "WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + " AND status IN (%s)" + " AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT;
private static final EnumMap<Database, String> QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED;
static {
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED = new EnumMap<>(Database.class);
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(
Database.SQL_SERVER,
"DELETE TOP (" + ACTION_PAGE_LIMIT + ") FROM sp_action " +
"WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" +
" AND status IN (%s)" +
" AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at ");
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(
Database.POSTGRESQL,
"DELETE FROM sp_action " +
"WHERE id IN (SELECT id FROM sp_action " +
"WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" +
" AND status IN (%s)" +
" AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT + ")");
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.SQL_SERVER,
"DELETE TOP (" + ACTION_PAGE_LIMIT + ") FROM sp_action " + "WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + " AND status IN (%s)" + " AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at ");
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.put(Database.POSTGRESQL,
"DELETE FROM sp_action " + "WHERE id IN (SELECT id FROM sp_action " + "WHERE tenant=" + Jpa.nativeQueryParamPrefix() + "tenant" + " AND status IN (%s)" + " AND last_modified_at<" + Jpa.nativeQueryParamPrefix() + "last_modified_at LIMIT " + ACTION_PAGE_LIMIT + ")");
}
private final EntityManager entityManager;
@@ -161,8 +147,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private final RetryTemplate retryTemplate;
@SuppressWarnings("java:S107")
protected JpaDeploymentManagement(
final EntityManager entityManager, final ActionRepository actionRepository,
protected JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
final JpaDistributionSetManagement distributionSetManagement, final TargetRepository targetRepository,
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
final AfterTransactionCommitExecutor afterCommit, final PlatformTransactionManager txManager,
@@ -175,12 +160,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
this.targetRepository = targetRepository;
this.auditorProvider = auditorProvider;
this.txManager = txManager;
onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit,
actionRepository, actionStatusRepository, quotaManagement, this::isMultiAssignmentsEnabled,
this::isConfirmationFlowEnabled, repositoryProperties);
offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit,
actionRepository, actionStatusRepository, quotaManagement,
this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties);
onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository,
quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties);
offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository,
quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties);
this.tenantConfigurationManagement = tenantConfigurationManagement;
this.systemSecurityContext = systemSecurityContext;
this.tenantAware = tenantAware;
@@ -197,30 +180,28 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
public List<DistributionSetAssignmentResult> assignDistributionSets(
final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
public List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
return assignDistributionSets0(initiatedBy, deploymentRequests, actionMessage);
}
private List<DistributionSetAssignmentResult> assignDistributionSets0(
final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
private List<DistributionSetAssignmentResult> assignDistributionSets0(final String initiatedBy,
final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(deploymentRequests);
return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy);
}
@Override
public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(
final Collection<Entry<String, Long>> assignments, final String initiatedBy) {
public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(final Collection<Entry<String, Long>> assignments,
final String initiatedBy) {
final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList();
enforceMaxAssignmentsPerRequest(distinctAssignments.size());
final List<DeploymentRequest> deploymentRequests = distinctAssignments.stream()
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build())
.toList();
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build()).toList();
return assignDistributionSets(
auditorAware.getCurrentAuditor().orElse(tenantAware.getCurrentUsername()),
deploymentRequests, null, offlineDsAssignmentStrategy);
return assignDistributionSets(auditorAware.getCurrentAuditor().orElse(tenantAware.getCurrentUsername()), deploymentRequests, null,
offlineDsAssignmentStrategy);
}
@Override
@@ -231,8 +212,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
@Retryable(retryFor = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action cancelAction(final long actionId) {
return cancelAction0(actionId);
}
@@ -240,8 +221,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private Action cancelAction0(final long actionId) {
log.debug("cancelAction({})", actionId);
final JpaAction action = actionRepository.findById(actionId)
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
final JpaAction action = actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
if (action.isCancelingOrCanceled()) {
throw new CancelActionNotAllowedException("Actions in canceling or canceled state cannot be canceled");
@@ -297,8 +277,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public Optional<Action> findAction(final long actionId) {
return actionRepository.findById(actionId)
.filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId())))
.map(JpaAction.class::cast);
.filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))).map(JpaAction.class::cast);
}
@Override
@@ -326,8 +305,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public Slice<Action> findActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId);
return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable)
.map(Action.class::cast);
return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable).map(Action.class::cast);
}
@Override
@@ -357,8 +335,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final CriteriaQuery<String> selMsgQuery = msgQuery.select(join);
selMsgQuery.where(cb.equal(as.get(AbstractJpaBaseEntity_.id), actionStatusId));
final List<String> result = new ArrayList<>(entityManager.createQuery(selMsgQuery)
.setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize()).getResultList());
final List<String> result = new ArrayList<>(
entityManager.createQuery(selMsgQuery).setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize())
.getResultList());
return new PageImpl<>(result, pageable, result.size());
}
@@ -372,16 +351,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public Page<Action> findActiveActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId);
return actionRepository
.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true), pageable)
return actionRepository.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, true), pageable)
.map(Action.class::cast);
}
@Override
public Page<Action> findInActiveActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId);
return actionRepository
.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, false), pageable)
return actionRepository.findAll(ActionSpecifications.byTargetControllerIdAndActive(controllerId, false), pageable)
.map(Action.class::cast);
}
@@ -393,15 +370,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
@Retryable(retryFor = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action forceQuitAction(final long actionId) {
return forceQuitAction0(actionId);
}
private Action forceQuitAction0(final long actionId) {
final JpaAction action = actionRepository.findById(actionId)
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
final JpaAction action = actionRepository.findById(actionId).orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
if (!action.isCancelingOrCanceled()) {
throw new ForceQuitActionNotAllowedException(action.getId() + " is not canceled yet and cannot be force quit");
@@ -426,8 +402,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
@Retryable(retryFor = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action forceTargetAction(final long actionId) {
final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed)
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
@@ -441,8 +417,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
@Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
@Retryable(retryFor = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public void cancelInactiveScheduledActionsForTargets(final List<Long> targetIds) {
if (!isMultiAssignmentsEnabled()) {
targetRepository.getAccessController().ifPresent(v -> {
@@ -458,38 +434,32 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public void startScheduledActionsByRolloutGroupParent(final long rolloutId, final long distributionSetId, final Long rolloutGroupParentId) {
while (DeploymentHelper.runInNewTransaction(
txManager,
"startScheduledActions-" + rolloutId,
status -> {
final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT);
final Page<Action> groupScheduledActions;
if (rolloutGroupParentId == null) {
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId,
Action.Status.SCHEDULED);
} else {
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId,
rolloutGroupParentId, Action.Status.SCHEDULED);
}
while (DeploymentHelper.runInNewTransaction(txManager, "startScheduledActions-" + rolloutId, status -> {
final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT);
final Page<Action> groupScheduledActions;
if (rolloutGroupParentId == null) {
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId,
Action.Status.SCHEDULED);
} else {
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId,
rolloutGroupParentId, Action.Status.SCHEDULED);
}
if (groupScheduledActions.getContent().isEmpty()) {
return 0L;
} else {
// self invocation won't check @PreAuthorize but it is already checked for the method
startScheduledActions(groupScheduledActions.getContent());
return groupScheduledActions.getTotalElements();
}
}) > 0) ;
if (groupScheduledActions.getContent().isEmpty()) {
return 0L;
} else {
// self invocation won't check @PreAuthorize but it is already checked for the method
startScheduledActions(groupScheduledActions.getContent());
return groupScheduledActions.getTotalElements();
}
}) > 0) ;
}
@Override
public void startScheduledActions(final List<Action> rolloutGroupActions) {
// Close actions already assigned and collect pending assignments
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream()
.map(JpaAction.class::cast)
.map(this::closeActionIfSetWasAlreadyAssigned)
.filter(Objects::nonNull)
.toList();
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream().map(JpaAction.class::cast)
.map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull).toList();
if (pendingTargetAssignments.isEmpty()) {
return;
}
@@ -524,9 +494,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// the database.
final List<Integer> statusList = status.stream().map(Status::ordinal).toList();
final Query deleteQuery = entityManager.createNativeQuery(String.format(
getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(database),
Jpa.formatNativeQueryInClause("status", statusList)));
final Query deleteQuery = entityManager.createNativeQuery(
String.format(getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(database),
Jpa.formatNativeQueryInClause("status", statusList)));
deleteQuery.setParameter("tenant", tenantAware.getCurrentTenant().toUpperCase());
Jpa.setNativeQueryInParameter(deleteQuery, "status", statusList);
@@ -540,8 +510,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
public boolean hasPendingCancellations(final Long targetId) {
// target access checked in assertTargetReadAllowed
assertTargetReadAllowed(targetId);
return actionRepository
.exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING));
return actionRepository.exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING));
}
@Override
@@ -560,19 +529,17 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
});
if (cancelationType == CancelationType.FORCE) {
actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId()))
.forEach(action -> {
try {
assertTargetUpdateAllowed(action);
forceQuitAction0(action.getId());
log.debug("Action {} force canceled (force)", action.getId());
} catch (final InsufficientPermissionException e) {
log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e);
} catch (final EntityNotFoundException e) {
log.trace("Could not cancel action {} due to entity not found exception.", action.getId(),
e);
}
});
actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId())).forEach(action -> {
try {
assertTargetUpdateAllowed(action);
forceQuitAction0(action.getId());
log.debug("Action {} force canceled (force)", action.getId());
} catch (final InsufficientPermissionException e) {
log.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e);
} catch (final EntityNotFoundException e) {
log.trace("Could not cancel action {} due to entity not found exception.", action.getId(), e);
}
});
}
}
@@ -585,9 +552,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private static Map<Long, List<TargetWithActionType>> convertRequest(final Collection<DeploymentRequest> deploymentRequests) {
return deploymentRequests.stream().collect(
Collectors.groupingBy(DeploymentRequest::getDistributionSetId,
Collectors.mapping(DeploymentRequest::getTargetWithActionType, Collectors.toList())));
return deploymentRequests.stream().collect(Collectors.groupingBy(DeploymentRequest::getDistributionSetId,
Collectors.mapping(DeploymentRequest::getTargetWithActionType, Collectors.toList())));
}
/**
@@ -601,16 +567,13 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private static DistributionSetAssignmentResult buildAssignmentResult(
final JpaDistributionSet distributionSet,
final List<JpaAction> assignedActions, final int totalTargetsForAssignment) {
final JpaDistributionSet distributionSet, final List<JpaAction> assignedActions, final int totalTargetsForAssignment) {
final int alreadyAssignedTargetsCount = totalTargetsForAssignment - assignedActions.size();
return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions);
}
private static String getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(final Database database) {
return QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.getOrDefault(database,
QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT);
return QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED.getOrDefault(database, QUERY_DELETE_ACTIONS_BY_STATE_AND_LAST_MODIFIED_DEFAULT);
}
private static RetryTemplate createRetryTemplate() {
@@ -627,16 +590,13 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return template;
}
private List<DistributionSetAssignmentResult> assignDistributionSets(
final String initiatedBy,
final List<DeploymentRequest> deploymentRequests, final String actionMessage,
final AbstractDsAssignmentStrategy strategy) {
private List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy,
final List<DeploymentRequest> deploymentRequests, final String actionMessage, final AbstractDsAssignmentStrategy strategy) {
final List<DeploymentRequest> validatedRequests = validateAndFilterRequestForAssignments(deploymentRequests);
final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests);
final List<DistributionSetAssignmentResult> results = assignmentsByDsIds.entrySet().stream()
.map(entry -> assignDistributionSetToTargetsWithRetry(
initiatedBy, entry.getKey(), entry.getValue(), actionMessage, strategy))
.map(entry -> assignDistributionSetToTargetsWithRetry(initiatedBy, entry.getKey(), entry.getValue(), actionMessage, strategy))
.toList();
strategy.sendDeploymentEvents(results);
return results;
@@ -660,9 +620,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private void checkForMultiAssignment(final Collection<DeploymentRequest> deploymentRequests) {
if (!isMultiAssignmentsEnabled()) {
final long distinctTargetsInRequest = deploymentRequests.stream()
.map(request -> request.getTargetWithActionType().getControllerId())
.distinct()
.count();
.map(request -> request.getTargetWithActionType().getControllerId()).distinct().count();
if (distinctTargetsInRequest < deploymentRequests.size()) {
throw new MultiAssignmentIsNotEnabledException();
}
@@ -675,13 +633,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private void checkForTargetTypeCompatibility(final List<DeploymentRequest> deploymentRequests) {
final List<String> controllerIds = deploymentRequests.stream()
.map(DeploymentRequest::getControllerId)
.distinct()
.toList();
final List<Long> distSetIds = deploymentRequests.stream().map(DeploymentRequest::getDistributionSetId)
.distinct()
.toList();
final List<String> controllerIds = deploymentRequests.stream().map(DeploymentRequest::getControllerId).distinct().toList();
final List<Long> distSetIds = deploymentRequests.stream().map(DeploymentRequest::getDistributionSetId).distinct().toList();
if (controllerIds.size() > 1 && distSetIds.size() > 1) {
throw new IllegalStateException("Assigning multiple Distribution Sets to multiple Targets simultaneously is not allowed!");
@@ -696,14 +649,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private void checkCompatibilityForSingleDsAssignment(final Long distSetId, final List<String> controllerIds) {
final DistributionSetType distSetType = distributionSetManagement.getValidAndComplete(distSetId).getType();
final Set<String> incompatibleTargetTypes = ListUtils.partition(controllerIds, Constants.MAX_ENTRIES_IN_STATEMENT)
.stream()
final Set<String> incompatibleTargetTypes = ListUtils.partition(controllerIds, Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids)
.and(TargetSpecifications.notCompatibleWithDistributionSetType(distSetType.getId()))))
.flatMap(List::stream)
.map(Target::getTargetType)
.map(TargetType::getName)
.collect(Collectors.toSet());
.and(TargetSpecifications.notCompatibleWithDistributionSetType(distSetType.getId())))).flatMap(List::stream)
.map(Target::getTargetType).map(TargetType::getName).collect(Collectors.toSet());
if (!incompatibleTargetTypes.isEmpty()) {
throw new IncompatibleTargetTypeException(incompatibleTargetTypes, distSetType.getName());
@@ -717,13 +666,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// we assume that list of assigned DS is less than
// MAX_ENTRIES_IN_STATEMENT
final Set<DistributionSetType> incompatibleDistSetTypes = distributionSetManagement.get(distSetIds).stream()
.map(DistributionSet::getType)
.collect(Collectors.toSet());
.map(DistributionSet::getType).collect(Collectors.toSet());
incompatibleDistSetTypes.removeAll(target.getTargetType().getDistributionSetTypes());
if (!incompatibleDistSetTypes.isEmpty()) {
final Set<String> distSetTypeNames = incompatibleDistSetTypes.stream()
.map(DistributionSetType::getName)
final Set<String> distSetTypeNames = incompatibleDistSetTypes.stream().map(DistributionSetType::getName)
.collect(Collectors.toSet());
throw new IncompatibleTargetTypeException(target.getTargetType().getName(), distSetTypeNames);
}
@@ -731,27 +678,21 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private List<DeploymentRequest> filterByTargetUpdatable(final List<DeploymentRequest> deploymentRequests) {
final List<String> controllerIds = deploymentRequests.stream()
.map(DeploymentRequest::getControllerId)
.distinct()
.toList();
final List<String> controllerIds = deploymentRequests.stream().map(DeploymentRequest::getControllerId).distinct().toList();
final List<String> found = targetRepository
.findAll(AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(controllerIds))
.stream().map(JpaTarget::getControllerId).toList();
final List<String> found = targetRepository.findAll(AccessController.Operation.UPDATE,
TargetSpecifications.hasControllerIdIn(controllerIds)).stream().map(JpaTarget::getControllerId).toList();
if (found.size() != controllerIds.size()) {
return deploymentRequests.stream()
.filter(deploymentRequest -> found.contains(deploymentRequest.getControllerId())).toList();
return deploymentRequests.stream().filter(deploymentRequest -> found.contains(deploymentRequest.getControllerId())).toList();
}
return deploymentRequests;
}
private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(final String initiatedBy,
final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
private DistributionSetAssignmentResult assignDistributionSetToTargetsWithRetry(
final String initiatedBy, final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) {
final RetryCallback<DistributionSetAssignmentResult, ConcurrencyFailureException> retryCallback =
retryContext -> assignDistributionSetToTargets(initiatedBy, dsId, targetsWithActionType, actionMessage, assignmentStrategy);
return retryTemplate.execute(retryCallback);
return retryTemplate.execute(retryContext ->
assignDistributionSetToTargets(initiatedBy, dsId, targetsWithActionType, actionMessage, assignmentStrategy));
}
/**
@@ -777,29 +718,19 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
* {@link DistributionSetType}.
*/
private DistributionSetAssignmentResult assignDistributionSetToTargets(
final String initiatedBy, final Long dsId,
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final String initiatedBy, final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) {
final JpaDistributionSet distributionSet = distributionSetManagement.getValidAndComplete(dsId);
JpaDistributionSet distributionSet = distributionSetManagement.getValidAndComplete(dsId);
if (distributionSetManagement.isImplicitLockApplicable(distributionSet)) {
// without new transaction DS changed event is not thrown
DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> {
distributionSetManagement.lock(distributionSet.getId());
return null;
});
distributionSet = DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> distributionSetManagement.lock(dsId));
}
final List<String> providedTargetIds = targetsWithActionType.stream()
.map(TargetWithActionType::getControllerId)
.distinct()
.toList();
final List<String> providedTargetIds = targetsWithActionType.stream().map(TargetWithActionType::getControllerId).distinct().toList();
final List<String> existingTargetIds = ListUtils.partition(providedTargetIds, Constants.MAX_ENTRIES_IN_STATEMENT)
.stream()
final List<String> existingTargetIds = ListUtils.partition(providedTargetIds, Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.map(ids -> targetRepository.findAll(AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(ids)))
.flatMap(List::stream).map(JpaTarget::getControllerId)
.toList();
.flatMap(List::stream).map(JpaTarget::getControllerId).toList();
final List<JpaTarget> targetEntities = assignmentStrategy.findTargetsForAssignment(existingTargetIds, distributionSet.getId());
if (targetEntities.isEmpty()) {
@@ -807,21 +738,19 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
final List<TargetWithActionType> existingTargetsWithActionType = targetsWithActionType.stream()
.filter(target -> existingTargetIds.contains(target.getControllerId()))
.toList();
.filter(target -> existingTargetIds.contains(target.getControllerId())).toList();
final List<JpaAction> assignedActions = doAssignDistributionSetToTargets(
initiatedBy, existingTargetsWithActionType, actionMessage, assignmentStrategy, distributionSet, targetEntities);
return buildAssignmentResult(distributionSet, assignedActions, existingTargetsWithActionType.size());
}
private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult(
final JpaDistributionSet distributionSetEntity, final int alreadyAssignedCount) {
private DistributionSetAssignmentResult allTargetsAlreadyAssignedResult(final JpaDistributionSet distributionSetEntity,
final int alreadyAssignedCount) {
// detaching as it is not necessary to persist the set itself
entityManager.detach(distributionSetEntity);
// return with nothing as all targets had the DS already assigned
return new DistributionSetAssignmentResult(distributionSetEntity, alreadyAssignedCount,
Collections.emptyList());
return new DistributionSetAssignmentResult(distributionSetEntity, alreadyAssignedCount, Collections.emptyList());
}
private List<JpaAction> doAssignDistributionSetToTargets(final String initiatedBy,
@@ -837,8 +766,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// not active before and the manual assignment which has been done cancels them
targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets);
setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity, targetEntitiesIdsChunks);
final Map<TargetWithActionType, JpaAction> assignedActions = createActions(
targetsWithActionType, targetEntities, distributionSetEntity, assignmentStrategy, initiatedBy);
final Map<TargetWithActionType, JpaAction> assignedActions = createActions(targetsWithActionType, targetEntities, distributionSetEntity,
assignmentStrategy, initiatedBy);
// create initial action status when action is created, so we remember
// the initial running status because we will change the status
// of the action itself and with this action status we have a nicer action history.
@@ -856,12 +785,12 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private void enforceMaxActionsPerTarget(final Collection<DeploymentRequest> deploymentRequests) {
final int quota = quotaManagement.getMaxActionsPerTarget();
final Map<String, Long> countOfTargetInRequest = deploymentRequests.stream()
.map(DeploymentRequest::getControllerId)
final Map<String, Long> countOfTargetInRequest = deploymentRequests.stream().map(DeploymentRequest::getControllerId)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
countOfTargetInRequest.forEach((controllerId, count) -> QuotaHelper.assertAssignmentQuota(controllerId, count,
quota, Action.class, Target.class, actionRepository::countByTargetControllerId));
countOfTargetInRequest.forEach(
(controllerId, count) -> QuotaHelper.assertAssignmentQuota(controllerId, count, quota, Action.class, Target.class,
actionRepository::countByTargetControllerId));
}
private void closeOrCancelActiveActions(final AbstractDsAssignmentStrategy assignmentStrategy, final List<List<Long>> targetIdsChunks) {
@@ -872,16 +801,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
}
private void setAssignedDistributionSetAndTargetUpdateStatus(
final AbstractDsAssignmentStrategy assignmentStrategy,
private void setAssignedDistributionSetAndTargetUpdateStatus(final AbstractDsAssignmentStrategy assignmentStrategy,
final JpaDistributionSet set, final List<List<Long>> targetIdsChunks) {
final String currentUser = auditorProvider.getCurrentAuditor().orElse(null);
assignmentStrategy.setAssignedDistributionSetAndTargetStatus(set, targetIdsChunks, currentUser);
}
private Map<TargetWithActionType, JpaAction> createActions(
final Collection<TargetWithActionType> targetsWithActionType, final List<JpaTarget> targets, final JpaDistributionSet set,
final AbstractDsAssignmentStrategy assignmentStrategy, final String initiatedBy) {
private Map<TargetWithActionType, JpaAction> createActions(final Collection<TargetWithActionType> targetsWithActionType,
final List<JpaTarget> targets, final JpaDistributionSet set, final AbstractDsAssignmentStrategy assignmentStrategy,
final String initiatedBy) {
final Map<TargetWithActionType, JpaAction> persistedActions = new LinkedHashMap<>();
for (final TargetWithActionType twt : targetsWithActionType) {
final JpaAction targetAction = assignmentStrategy.createTargetAction(initiatedBy, twt, targets, set);
@@ -892,9 +820,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return persistedActions;
}
private void createActionsStatus(
final Map<TargetWithActionType, JpaAction> actions,
final AbstractDsAssignmentStrategy assignmentStrategy, final String actionMessage) {
private void createActionsStatus(final Map<TargetWithActionType, JpaAction> actions, final AbstractDsAssignmentStrategy assignmentStrategy,
final String actionMessage) {
actionStatusRepository.saveAll(actions.entrySet().stream().map(entry -> {
final JpaAction action = entry.getValue();
final JpaActionStatus actionStatus = assignmentStrategy.createActionStatus(action, actionMessage);
@@ -921,8 +848,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// assignment already
if (!isConfirmationRequired) {
// confirmation given on assignment dialog
actionStatus.addMessage(
String.format("Assignment confirmed by initiator [%s].", action.getInitiatedBy()));
actionStatus.addMessage(String.format("Assignment confirmed by initiator [%s].", action.getInitiatedBy()));
} else if (action.getTarget().getAutoConfirmationStatus() != null) {
// auto-confirmation is configured
actionStatus.addMessage(action.getTarget().getAutoConfirmationStatus().constructActionMessage());
@@ -931,8 +857,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
} else {
actionStatus
.addMessage("Waiting for the confirmation by the device before processing with the deployment");
actionStatus.addMessage("Waiting for the confirmation by the device before processing with the deployment");
}
}
}
@@ -952,8 +877,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
final JpaTarget target = action.getTarget();
if (target.getAssignedDistributionSet() != null
&& action.getDistributionSet().getId().equals(target.getAssignedDistributionSet().getId())) {
if (target.getAssignedDistributionSet() != null && action.getDistributionSet().getId()
.equals(target.getAssignedDistributionSet().getId())) {
// the target has already the distribution set assigned, we don't
// need to start the scheduled action, just finish it.
log.debug("Target {} has distribution set {} assigned. Closing action...", target.getControllerId(),
@@ -990,8 +915,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private List<JpaAction> activateActionsOfRolloutGroup(final List<JpaAction> actions) {
actions.forEach(action -> {
action.setActive(true);
final boolean confirmationRequired = action.getRolloutGroup().isConfirmationRequired()
&& action.getTarget().getAutoConfirmationStatus() == null;
final boolean confirmationRequired = action.getRolloutGroup().isConfirmationRequired() && action.getTarget()
.getAutoConfirmationStatus() == null;
if (isConfirmationFlowEnabled() && confirmationRequired) {
action.setStatus(Status.WAIT_FOR_CONFIRMATION);
return;
@@ -1022,18 +947,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private boolean isMultiAssignmentsEnabled() {
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
.isMultiAssignmentsEnabled();
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).isMultiAssignmentsEnabled();
}
private boolean isConfirmationFlowEnabled() {
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
.isConfirmationFlowEnabled();
return TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).isConfirmationFlowEnabled();
}
private <T extends Serializable> T getConfigValue(final String key, final Class<T> valueType) {
return systemSecurityContext
.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue());
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement.getConfigurationValue(key, valueType).getValue());
}
private void assertTargetReadAllowed(final Long targetId) {
@@ -1051,8 +973,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private JpaAction assertTargetUpdateAllowed(final JpaAction action) {
targetRepository.findOne(TargetSpecifications.hasId(action.getTarget().getId())).ifPresentOrElse(
target -> targetRepository.getAccessController()
.ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target)),
() -> {
.ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target)), () -> {
throw new EntityNotFoundException(Action.class, action);
});
return action;

View File

@@ -78,8 +78,7 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
public void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation) {
log.debug("Invalidate distribution sets {}", distributionSetInvalidation.getDistributionSetIds());
final String tenant = tenantAware.getCurrentTenant();
if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
distributionSetInvalidation.isCancelRollouts())) {
if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts())) {
final String handlerId = JpaRolloutManagement.createRolloutLockKey(tenant);
final Lock lock = lockRegistry.obtain(handlerId);
try {
@@ -122,17 +121,15 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
return cancelationType != CancelationType.NONE || cancelRollouts;
}
private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation,
final String tenant) {
private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation, final String tenant) {
DeploymentHelper.runInNewTransaction(txManager, tenant + "-invalidateDS", status -> {
distributionSetInvalidation.getDistributionSetIds().forEach(setId -> invalidateDistributionSet(setId,
distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts()));
distributionSetInvalidation.getDistributionSetIds().forEach(setId -> invalidateDistributionSet(
setId, distributionSetInvalidation.getCancelationType(), distributionSetInvalidation.isCancelRollouts()));
return 0;
});
}
private void invalidateDistributionSet(final long setId, final CancelationType cancelationType,
final boolean cancelRollouts) {
private void invalidateDistributionSet(final long setId, final CancelationType cancelationType, final boolean cancelRollouts) {
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
if (!distributionSet.isComplete()) {
throw new IncompleteDistributionSetException("Distribution set of type "

View File

@@ -248,23 +248,27 @@ public class JpaDistributionSetManagement
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public void lock(final long id) {
public JpaDistributionSet lock(final long id) {
final JpaDistributionSet distributionSet = getById(id);
if (!distributionSet.isLocked()) {
if (distributionSet.isLocked()) {
return distributionSet;
} else {
lockSoftwareModules(distributionSet);
distributionSet.lock();
jpaRepository.save(distributionSet);
return jpaRepository.save(distributionSet);
}
}
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public void unlock(final long id) {
public JpaDistributionSet unlock(final long id) {
final JpaDistributionSet distributionSet = getById(id);
if (distributionSet.isLocked()) {
distributionSet.unlock();
jpaRepository.save(distributionSet);
return jpaRepository.save(distributionSet);
} else {
return distributionSet;
}
}

View File

@@ -10,11 +10,11 @@
package org.eclipse.hawkbit.repository.jpa.management;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import jakarta.validation.constraints.NotNull;
import jakarta.persistence.EntityManager;
import cz.jirutka.rsql.parser.RSQLParserException;
import lombok.extern.slf4j.Slf4j;
@@ -27,17 +27,12 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.GenericTargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeException;
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
@@ -53,14 +48,11 @@ import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProperty;
import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.AuditorAware;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@@ -74,9 +66,10 @@ import org.springframework.validation.annotation.Validated;
@Validated
@Service
@ConditionalOnBooleanProperty(prefix = "hawkbit.jpa", name = { "enabled", "target-filter-management" }, matchIfMissing = true)
class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
class JpaTargetFilterQueryManagement
extends AbstractJpaRepositoryManagement<JpaTargetFilterQuery, TargetFilterQueryManagement.Create, TargetFilterQueryManagement.Update, TargetFilterQueryRepository, TargetFilterQueryFields>
implements TargetFilterQueryManagement<JpaTargetFilterQuery>{
private final TargetFilterQueryRepository targetFilterQueryRepository;
private final TargetManagement targetManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final QuotaManagement quotaManagement;
@@ -87,12 +80,12 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
private final AuditorAware<String> auditorAware;
protected JpaTargetFilterQueryManagement(
final TargetFilterQueryRepository targetFilterQueryRepository,
final TargetFilterQueryRepository targetFilterQueryRepository, final EntityManager entityManager,
final TargetManagement targetManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final QuotaManagement quotaManagement, final TenantConfigurationManagement tenantConfigurationManagement,
final RepositoryProperties repositoryProperties,
final SystemSecurityContext systemSecurityContext, final ContextAware contextAware, final AuditorAware<String> auditorAware) {
this.targetFilterQueryRepository = targetFilterQueryRepository;
super(targetFilterQueryRepository, entityManager);
this.targetManagement = targetManagement;
this.distributionSetManagement = distributionSetManagement;
this.quotaManagement = quotaManagement;
@@ -104,38 +97,22 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
}
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public TargetFilterQuery create(final TargetFilterQueryCreate c) {
final JpaTargetFilterQueryCreate create = (JpaTargetFilterQueryCreate) c;
public JpaTargetFilterQuery create(final Create create) {
validate(create);
return super.create(create);
}
create.getQuery().ifPresent(query -> {
// validate the RSQL query syntax
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
// enforce the 'max targets per auto assign' quota right here even
// if the result of the filter query can vary over time
create.getAutoAssignDistributionSetId().ifPresent(dsId -> {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement)
.validate(create);
assertMaxTargetsQuota(query, create.getName().orElse(null), dsId);
});
});
return targetFilterQueryRepository.save(AccessController.Operation.CREATE, create.build());
@Override
public List<JpaTargetFilterQuery> create(final Collection<Create> create) {
create.forEach(this::validate);
return super.create(create);
}
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public void delete(final long targetFilterQueryId) {
if (!targetFilterQueryRepository.existsById(targetFilterQueryId)) {
throw new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId);
}
targetFilterQueryRepository.deleteById(targetFilterQueryId);
public JpaTargetFilterQuery update(final Update update) {
validate(update);
return super.update(update);
}
@Override
@@ -149,67 +126,9 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
}
}
@Override
public Slice<TargetFilterQuery> findAll(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, null, pageable);
}
@Override
public long count() {
return targetFilterQueryRepository.count();
}
@Override
public long countByAutoAssignDistributionSetId(final long autoAssignDistributionSetId) {
return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
}
@Override
public Slice<TargetFilterQuery> findByName(final String name, final Pageable pageable) {
if (ObjectUtils.isEmpty(name)) {
return findAll(pageable);
}
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)), pageable
);
}
@Override
public long countByName(final String name) {
if (ObjectUtils.isEmpty(name)) {
return count();
}
return JpaManagementHelper.countBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.likeName(name)));
}
@Override
public Page<TargetFilterQuery> findByRsql(final String rsqlFilter, final Pageable pageable) {
final List<Specification<JpaTargetFilterQuery>> specList = !ObjectUtils.isEmpty(rsqlFilter)
? Collections.singletonList(RsqlUtility.getInstance().buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class))
: Collections.emptyList();
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, specList, pageable);
}
@Override
public Slice<TargetFilterQuery> findByQuery(final String query, final Pageable pageable) {
final List<Specification<JpaTargetFilterQuery>> specList = !ObjectUtils.isEmpty(query)
? Collections.singletonList(TargetFilterQuerySpecification.equalsQuery(query))
: Collections.emptyList();
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository, specList, pageable);
}
@Override
public Slice<TargetFilterQuery> findByAutoAssignDistributionSetId(final long setId, @NotNull final Pageable pageable) {
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet)), pageable
);
return jpaRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
}
@Override
@@ -222,59 +141,20 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
specList.add(RsqlUtility.getInstance().buildRsqlSpecification(rsql, TargetFilterQueryFields.class));
}
return JpaManagementHelper.findAllWithCountBySpec(targetFilterQueryRepository, specList, pageable);
return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable);
}
@Override
public Slice<TargetFilterQuery> findWithAutoAssignDS(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(targetFilterQueryRepository,
Collections.singletonList(TargetFilterQuerySpecification.withAutoAssignDS()), pageable
);
}
@Override
public Optional<TargetFilterQuery> get(final long targetFilterQueryId) {
return targetFilterQueryRepository.findById(targetFilterQueryId).map(TargetFilterQuery.class::cast);
}
@Override
public Optional<TargetFilterQuery> getByName(final String targetFilterQueryName) {
return targetFilterQueryRepository.findByName(targetFilterQueryName);
}
@Override
@Transactional
public TargetFilterQuery update(final TargetFilterQueryUpdate u) {
final GenericTargetFilterQueryUpdate update = (GenericTargetFilterQueryUpdate) u;
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.getId());
update.getName().ifPresent(targetFilterQuery::setName);
update.getQuery().ifPresent(query -> {
// enforce the 'max targets per auto assignment'-quota only if the
// query is going to change
if (targetFilterQuery.getAutoAssignDistributionSet() != null
&& !query.equals(targetFilterQuery.getQuery())) {
assertMaxTargetsQuota(query, targetFilterQuery.getName(),
targetFilterQuery.getAutoAssignDistributionSet().getId());
}
// set the new query
targetFilterQuery.setQuery(query);
});
update.getConfirmationRequired().ifPresent(targetFilterQuery::setConfirmationRequired);
return targetFilterQueryRepository.save(targetFilterQuery);
return JpaManagementHelper.findAllWithoutCountBySpec(
jpaRepository, List.of(TargetFilterQuerySpecification.withAutoAssignDS()), pageable);
}
@Override
@Transactional
public TargetFilterQuery updateAutoAssignDS(final AutoAssignDistributionSetUpdate update) {
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(
update.getTargetFilterId());
if (update.getDsId() == null) {
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.targetFilterId());
if (update.dsId() == null) {
targetFilterQuery.setAccessControlContext(null);
targetFilterQuery.setAutoAssignDistributionSet(null);
targetFilterQuery.setAutoAssignActionType(null);
@@ -283,9 +163,9 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
targetFilterQuery.setConfirmationRequired(false);
} else {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update);
assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.getDsId());
assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.dsId());
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
.getValidAndComplete(update.getDsId());
.getValidAndComplete(update.dsId());
if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) {
distributionSetManagement.lock(distributionSet.getId());
@@ -293,23 +173,20 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
targetFilterQuery.setAutoAssignDistributionSet(distributionSet);
contextAware.getCurrentContext().ifPresent(targetFilterQuery::setAccessControlContext);
targetFilterQuery.setAutoAssignInitiatedBy(
auditorAware.getCurrentAuditor().orElse(targetFilterQuery.getCreatedBy()));
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType()));
targetFilterQuery.setAutoAssignWeight(
update.getWeight() == null ? repositoryProperties.getActionWeightIfAbsent() : update.getWeight());
targetFilterQuery.setAutoAssignInitiatedBy(auditorAware.getCurrentAuditor().orElse(targetFilterQuery.getCreatedBy()));
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.actionType()));
targetFilterQuery.setAutoAssignWeight(update.weight() == null ? repositoryProperties.getActionWeightIfAbsent() : update.weight());
final boolean confirmationRequired =
update.getConfirmationRequired() == null ?
isConfirmationFlowEnabled() : update.getConfirmationRequired();
update.confirmationRequired() == null ? isConfirmationFlowEnabled() : update.confirmationRequired();
targetFilterQuery.setConfirmationRequired(confirmationRequired);
}
return targetFilterQueryRepository.save(targetFilterQuery);
return jpaRepository.save(targetFilterQuery);
}
@Override
@Transactional
public void cancelAutoAssignmentForDistributionSet(final long distributionSetId) {
targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetId);
jpaRepository.unsetAutoAssignDistributionSetAndActionTypeAndAccessContext(distributionSetId);
log.debug("Auto assignments for distribution sets {} deactivated", distributionSetId);
}
@@ -331,8 +208,7 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
}
private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) {
return targetFilterQueryRepository.findById(queryId)
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
return jpaRepository.findById(queryId).orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
}
private void assertMaxTargetsQuota(final String query, final String filterName, final long dsId) {
@@ -340,4 +216,51 @@ class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(dsId, query),
quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class, null);
}
}
private void validate(final Create create) {
Optional.ofNullable(create.getAutoAssignDistributionSet()).ifPresent(distributionSet -> {
if (!distributionSet.isValid()) {
throw new InvalidDistributionSetException();
}
if (!distributionSet.isComplete()) {
throw new IncompleteDistributionSetException();
}
});
Optional.ofNullable(create.getAutoAssignActionType()).ifPresent(actionType -> {
if (!TargetFilterQuery.ALLOWED_AUTO_ASSIGN_ACTION_TYPES.contains(actionType)) {
throw new InvalidAutoAssignActionTypeException();
}
});
Optional.ofNullable(create.getQuery()).ifPresent(query -> {
// validate the RSQL query syntax
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
// enforce the 'max targets per auto assign' quota right here even if the result of the filter query can vary over time
Optional.ofNullable(create.getAutoAssignDistributionSet()).ifPresent(dsId -> {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(create);
assertMaxTargetsQuota(query, create.getName(), dsId.getId());
});
});
if (create.getAutoAssignWeight() == null) {
create.setAutoAssignWeight(create.getAutoAssignDistributionSet() == null ? 0 : repositoryProperties.getActionWeightIfAbsent());
}
}
private void validate(final Update update) {
final JpaTargetFilterQuery targetFilterQuery = findTargetFilterQueryOrThrowExceptionIfNotFound(update.getId());
Optional.ofNullable(update.getQuery()).ifPresent(query -> {
// validate the RSQL query syntax
RsqlUtility.getInstance().validateRsqlFor(query, TargetFields.class, JpaTarget.class);
Optional.ofNullable(targetFilterQuery.getAutoAssignDistributionSet()).ifPresent(autoAssignDs -> {
// enforce the 'max targets per auto assignment'-quota only if the query is going to change
if (!query.equals(targetFilterQuery.getQuery())) {
assertMaxTargetsQuota(query, targetFilterQuery.getName(), autoAssignDs.getId());
}
});
// set the new query
targetFilterQuery.setQuery(query);
});
}
}

View File

@@ -64,11 +64,11 @@ public class JpaTargetFilterQuery extends AbstractJpaTenantAwareBaseEntity imple
@NotEmpty
private String query;
@ManyToOne(optional = true, fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class)
@ManyToOne(fetch = FetchType.LAZY, targetEntity = JpaDistributionSet.class)
@JoinColumn(
name = "auto_assign_distribution_set",
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_target_filter_query_auto_assign_distribution_set"))
private JpaDistributionSet autoAssignDistributionSet;
private DistributionSet autoAssignDistributionSet;
@Column(name = "auto_assign_action_type")
@Convert(converter = JpaAction.ActionTypeConverter.class)

View File

@@ -33,22 +33,7 @@ public final class TargetFilterQuerySpecification {
* @return the {@link JpaTargetFilterQuery} {@link Specification}
*/
public static Specification<JpaTargetFilterQuery> equalsQuery(final String queryValue) {
return (targetFilterQueryRoot, query, cb) -> cb.equal(targetFilterQueryRoot.get(JpaTargetFilterQuery_.query),
queryValue);
}
/**
* {@link Specification} for retrieving {@link JpaTargetFilterQuery}s based
* on is {@link JpaTargetFilterQuery#getName()}.
*
* @param searchText of the filter
* @return the {@link JpaTargetFilterQuery} {@link Specification}
*/
public static Specification<JpaTargetFilterQuery> likeName(final String searchText) {
return (targetFilterQueryRoot, query, cb) -> {
final String searchTextToLower = searchText.toLowerCase();
return cb.like(cb.lower(targetFilterQueryRoot.get(JpaTargetFilterQuery_.name)), searchTextToLower);
};
return (targetFilterQueryRoot, query, cb) -> cb.equal(targetFilterQueryRoot.get(JpaTargetFilterQuery_.query), queryValue);
}
/**

View File

@@ -11,10 +11,9 @@ package org.eclipse.hawkbit.repository.jpa.utils;
import java.util.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.exception.NoWeightProvidedInMultiAssignmentModeException;
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.model.DeploymentRequest;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.security.SystemSecurityContext;
@@ -29,8 +28,8 @@ public final class WeightValidationHelper {
private final TenantConfigurationManagement tenantConfigurationManagement;
private final SystemSecurityContext systemSecurityContext;
private WeightValidationHelper(final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
private WeightValidationHelper(
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) {
this.systemSecurityContext = systemSecurityContext;
this.tenantConfigurationManagement = tenantConfigurationManagement;
}
@@ -41,8 +40,8 @@ public final class WeightValidationHelper {
* @param systemSecurityContext security context used to get the tenant and for execution
* @param tenantConfigurationManagement to get the value from
*/
public static WeightValidationHelper usingContext(final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
public static WeightValidationHelper usingContext(
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement) {
return new WeightValidationHelper(systemSecurityContext, tenantConfigurationManagement);
}
@@ -74,9 +73,8 @@ public final class WeightValidationHelper {
*
* @param targetFilterQueryCreate the target filter query
*/
public void validate(final JpaTargetFilterQueryCreate targetFilterQueryCreate) {
validateWeight(targetFilterQueryCreate.getAutoAssignWeight().orElse(null));
public void validate(final TargetFilterQueryManagement.Create targetFilterQueryCreate) {
validateWeight(targetFilterQueryCreate.getAutoAssignWeight());
}
/**
@@ -84,16 +82,14 @@ public final class WeightValidationHelper {
*
* @param autoAssignDistributionSetUpdate the auto assignment distribution set update
*/
public void validate(final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate) {
validateWeight(autoAssignDistributionSetUpdate.getWeight());
public void validate(final TargetFilterQueryManagement.AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate) {
validateWeight(autoAssignDistributionSetUpdate.weight());
}
/**
* Checks if the weight is valid
*
* @param weight weight tied to the rollout, auto assignment, or online
* assignment.
* @param weight weight tied to the rollout, auto assignment, or online assignment.
*/
public void validateWeight(final Integer weight) {
final boolean hasWeight = weight != null;
@@ -101,8 +97,7 @@ public final class WeightValidationHelper {
}
/**
* Checks if the weight is valid with the multi-assignments being turned
* off/on.
* Checks if the weight is valid with the multi-assignments being turned off/on.
*
* @param hasWeight indicator of the weight if it has numerical value
* @param hasNoWeight indicator of the weight if it doesn't have a numerical value
@@ -119,4 +114,4 @@ public final class WeightValidationHelper {
throw new NoWeightProvidedInMultiAssignmentModeException();
}
}
}
}

View File

@@ -26,7 +26,7 @@ import java.util.Map;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
@@ -259,7 +259,7 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
distributionSetManagement.lock(hidden.getId());
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test").query("id==*"));
.create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());
runAs(withUser("user",
READ_REPOSITORY,
@@ -268,14 +268,14 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
// read / update target needed to update target filter query
READ_TARGET, UPDATE_TARGET), () -> {
assertThat(targetFilterQueryManagement
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(permitted.getId())
.updateAutoAssignDS(new TargetFilterQueryManagement.AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(permitted.getId())
.actionType(Action.ActionType.FORCED).confirmationRequired(false))
.getAutoAssignDistributionSet().getId()).isEqualTo(permitted.getId());
targetFilterQueryManagement
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
.updateAutoAssignDS(new TargetFilterQueryManagement.AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
.ds(readOnly.getId()).actionType(Action.ActionType.FORCED).confirmationRequired(false))
.getAutoAssignDistributionSet().getId();
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(
final TargetFilterQueryManagement.AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new TargetFilterQueryManagement.AutoAssignDistributionSetUpdate(
targetFilterQuery.getId())
.ds(hidden.getId()).actionType(Action.ActionType.FORCED).confirmationRequired(false);
assertThatThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate))

View File

@@ -25,6 +25,8 @@ import java.util.List;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
@@ -103,7 +105,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
});
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test").query("id==*"));
.create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> {
// verify targetManagement#findByTargetFilterQuery
@@ -314,7 +316,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("testName").query("id==*"));
.create(TargetFilterQueryManagement.Create.builder().name("testName").query("id==*").build());
runAs(withUser("user",
READ_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")" +
@@ -322,8 +324,8 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
UPDATE_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")",
READ_REPOSITORY + "/id==" + distributionSet.getId()), () -> {
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()));
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
autoAssignChecker.checkAllTargets();

View File

@@ -12,17 +12,16 @@ package org.eclipse.hawkbit.repository.jpa.autoassign;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetManagement.Create;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
@@ -80,9 +79,9 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
// target filter query that matches all targets
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*"));
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(secondDistributionSet.getId()));
.create(Create.builder().name("filterA").query("name==*").build());
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(secondDistributionSet.getId()));
// Run the check
autoAssignChecker.checkAllTargets();
@@ -116,11 +115,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final DistributionSet setB = testdataFactory.createDistributionSet("dsB");
// target filter query that matches all targets
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(entityFactory
.targetFilterQuery()
.updateAutoAssign(targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
.ds(setA.getId()));
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.create(Create.builder().name("filterA").query("name==*").build()).getId())
.ds(setA.getId()));
implicitLock(setA);
final String targetDsAIdPref = "targ";
@@ -169,10 +167,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final DistributionSet toAssignDs = testdataFactory.createDistributionSet();
// target filter query that matches all targets
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
.ds(toAssignDs.getId()));
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.create(Create.builder().name("filterA").query("name==*").build()).getId())
.ds(toAssignDs.getId()));
implicitLock(toAssignDs);
final List<Target> targets = testdataFactory.createTargets(25);
@@ -200,11 +198,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
enableConfirmationFlow();
}
targetFilterQueryManagement.updateAutoAssignDS(entityFactory
.targetFilterQuery()
.updateAutoAssign(targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
.ds(distributionSet.getId()).confirmationRequired(confirmationRequired));
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.create(Create.builder().name("filterA").query("name==*").build()).getId())
.ds(distributionSet.getId()).confirmationRequired(confirmationRequired));
final String targetDsAIdPref = "targ";
final List<Target> targets = testdataFactory.createTargets(20, targetDsAIdPref,
@@ -231,10 +228,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
}
// target filter query that matches all targets
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("filterA").query("name==*")).getId())
.ds(toAssignDs.getId()).confirmationRequired(confirmationRequired));
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQueryManagement
.create(Create.builder().name("filterA").query("name==*").build()).getId())
.ds(toAssignDs.getId()).confirmationRequired(confirmationRequired));
final List<Target> targets = testdataFactory.createTargets(25);
@@ -252,7 +249,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
void checkAutoAssignWithFailures() {
// incomplete distribution set that will be assigned
final DistributionSet setF = distributionSetManagement.create(Create.builder()
final DistributionSet setF = distributionSetManagement.create(DistributionSetManagement.Create.builder()
.type(testdataFactory.findOrCreateDefaultTestDsType())
.name("dsA").version("1")
.build());
@@ -263,15 +260,15 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final String targetDsFIdPref = "targB";
final Long filterId = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("filterA").query("id==" + targetDsFIdPref + "*"))
Create.builder().name("filterA").query("id==" + targetDsFIdPref + "*").build())
.getId();
final AutoAssignDistributionSetUpdate targetFilterQuery = entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(setF.getId());
final AutoAssignDistributionSetUpdate targetFilterQuery = new AutoAssignDistributionSetUpdate(filterId).ds(setF.getId());
// target filter query that matches first bunch of targets, that should fail
assertThatExceptionOfType(IncompleteDistributionSetException.class).isThrownBy(
() -> targetFilterQueryManagement.updateAutoAssignDS(targetFilterQuery));
// target filter query that matches failed bunch of targets
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("filterB")
.query("id==" + targetDsAIdPref + "*").autoAssignDistributionSet(setA.getId()));
targetFilterQueryManagement.create(Create.builder().name("filterB")
.query("id==" + targetDsAIdPref + "*").autoAssignDistributionSet(setA).build());
implicitLock(setA);
final List<Target> targetsF = testdataFactory.createTargets(10, targetDsFIdPref,
@@ -308,13 +305,11 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final String targetDsBIdPref = "B";
final String targetDsCIdPref = "C";
final List<Target> targetsA = createTargetsAndAutoAssignDistSet(targetDsAIdPref, 5, distributionSet,
ActionType.FORCED);
final List<Target> targetsA = createTargetsAndAutoAssignDistSet(targetDsAIdPref, 5, distributionSet, ActionType.FORCED);
implicitLock(distributionSet);
final List<Target> targetsB = createTargetsAndAutoAssignDistSet(targetDsBIdPref, 10, distributionSet,
ActionType.SOFT);
final List<Target> targetsC = createTargetsAndAutoAssignDistSet(targetDsCIdPref, 10, distributionSet,
ActionType.DOWNLOAD_ONLY);
final DistributionSet distributionSetLocked = distributionSetManagement.get(distributionSet.getId()).orElseThrow();
final List<Target> targetsB = createTargetsAndAutoAssignDistSet(targetDsBIdPref, 10, distributionSetLocked, ActionType.SOFT);
final List<Target> targetsC = createTargetsAndAutoAssignDistSet(targetDsCIdPref, 10, distributionSetLocked, ActionType.DOWNLOAD_ONLY);
final int targetsCount = targetsA.size() + targetsB.size() + targetsC.size();
@@ -339,8 +334,9 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final int weight = 32;
enableMultiAssignments();
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*")
.autoAssignDistributionSet(ds).autoAssignWeight(weight));
targetFilterQueryManagement.create(Create.builder()
.name("a").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(weight)
.build());
testdataFactory.createTargets(amountOfTargets);
autoAssignChecker.checkAllTargets();
@@ -357,8 +353,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
void filterWithoutWeightWorksInMultiAssignmentMode() {
final int amountOfTargets = 5;
final DistributionSet ds = testdataFactory.createDistributionSet();
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("a").query("name==*").autoAssignDistributionSet(ds));
targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").autoAssignDistributionSet(ds).build());
enableMultiAssignments();
testdataFactory.createTargets(amountOfTargets);
@@ -382,8 +377,8 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
.findOrCreateDistributionSetType("incompatibleDsType1", "incompDsType1");
final DistributionSetType incompatibleDsType2 = testdataFactory
.findOrCreateDistributionSetType("incompatibleDsType2", "incompDsType2");
final TargetFilterQuery testFilter = targetFilterQueryManagement.create(entityFactory.targetFilterQuery()
.create().name("test-filter").query("name==*").autoAssignDistributionSet(testDs));
final TargetFilterQuery testFilter = targetFilterQueryManagement.create(
Create.builder().name("test-filter").query("name==*").autoAssignDistributionSet(testDs).build());
final TargetType incompatibleEmptyType = testdataFactory.createTargetType("incompatibleEmptyType", Set.of());
final TargetType incompatibleSingleType = testdataFactory.createTargetType(
@@ -429,12 +424,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
Arguments.of(false, false, Status.RUNNING));
}
/**
* @param set the expected distribution set
* @param targets the targets that should have it
*/
private void verifyThatTargetsHaveDistributionSetAssignment(
final DistributionSet set, final List<Target> targets, final int count) {
private void verifyThatTargetsHaveDistributionSetAssignment(final DistributionSet set, final List<Target> targets, final int count) {
final List<Long> targetIds = targets.stream().map(Target::getId).toList();
final Slice<Target> targetsAll = targetManagement.findAll(PAGE);
@@ -442,22 +432,19 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
for (final Target target : targetsAll) {
if (targetIds.contains(target.getId())) {
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()))
.as("assigned DS").contains(set);
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId())).as("assigned DS").contains(set);
}
}
}
private void verifyThatTargetsHaveDistributionSetAssignedAndActionStatus(final DistributionSet set,
final List<Target> targets, final Action.Status status) {
private void verifyThatTargetsHaveDistributionSetAssignedAndActionStatus(
final DistributionSet set, final List<Target> targets, final Action.Status status) {
final List<String> targetIds = targets.stream().map(Target::getControllerId).toList();
final List<Target> targetsWithAssignedDS = targetManagement.findByAssignedDistributionSet(set.getId(), PAGE).getContent();
assertThat(targetsWithAssignedDS).isNotEmpty();
assertThat(targetsWithAssignedDS).allMatch(target -> targetIds.contains(target.getControllerId()));
final List<Action> actionsByDs = findActionsByDistributionSet(PAGE, set.getId())
.getContent();
final List<Action> actionsByDs = findActionsByDistributionSet(PAGE, set.getId()).getContent();
assertThat(actionsByDs).hasSize(targets.size());
assertThat(actionsByDs).allMatch(action -> action.getStatus() == status);
}
@@ -490,9 +477,10 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final List<Target> targets = testdataFactory.createTargets(targetCount, "target" + prefix,
prefix.concat(SPACE_AND_DESCRIPTION));
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("filter" + prefix).query("id==target" + prefix + "*")
.autoAssignDistributionSet(distributionSet).autoAssignActionType(actionType));
targetFilterQueryManagement.create(Create.builder()
.name("filter" + prefix).query("id==target" + prefix + "*")
.autoAssignDistributionSet(distributionSet).autoAssignActionType(actionType)
.build());
return targets;
}

View File

@@ -15,6 +15,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import java.util.Collections;
import java.util.List;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
@@ -145,12 +146,10 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
*/
@Test
void verifyInvalidateDistributionSetStopAll() {
final InvalidationTestData invalidationTestData = createInvalidationTestData(
"verifyInvalidateDistributionSetStopAll");
final InvalidationTestData invalidationTestData = createInvalidationTestData("verifyInvalidateDistributionSetStopAll");
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.SOFT,
true);
Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.SOFT,true);
final DistributionSetInvalidationCount distributionSetInvalidationCount = distributionSetInvalidationManagement
.countEntitiesForInvalidation(distributionSetInvalidation);
assertDistributionSetInvalidationCount(distributionSetInvalidationCount, 1, 5, 1);
@@ -185,10 +184,11 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
/**
* Verify that invalidating an invalidated distribution set don't throws an exception
* -> should be able to cancel actions again (if previous time there was a problem
* -> should be able to cancel actions again (if previous time there was a problem
*/
@Test
@SuppressWarnings("java:S2699") // test that no exception is thrown
@SuppressWarnings("java:S2699")
// test that no exception is thrown
void verifyInvalidateInvalidatedDistributionSetDontThrowsException() {
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
distributionSetInvalidationManagement.invalidateDistributionSet(
@@ -266,13 +266,13 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
}
private InvalidationTestData createInvalidationTestData(final String testName) {
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
DistributionSet distributionSet = testdataFactory.createDistributionSet();
final List<Target> targets = testdataFactory.createTargets(5, testName);
assignDistributionSet(distributionSet, targets);
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery()
.create().name(testName).query("name==*").autoAssignDistributionSet(distributionSet));
final Rollout rollout = testdataFactory.createRolloutByVariables(testName, "desc", 2, "name==*",
distributionSet, "50", "80");
// if implicitly locked - the old distribution set becomes stale
distributionSet = assignDistributionSet(distributionSet, targets).getDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder()
.name(testName).query("name==*").autoAssignDistributionSet(distributionSet).build());
final Rollout rollout = testdataFactory.createRolloutByVariables(testName, "desc", 2, "name==*", distributionSet, "50", "80");
return new InvalidationTestData(distributionSet, targets, targetFilterQuery, rollout);
}

View File

@@ -35,6 +35,7 @@ import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
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.DistributionSetUpdatedEvent;
@@ -994,10 +995,14 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
DistributionSet ds2 = testdataFactory.createDistributionSet("DS2");
testdataFactory.createTargets("targets", 4);
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 1").autoAssignDistributionSet(ds.getId()).query("name==targets*"));
TargetFilterQueryManagement.Create.builder()
.name("test filter 1").autoAssignDistributionSet(ds).query("name==targets*")
.build());
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter 2").autoAssignDistributionSet(ds.getId()).query("name==targets*"));
TargetFilterQueryManagement.Create.builder()
.name("test filter 2").autoAssignDistributionSet(ds).query("name==targets*")
.build());
assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds.getId())).isEqualTo(2);
assertThat(distributionSetManagement.countAutoAssignmentsForDistributionSet(ds2.getId())).isNull();

View File

@@ -12,7 +12,8 @@ package org.eclipse.hawkbit.repository.jpa.management;
import java.util.List;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.junit.jupiter.api.Test;
@@ -28,7 +29,7 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
@Test
void createPermissionsCheck() {
assertPermissions(
() -> targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("name").query("controllerId==id")),
() -> targetFilterQueryManagement.create(Create.builder().name("name").query("controllerId==id").build()),
List.of(SpPermission.CREATE_TARGET));
}
@@ -76,22 +77,6 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
assertPermissions(() -> targetFilterQueryManagement.countByAutoAssignDistributionSetId(1L), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByNamePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.findByName("filterName", PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByNamePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.countByName("filterName"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -100,23 +85,6 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
assertPermissions(() -> targetFilterQueryManagement.findByRsql("name==id", PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByQueryPermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.findByQuery("controllerId==id", PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByAutoAssignDistributionSetIdPermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.findByAutoAssignDistributionSetId(1L, PAGE),
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -142,23 +110,6 @@ class TargetFilterQueryManagementSecurityTest extends AbstractJpaIntegrationTest
assertPermissions(() -> targetFilterQueryManagement.get(1L), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void getTargetFilterQueryByNamePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.getByName("filterName"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void updatePermissionsCheck() {
assertPermissions(() -> targetFilterQueryManagement.update(entityFactory.targetFilterQuery().update(1L)),
List.of(SpPermission.UPDATE_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/

View File

@@ -27,9 +27,9 @@ import org.assertj.core.api.Assertions;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryCreate;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Create;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.Update;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
@@ -67,10 +67,9 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
* Verifies that management get access reacts as specfied on calls for non existing entities by means of Optional not present.
*/
@Test
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
void nonExistingEntityAccessReturnsNotPresent() {
assertThat(targetFilterQueryManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(targetFilterQueryManagement.getByName(NOT_EXIST_ID)).isNotPresent();
}
/**
@@ -84,7 +83,7 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void entityQueriesReferringToNotExistingEntitiesThrowsException() {
final DistributionSet set = testdataFactory.createDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("test filter").query("name==PendingTargets001"));
Create.builder().name("test filter").query("name==PendingTargets001").build());
verifyThrownExceptionBy(() -> targetFilterQueryManagement.delete(NOT_EXIST_IDL), "TargetFilterQuery");
@@ -93,20 +92,20 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
"DistributionSet");
verifyThrownExceptionBy(
() -> targetFilterQueryManagement.update(entityFactory.targetFilterQuery().update(NOT_EXIST_IDL)),
() -> targetFilterQueryManagement.update(Update.builder().id(NOT_EXIST_IDL).build()),
"TargetFilterQuery");
verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)),
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)),
"DistributionSet");
verifyThrownExceptionBy(
() -> targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(NOT_EXIST_IDL).ds(set.getId())),
new AutoAssignDistributionSetUpdate(NOT_EXIST_IDL).ds(set.getId())),
"TargetFilterQuery");
verifyThrownExceptionBy(() -> targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)),
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(NOT_EXIST_IDL)),
"DistributionSet");
}
@@ -117,8 +116,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void createTargetFilterQuery() {
final String filterName = "new target filter";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001"));
assertEquals(targetFilterQuery, targetFilterQueryManagement.getByName(filterName).get(),
.create(Create.builder().name(filterName).query("name==PendingTargets001").build());
assertEquals(targetFilterQuery, targetFilterQueryManagement.get(targetFilterQuery.getId()).get(),
"Retrieved newly created custom target filter");
}
@@ -134,8 +133,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet set = testdataFactory.createDistributionSet();
// creation is supposed to work as there is no distribution set
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create()
.name("testfilter").autoAssignDistributionSet(set.getId()).query("name==target*");
final Create targetFilterQueryCreate = Create.builder()
.name("testfilter").autoAssignDistributionSet(set).query("name==target*").build();
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
}
@@ -147,12 +146,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void searchTargetFilterQuery() {
final String filterName = "targetFilterQueryName";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001"));
.create(Create.builder().name(filterName).query("name==PendingTargets001").build());
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("someOtherFilter").query("name==PendingTargets002"));
targetFilterQueryManagement.create(Create.builder().name("someOtherFilter").query("name==PendingTargets002").build());
final List<TargetFilterQuery> results = targetFilterQueryManagement
final List<? extends TargetFilterQuery> results = targetFilterQueryManagement
.findByRsql("name==" + filterName, PageRequest.of(0, 10)).getContent();
assertEquals(1, results.size(), "Search result should have 1 result");
assertEquals(targetFilterQuery, results.get(0), "Retrieved newly created custom target filter");
@@ -174,8 +172,7 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test
void createDuplicateTargetFilterQuery() {
final String filterName = "new target filter duplicate";
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create()
.name(filterName).query("name==PendingTargets001");
final Create targetFilterQueryCreate = Create.builder().name(filterName).query("name==PendingTargets001").build();
targetFilterQueryManagement.create(targetFilterQueryCreate);
@@ -190,8 +187,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test
void deleteTargetFilterQuery() {
final String filterName = "delete_target_filter_query";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery()
.create().name(filterName).query("name==PendingTargets001"));
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
Create.builder().name(filterName).query("name==PendingTargets001").build());
targetFilterQueryManagement.delete(targetFilterQuery.getId());
assertFalse(
targetFilterQueryManagement.get(targetFilterQuery.getId()).isPresent(),
@@ -205,11 +202,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void updateTargetFilterQuery() {
final String filterName = "target_filter_01";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001"));
.create(Create.builder().name(filterName).query("name==PendingTargets001").build());
final String newQuery = "status==UNKNOWN";
targetFilterQueryManagement.update(entityFactory.targetFilterQuery().update(targetFilterQuery.getId()).query(newQuery));
assertEquals(newQuery, targetFilterQueryManagement.getByName(filterName).get().getQuery(),
final String newQuery = "name==PendingTargets002";
targetFilterQueryManagement.update(Update.builder().id(targetFilterQuery.getId()).query(newQuery).build());
assertEquals(newQuery, targetFilterQueryManagement.get(targetFilterQuery.getId()).get().getQuery(),
"Returns updated target filter query");
}
@@ -220,12 +217,12 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void assignDistributionSet() {
final String filterName = "target_filter_02";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001"));
.create(Create.builder().name(filterName).query("name==PendingTargets001").build());
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
verifyAutoAssignmentWithDefaultActionType(filterName, targetFilterQuery, distributionSet);
verifyAutoAssignmentWithSoftActionType(filterName, targetFilterQuery, distributionSet);
verifyAutoAssignmentWithDownloadOnlyActionType(filterName, targetFilterQuery, distributionSet);
verifyAutoAssignmentWithDefaultActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithSoftActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithDownloadOnlyActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithInvalidActionType(targetFilterQuery, distributionSet);
verifyAutoAssignmentWithIncompleteDs(targetFilterQuery);
verifyAutoAssignmentWithSoftDeletedDs(targetFilterQuery);
@@ -243,12 +240,12 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
// creation is supposed to work as there is no distribution set
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("testfilter").query("name==target*"));
.create(Create.builder().name("testfilter").query("name==target*").build());
// assigning a distribution set is supposed to fail as the query
// addresses too many targets
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId());
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
}
@@ -264,12 +261,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet set = testdataFactory.createDistributionSet();
// creation is supposed to work as the query does not exceed the quota
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(entityFactory.targetFilterQuery()
.create().name("testfilter").autoAssignDistributionSet(set.getId()).query("name==foo"));
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
Create.builder().name("testfilter").autoAssignDistributionSet(set).query("name==foo").build());
// update with a query string that addresses too many targets
final TargetFilterQueryUpdate targetFilterQueryUpdate = entityFactory.targetFilterQuery().update(targetFilterQuery.getId())
.query("name==target*");
final Update targetFilterQueryUpdate = Update.builder().id(targetFilterQuery.getId()).query("name==target*").build();
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> targetFilterQueryManagement.update(targetFilterQueryUpdate));
}
@@ -281,23 +277,23 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void removeAssignDistributionSet() {
final String filterName = "target_filter_03";
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001"));
.create(Create.builder().name(filterName).query("name==PendingTargets001").build());
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()));
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
implicitLock(distributionSet);
// Check if target filter query is there
TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get();
TargetFilterQuery tfq = targetFilterQueryManagement.get(targetFilterQuery.getId()).get();
assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set");
assertEquals(ActionType.FORCED, tfq.getAutoAssignActionType(), "Return correct action type");
distributionSetManagement.delete(distributionSet.getId());
// Check if auto assign distribution set is null
tfq = targetFilterQueryManagement.getByName(filterName).get();
tfq = targetFilterQueryManagement.get(targetFilterQuery.getId()).get();
assertNotNull(tfq, "Returns target filter query");
assertNull(tfq.getAutoAssignDistributionSet(), "Returns distribution set as null");
assertNull(tfq.getAutoAssignActionType(), "Returns action type as null");
@@ -316,14 +312,14 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
assignDistributionSet(distributionSet.getId(), target.getControllerId());
final Long filterId = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName).query("name==PendingTargets001"))
.create(Create.builder().name(filterName).query("name==PendingTargets001").build())
.getId();
targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(distributionSet.getId()));
new AutoAssignDistributionSetUpdate(filterId).ds(distributionSet.getId()));
implicitLock(distributionSet);
// Check if target filter query is there with the distribution set
TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get();
TargetFilterQuery tfq = targetFilterQueryManagement.get(filterId).get();
assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set");
assertEquals(ActionType.FORCED, tfq.getAutoAssignActionType(), "Return correct action type");
@@ -333,7 +329,7 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
assertTrue(distributionSetManagement.get(distributionSet.getId()).get().isDeleted(), "Distribution set should be deleted");
// Check if auto assign distribution set is null
tfq = targetFilterQueryManagement.getByName(filterName).get();
tfq = targetFilterQueryManagement.get(filterId).get();
assertNotNull(tfq, "Returns target filter query");
assertNull(tfq.getAutoAssignDistributionSet(), "Returns distribution set as null");
assertNull(tfq.getAutoAssignActionType(), "Returns action type as null");
@@ -346,24 +342,23 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void findFiltersWithDistributionSet() {
final String filterName = "d";
assertEquals(0L, targetFilterQueryManagement.count());
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*"));
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("b").query("name==*"));
targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build());
targetFilterQueryManagement.create(Create.builder().name("b").query("name==*").build());
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final DistributionSet distributionSet2 = testdataFactory.createDistributionSet("2");
final TargetFilterQuery tfq = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create()
.name("c").query("name==x").autoAssignDistributionSet(distributionSet).autoAssignActionType(ActionType.SOFT));
Create.builder()
.name("c").query("name==x").autoAssignDistributionSet(distributionSet).autoAssignActionType(ActionType.SOFT)
.build());
final TargetFilterQuery tfq2 = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create()
.name(filterName).query("name==z*").autoAssignDistributionSet(distributionSet2));
Create.builder().name(filterName).query("name==z*").autoAssignDistributionSet(distributionSet2).build());
assertEquals(4L, targetFilterQueryManagement.count());
// check if find works
verifyFindByDistributionSetAndRsql(distributionSet, null, tfq);
targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(tfq2.getId()).ds(distributionSet.getId()));
targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(tfq2.getId()).ds(distributionSet.getId()));
// check if find works for two
verifyFindByDistributionSetAndRsql(distributionSet, null, tfq, tfq2);
@@ -379,15 +374,13 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void weightNotRequiredInMultiAssignmentMode() {
enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*")).getId();
final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build()).getId();
assertThat(
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("b").query("name==*").autoAssignDistributionSet(ds)))
targetFilterQueryManagement.create(Create.builder().name("b").query("name==*").autoAssignDistributionSet(ds).build()))
.isNotNull();
assertThat(
targetFilterQueryManagement
.updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId())))
targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId())))
.isNotNull();
}
@@ -397,16 +390,15 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test
void weightAllowedWhenMultiAssignmentModeNotEnabled() {
final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a").query("name==*")).getId();
final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build()).getId();
assertThat(
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create()
.name("b").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(342)))
Create.builder().name("b").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(342).build()))
.isNotNull();
assertThat(
targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(343)))
new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(343)))
.isNotNull();
}
@@ -418,10 +410,9 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(23)).getId();
Create.builder().name("a").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(23).build()).getId();
assertThat(targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(null).weight(null)))
new AutoAssignDistributionSetUpdate(filterId).ds(null).weight(null)))
.isNotNull();
}
@@ -433,27 +424,27 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet();
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX + 1);
final Create targetFilterQueryCreate = Create.builder().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX + 1).build();
Assertions.assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(
() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
final Long filterId = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX)).getId();
final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a")
.query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(Action.WEIGHT_MAX).build()).getId();
assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight()).contains(Action.WEIGHT_MAX);
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery().updateAutoAssign(filterId)
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(filterId)
.ds(ds.getId()).weight(Action.WEIGHT_MAX + 1);
Assertions.assertThatExceptionOfType(ConstraintViolationException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate2 = entityFactory.targetFilterQuery()
.updateAutoAssign(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN - 1);
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate2 =
new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN - 1);
Assertions.assertThatExceptionOfType(ConstraintViolationException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate2));
targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(Action.WEIGHT_MAX));
new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(Action.WEIGHT_MAX));
targetFilterQueryManagement.updateAutoAssignDS(
entityFactory.targetFilterQuery().updateAutoAssign(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN));
new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId()).weight(Action.WEIGHT_MIN));
assertThat(targetFilterQueryManagement.get(filterId).get().getAutoAssignWeight()).contains(Action.WEIGHT_MIN);
}
@@ -464,8 +455,9 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void createTargetFilterWithInvalidDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createAndInvalidateDistributionSet();
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create()
.name("createTargetFilterWithInvalidDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet);
final Create targetFilterQueryCreate = Create.builder()
.name("createTargetFilterWithInvalidDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet)
.build();
assertThatExceptionOfType(InvalidDistributionSetException.class)
.as("Invalid distributionSet should throw an exception")
.isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
@@ -478,9 +470,10 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void createTargetFilterWithIncompleteDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createIncompleteDistributionSet();
final TargetFilterQueryCreate targetFilterQueryCreate = entityFactory.targetFilterQuery().create()
final Create targetFilterQueryCreate = Create.builder()
.name("createTargetFilterWithIncompleteDistributionSet").query("name==*")
.autoAssignDistributionSet(distributionSet);
.autoAssignDistributionSet(distributionSet)
.build();
assertThatExceptionOfType(IncompleteDistributionSetException.class)
.as("Incomplete distributionSet should throw an exception")
.isThrownBy(() -> targetFilterQueryManagement.create(targetFilterQueryCreate));
@@ -492,9 +485,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
@Test
void updateAutoAssignDsWithInvalidDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("updateAutoAssignDsWithInvalidDistributionSet")
.query("name==*").autoAssignDistributionSet(distributionSet));
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(Create.builder()
.name("updateAutoAssignDsWithInvalidDistributionSet").query("name==*").autoAssignDistributionSet(distributionSet).build());
final DistributionSet invalidDistributionSet = testdataFactory.createAndInvalidateDistributionSet();
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
@@ -511,8 +503,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
void updateAutoAssignDsWithIncompleteDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement.create(
entityFactory.targetFilterQuery().create().name("updateAutoAssignDsWithIncompleteDistributionSet")
.query("name==*").autoAssignDistributionSet(distributionSet));
Create.builder().name("updateAutoAssignDsWithIncompleteDistributionSet")
.query("name==*").autoAssignDistributionSet(distributionSet).build());
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
@@ -530,11 +522,11 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
for (final ActionType actionType : ActionType.values()) {
final Supplier<Long> create = () ->
targetFilterQueryManagement.create(
entityFactory.targetFilterQuery()
.create()
Create.builder()
.name("testAutoAssignActionTypeConvert_" + actionType)
.query("name==*")
.autoAssignActionType(actionType))
.autoAssignActionType(actionType)
.build())
.getId();
if (actionType == ActionType.TIMEFORCED) {
assertThatExceptionOfType(AbstractServerRtException.class).isThrownBy(create::get);
@@ -544,45 +536,36 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
}
final JpaTargetFilterQuery jpaTargetFilterQuery = (JpaTargetFilterQuery) targetFilterQueryManagement.create(
entityFactory.targetFilterQuery()
.create()
.name("testAutoAssignActionTypeConvert")
.query("name==*"));
Create.builder().name("testAutoAssignActionTypeConvert").query("name==*").build());
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() ->
jpaTargetFilterQuery.setAutoAssignActionType(ActionType.TIMEFORCED));
}
private void verifyAutoAssignmentWithDefaultActionType(final String filterName,
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()));
private void verifyAutoAssignmentWithDefaultActionType(final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
implicitLock(distributionSet);
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.FORCED);
verifyAutoAssignDsAndActionType(targetFilterQuery.getId(), distributionSet, ActionType.FORCED);
}
private void verifyAutoAssignmentWithSoftActionType(final String filterName,
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.SOFT));
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.SOFT);
private void verifyAutoAssignmentWithSoftActionType(final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.SOFT));
verifyAutoAssignDsAndActionType(targetFilterQuery.getId(), distributionSet, ActionType.SOFT);
}
private void verifyAutoAssignmentWithDownloadOnlyActionType(final String filterName,
final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
private void verifyAutoAssignmentWithDownloadOnlyActionType(final TargetFilterQuery targetFilterQuery, final DistributionSet distributionSet) {
targetFilterQueryManagement
.updateAutoAssignDS(entityFactory.targetFilterQuery().updateAutoAssign(targetFilterQuery.getId())
.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(targetFilterQuery.getId())
.ds(distributionSet.getId()).actionType(ActionType.DOWNLOAD_ONLY));
verifyAutoAssignDsAndActionType(filterName, distributionSet, ActionType.DOWNLOAD_ONLY);
verifyAutoAssignDsAndActionType(targetFilterQuery.getId(), distributionSet, ActionType.DOWNLOAD_ONLY);
}
private void verifyAutoAssignmentWithInvalidActionType(final TargetFilterQuery targetFilterQuery,
final DistributionSet distributionSet) {
// assigning a distribution set with TIMEFORCED action is supposed to
// fail as only FORCED and SOFT action types are allowed
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId())
.ds(distributionSet.getId())
.actionType(ActionType.TIMEFORCED);
// assigning a distribution set with TIMEFORCED action is supposed to fail as only FORCED and SOFT action types are allowed
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()).actionType(ActionType.TIMEFORCED);
assertThatExceptionOfType(InvalidAutoAssignActionTypeException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
}
@@ -594,8 +577,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
.name("incomplete").version("1")
.build());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(incompleteDistributionSet.getId());
assertThatExceptionOfType(IncompleteDistributionSetException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
}
@@ -605,14 +588,14 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
assignDistributionSet(softDeletedDs, testdataFactory.createTarget("forSoftDeletedDs"));
distributionSetManagement.delete(softDeletedDs.getId());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate = entityFactory.targetFilterQuery()
.updateAutoAssign(targetFilterQuery.getId()).ds(softDeletedDs.getId());
final AutoAssignDistributionSetUpdate autoAssignDistributionSetUpdate =
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(softDeletedDs.getId());
assertThatExceptionOfType(DeletedException.class)
.isThrownBy(() -> targetFilterQueryManagement.updateAutoAssignDS(autoAssignDistributionSetUpdate));
}
private void verifyFindByDistributionSetAndRsql(final DistributionSet distributionSet, final String rsql,
final TargetFilterQuery... expectedFilterQueries) {
private void verifyFindByDistributionSetAndRsql(
final DistributionSet distributionSet, final String rsql, final TargetFilterQuery... expectedFilterQueries) {
final Page<TargetFilterQuery> tfqList = targetFilterQueryManagement
.findByAutoAssignDSAndRsql(distributionSet.getId(), rsql, PageRequest.of(0, 500));
@@ -642,9 +625,8 @@ class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest {
Arrays.stream(expectedFilterQueries).map(TargetFilterQuery::getId).toArray(Long[]::new));
}
private void verifyAutoAssignDsAndActionType(final String filterName, final DistributionSet distributionSet,
final ActionType actionType) {
final TargetFilterQuery tfq = targetFilterQueryManagement.getByName(filterName).get();
private void verifyAutoAssignDsAndActionType(final Long filterId, final DistributionSet distributionSet, final ActionType actionType) {
final TargetFilterQuery tfq = targetFilterQueryManagement.get(filterId).get();
assertEquals(distributionSet, tfq.getAutoAssignDistributionSet(), "Returns correct distribution set");
assertEquals(actionType, tfq.getAutoAssignActionType(), "Return correct action type");

View File

@@ -19,6 +19,7 @@ import java.util.Set;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.Action.Status;
@@ -215,7 +216,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
void findTargetWithoutAssignedDistributionSet() {
final DistributionSet assignedSet = testdataFactory.createDistributionSet("");
final TargetFilterQuery tfq = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("tfq").query("name==*"));
.create(TargetFilterQueryManagement.Create.builder().name("tfq").query("name==*").build());
final List<Target> unassignedTargets = testdataFactory.createTargets(12, "unassigned", "unassigned");
final List<Target> assignedTargets = testdataFactory.createTargets(10, "assigned", "assigned");
@@ -260,7 +261,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final DistributionSet testDs = testdataFactory.createDistributionSet();
final TargetType targetType = testdataFactory.createTargetType("testType", Set.of(testDs.getType()));
final TargetFilterQuery tfq = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test-filter").query("name==*"));
.create(TargetFilterQueryManagement.Create.builder().name("test-filter").query("name==*").build());
final List<Target> targets = testdataFactory.createTargets(20, "withOutType");
final List<Target> targetWithCompatibleTypes = testdataFactory.createTargetsWithType(20, "compatible",
targetType);
@@ -284,7 +285,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final TargetType incompatibleTargetType = testdataFactory.createTargetType(
"incompTestType", Set.of(testdataFactory.createDistributionSet().getType()));
final TargetFilterQuery tfq = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test-filter").query("name==*"));
.create(TargetFilterQueryManagement.Create.builder().name("test-filter").query("name==*").build());
final List<Target> targetsWithOutType = testdataFactory.createTargets(20, "withOutType");
final List<Target> targetsWithCompatibleType = testdataFactory.createTargetsWithType(20, "compatible",

View File

@@ -13,6 +13,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.eclipse.hawkbit.repository.TargetFilterQueryFields;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -41,12 +42,11 @@ class RsqlTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest {
final DistributionSet ds1 = testdataFactory.createDistributionSet("AutoAssignedDs_1");
final DistributionSet ds2 = testdataFactory.createDistributionSet("AutoAssignedDs_2");
filter1 = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(filterName1)
.query("name==*").autoAssignDistributionSet(ds1).autoAssignActionType(ActionType.SOFT));
filter2 = targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(filterName2)
.query("name==*").autoAssignDistributionSet(ds2));
targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name(filterName3).query("name==*"));
filter1 = targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder().name(filterName1)
.query("name==*").autoAssignDistributionSet(ds1).autoAssignActionType(ActionType.SOFT).build());
filter2 = targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder().name(filterName2)
.query("name==*").autoAssignDistributionSet(ds2).build());
targetFilterQueryManagement.create(TargetFilterQueryManagement.Create.builder().name(filterName3).query("name==*").build());
assertEquals(3L, targetFilterQueryManagement.count());
}
@@ -68,7 +68,6 @@ class RsqlTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest {
assertRSQLQuery(TargetFilterQueryFields.ID.name() + "=in=(" + filter1.getId() + ",10000000)", 1);
assertRSQLQuery(TargetFilterQueryFields.ID.name() + "=out=(" + filter1.getId() + ",10000000)", 2);
}
/**
@@ -117,7 +116,7 @@ class RsqlTargetFilterQueryFieldsTest extends AbstractJpaIntegrationTest {
}
private void assertRSQLQuery(final String rsql, final long expectedFilterQueriesSize) {
final Page<TargetFilterQuery> findTargetFilterQueryPage = targetFilterQueryManagement.findByRsql(rsql, PAGE);
final Page<? extends TargetFilterQuery> findTargetFilterQueryPage = targetFilterQueryManagement.findByRsql(rsql, PAGE);
assertThat(findTargetFilterQueryPage).isNotNull();
assertThat(findTargetFilterQueryPage.getTotalElements()).isEqualTo(expectedFilterQueriesSize);
}