Introduce basic functionality for invalidation of distributionsets (#1179)
* Basic DS invalidation functionality Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add checks for valid/complete DS Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Stop rollouts + auto assignments when invalidating a DS Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add methods to count AAs + rollouts for invalidation Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Small refactoring for DS management Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add invalidation functionality to REST API Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix update stopped rollouts status Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add various tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Introduce countActionsForInvalidation Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix event tests with incomplete DS Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add H2 migration script Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix action count method Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix REST documentation tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Change flyway version number Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add lock for DS invalidation + adapt tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Move concurrency test to own class Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Handle possible InterruptedException Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix concurrency test Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Use one transaction for all invalidations Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add invalidate endpoint to REST docu Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Execute invalidation in transaction when actions are cancelled Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Check that distribution set is valid when editing/creating metadata Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Remove all changes in UI Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Add DB migration files for all databases Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Implement review findings Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Move DS invalidation to own class to check permissions for single steps Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Move invalidation count methods to management classes Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com> * Fix failing tests Signed-off-by: Sebastian Firsching <sebastian.firsching@bosch-si.com>
This commit is contained in:
committed by
GitHub
parent
b25e118e6c
commit
825cb64448
@@ -64,6 +64,28 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
*/
|
||||
Page<Action> findByDistributionSetId(Pageable pageable, Long dsId);
|
||||
|
||||
/**
|
||||
* Retrieves all active {@link Action}s which are referring the given
|
||||
* {@link DistributionSet}.
|
||||
*
|
||||
* @param set
|
||||
* the {@link DistributionSet} on which will be filtered
|
||||
* @return the found {@link Action}s
|
||||
*/
|
||||
List<Action> findByDistributionSetAndActiveIsTrue(DistributionSet set);
|
||||
|
||||
/**
|
||||
* Retrieves all active {@link Action}s which are referring the given
|
||||
* {@link DistributionSet} and are not in the given state
|
||||
*
|
||||
* @param set
|
||||
* the {@link DistributionSet} on which will be filtered
|
||||
* @param status
|
||||
* the state the actions should not have
|
||||
* @return the found {@link Action}s
|
||||
*/
|
||||
List<Action> findByDistributionSetAndActiveIsTrueAndStatusIsNot(DistributionSet set, Status status);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Action}s which are referring the given
|
||||
* {@link Target}.
|
||||
@@ -103,7 +125,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
* Retrieves the active {@link Action}s with the highest weights that refer
|
||||
* to the given {@link Target}. If {@link Action}s have the same weight they
|
||||
* are ordered ascending by ID (oldest ones first).
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* pageable
|
||||
* @param controllerId
|
||||
@@ -117,7 +139,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Retrieves the active {@link Action}s with the lowest IDs (the oldest one)
|
||||
* whose weight is null and that that refers to the given {@link Target}.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* pageable
|
||||
* @param controllerId
|
||||
@@ -131,7 +153,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Checks if an active action exists for given
|
||||
* {@link Target#getControllerId()}.
|
||||
*
|
||||
*
|
||||
* @param controllerId
|
||||
* of target to check
|
||||
* @return <code>true</code> if an active action for the target exists.
|
||||
@@ -264,10 +286,9 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
List<Action> findByExternalRefInAndActive(@Param("externalRefs") List<String> externalRefs,
|
||||
@Param("active") boolean active);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves an {@link Action} that matches the queried externalRef.
|
||||
*
|
||||
*
|
||||
* @param externalRef
|
||||
* of the action. See {@link Action#getExternalRef()}
|
||||
* @return the found {@link Action}
|
||||
@@ -351,6 +372,27 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
*/
|
||||
Long countByDistributionSetId(Long distributionSet);
|
||||
|
||||
/**
|
||||
* Counts all active {@link Action}s referring to the given DistributionSet.
|
||||
*
|
||||
* @param distributionSet
|
||||
* DistributionSet to count the {@link Action}s from
|
||||
* @return the count of actions referring to the given distributionSet
|
||||
*/
|
||||
Long countByDistributionSetIdAndActiveIsTrue(Long distributionSet);
|
||||
|
||||
/**
|
||||
* Counts all active {@link Action}s referring to the given DistributionSet
|
||||
* that are not in a given state.
|
||||
*
|
||||
* @param distributionSet
|
||||
* DistributionSet to count the {@link Action}s from
|
||||
* @param status
|
||||
* the state the actions should not have
|
||||
* @return the count of actions referring to the given distributionSet
|
||||
*/
|
||||
Long countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(Long distributionSet, Status status);
|
||||
|
||||
/**
|
||||
* Counts all actions referring to a given rollout and rolloutgroup which
|
||||
* are currently not in the given status. An in-clause statement does not
|
||||
@@ -396,7 +438,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
|
||||
/**
|
||||
* Counts all actions referring to a given rollout and status.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the actions belong to
|
||||
* @param status
|
||||
@@ -409,7 +451,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Returns {@code true} if actions for the given rollout exists, otherwise
|
||||
* {@code false}
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the actions belong to
|
||||
* @return {@code true} if actions for the given rollout exists, otherwise
|
||||
@@ -421,7 +463,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
/**
|
||||
* Returns {@code true} if actions for the given rollout exists, otherwise
|
||||
* {@code false}
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the actions belong to
|
||||
* @param status
|
||||
@@ -471,7 +513,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
|
||||
/**
|
||||
* Retrieves all actions for a specific rollout and in a specific status.
|
||||
*
|
||||
*
|
||||
* @param pageable
|
||||
* page parameters
|
||||
* @param rolloutId
|
||||
@@ -528,7 +570,7 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
|
||||
/**
|
||||
* Deletes all actions with the given IDs.
|
||||
*
|
||||
*
|
||||
* @param actionIDs
|
||||
* the IDs of the actions to be deleted.
|
||||
*/
|
||||
|
||||
@@ -35,6 +35,7 @@ import javax.persistence.criteria.Root;
|
||||
|
||||
import org.eclipse.hawkbit.repository.ActionFields;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
@@ -43,7 +44,6 @@ import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEv
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
@@ -67,6 +67,7 @@ import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DeploymentRequest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
@@ -130,6 +131,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
private final EntityManager entityManager;
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final DistributionSetRepository distributionSetRepository;
|
||||
private final TargetRepository targetRepository;
|
||||
private final ActionStatusRepository actionStatusRepository;
|
||||
@@ -146,6 +148,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
private final RetryTemplate retryTemplate;
|
||||
|
||||
protected JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
|
||||
final DistributionSetManagement distributionSetManagement,
|
||||
final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository,
|
||||
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
|
||||
final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit,
|
||||
@@ -156,6 +159,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
super(actionRepository, repositoryProperties);
|
||||
this.entityManager = entityManager;
|
||||
this.distributionSetRepository = distributionSetRepository;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.targetRepository = targetRepository;
|
||||
this.actionStatusRepository = actionStatusRepository;
|
||||
this.auditorProvider = auditorProvider;
|
||||
@@ -254,8 +258,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
/**
|
||||
* method assigns the {@link DistributionSet} to all {@link Target}s by
|
||||
* their IDs with a specific {@link ActionType} and {@code forcetime}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* In case the update was executed offline (i.e. not managed by hawkBit) the
|
||||
* handling differs my means that:<br/>
|
||||
* A. it ignores targets completely that are in
|
||||
@@ -285,7 +289,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
|
||||
final AbstractDsAssignmentStrategy assignmentStrategy) {
|
||||
|
||||
final JpaDistributionSet distributionSetEntity = getAndValidateDsById(dsID);
|
||||
final JpaDistributionSet distributionSetEntity = (JpaDistributionSet) distributionSetManagement
|
||||
.getValidAndComplete(dsID);
|
||||
final List<String> providedTargetIds = targetsWithActionType.stream().map(TargetWithActionType::getControllerId)
|
||||
.distinct().collect(Collectors.toList());
|
||||
|
||||
@@ -363,18 +368,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
return new DistributionSetAssignmentResult(distributionSet, alreadyAssignedTargetsCount, assignedActions);
|
||||
}
|
||||
|
||||
private JpaDistributionSet getAndValidateDsById(final Long dsID) {
|
||||
final JpaDistributionSet distributionSet = distributionSetRepository.findById(dsID)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, dsID));
|
||||
|
||||
if (!distributionSet.isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Distribution set of type "
|
||||
+ distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId());
|
||||
}
|
||||
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
private void checkQuotaForAssignment(final Collection<DeploymentRequest> deploymentRequests) {
|
||||
if (!deploymentRequests.isEmpty()) {
|
||||
enforceMaxAssignmentsPerRequest(deploymentRequests.size());
|
||||
@@ -656,8 +649,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
private Specification<JpaAction> createSpecificationFor(final String controllerId, final String rsqlParam) {
|
||||
final Specification<JpaAction> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class, virtualPropertyReplacer,
|
||||
database);
|
||||
final Specification<JpaAction> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, ActionFields.class,
|
||||
virtualPropertyReplacer, database);
|
||||
return (root, query, cb) -> cb.and(spec.toPredicate(root, query, cb),
|
||||
cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId));
|
||||
}
|
||||
@@ -779,6 +772,17 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
return actionRepository.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countActionsByDistributionSetIdAndActiveIsTrue(final Long distributionSet) {
|
||||
return actionRepository.countByDistributionSetIdAndActiveIsTrue(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countActionsByDistributionSetIdAndActiveIsTrueAndStatusIsNot(final Long distributionSet,
|
||||
final Status status) {
|
||||
return actionRepository.countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(distributionSet, status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Action> findActionsByDistributionSet(final Pageable pageable, final long dsId) {
|
||||
throwExceptionIfDistributionSetDoesNotExist(dsId);
|
||||
@@ -832,7 +836,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPendingCancellations(String controllerId) {
|
||||
public boolean hasPendingCancellations(final String controllerId) {
|
||||
return actionRepository.existsByTargetControllerIdAndStatusAndActiveIsTrue(controllerId,
|
||||
Action.Status.CANCELING);
|
||||
}
|
||||
@@ -881,4 +885,21 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelActionsForDistributionSet(final CancelationType cancelationType, final DistributionSet set) {
|
||||
actionRepository.findByDistributionSetAndActiveIsTrueAndStatusIsNot(set, Status.CANCELING).forEach(action -> {
|
||||
final JpaAction jpaAction = (JpaAction) action;
|
||||
cancelAction(jpaAction.getId());
|
||||
LOG.debug("Action {} canceled", jpaAction.getId());
|
||||
});
|
||||
if (cancelationType == CancelationType.FORCE) {
|
||||
actionRepository.findByDistributionSetAndActiveIsTrue(set).forEach(action -> {
|
||||
final JpaAction jpaAction = (JpaAction) action;
|
||||
forceQuitAction(jpaAction.getId());
|
||||
LOG.debug("Action {} force canceled", jpaAction.getId());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* Copyright (c) 2021 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.StopRolloutException;
|
||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
/**
|
||||
* Jpa implementation for {@link DistributionSetInvalidationManagement}
|
||||
*
|
||||
*/
|
||||
public class JpaDistributionSetInvalidationManagement implements DistributionSetInvalidationManagement {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JpaDistributionSetInvalidationManagement.class);
|
||||
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final RolloutManagement rolloutManagement;
|
||||
private final DeploymentManagement deploymentManagement;
|
||||
private final TargetFilterQueryManagement targetFilterQueryManagement;
|
||||
private final PlatformTransactionManager txManager;
|
||||
private final RepositoryProperties repositoryProperties;
|
||||
private final TenantAware tenantAware;
|
||||
private final LockRegistry lockRegistry;
|
||||
|
||||
protected JpaDistributionSetInvalidationManagement(final DistributionSetManagement distributionSetManagement,
|
||||
final RolloutManagement rolloutManagement, final DeploymentManagement deploymentManagement,
|
||||
final TargetFilterQueryManagement targetFilterQueryManagement, final PlatformTransactionManager txManager,
|
||||
final RepositoryProperties repositoryProperties, final TenantAware tenantAware,
|
||||
final LockRegistry lockRegistry) {
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.rolloutManagement = rolloutManagement;
|
||||
this.deploymentManagement = deploymentManagement;
|
||||
this.targetFilterQueryManagement = targetFilterQueryManagement;
|
||||
this.txManager = txManager;
|
||||
this.repositoryProperties = repositoryProperties;
|
||||
this.tenantAware = tenantAware;
|
||||
this.lockRegistry = lockRegistry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation) {
|
||||
LOG.debug("Invalidate distribution sets {}", distributionSetInvalidation.getDistributionSetIds());
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
|
||||
if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
|
||||
distributionSetInvalidation.isCancelRollouts())) {
|
||||
final String handlerId = JpaRolloutManagement.createRolloutLockKey(tenant);
|
||||
final Lock lock = lockRegistry.obtain(handlerId);
|
||||
try {
|
||||
if (!lock.tryLock(repositoryProperties.getDsInvalidationLockTimeout(), TimeUnit.SECONDS)) {
|
||||
throw new StopRolloutException("Timeout while trying to invalidate distribution sets");
|
||||
}
|
||||
try {
|
||||
invalidateDistributionSetsInTransaction(distributionSetInvalidation, tenant);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
} catch (final InterruptedException e) {
|
||||
LOG.error("InterruptedException while invalidating distribution sets {}!",
|
||||
distributionSetInvalidation.getDistributionSetIds(), e);
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
} else {
|
||||
// no lock is needed as no rollout will be stopped
|
||||
invalidateDistributionSetsInTransaction(distributionSetInvalidation, 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()));
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
private void invalidateDistributionSet(final long setId, final CancelationType cancelationType,
|
||||
final boolean cancelRollouts) {
|
||||
final DistributionSet set = distributionSetManagement.getValidAndComplete(setId);
|
||||
distributionSetManagement.invalidate(set);
|
||||
LOG.debug("Distribution set {} set to invalid", setId);
|
||||
|
||||
if (shouldRolloutsBeCanceled(cancelationType, cancelRollouts)) {
|
||||
rolloutManagement.cancelRolloutsForDistributionSet(set);
|
||||
}
|
||||
|
||||
if (cancelationType != CancelationType.NONE) {
|
||||
deploymentManagement.cancelActionsForDistributionSet(cancelationType, set);
|
||||
}
|
||||
|
||||
targetFilterQueryManagement.cancelAutoAssignmentForDistributionSet(setId);
|
||||
}
|
||||
|
||||
private static boolean shouldRolloutsBeCanceled(final CancelationType cancelationType,
|
||||
final boolean cancelRollouts) {
|
||||
return cancelationType != CancelationType.NONE || cancelRollouts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSetInvalidationCount countEntitiesForInvalidation(
|
||||
final DistributionSetInvalidation distributionSetInvalidation) {
|
||||
final Collection<Long> setIds = distributionSetInvalidation.getDistributionSetIds();
|
||||
final long rolloutsCount = shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
|
||||
distributionSetInvalidation.isCancelRollouts()) ? countRolloutsForInvalidation(setIds) : 0;
|
||||
final long autoAssignmentsCount = countAutoAssignmentsForInvalidation(setIds);
|
||||
final long actionsCount = countActionsForInvalidation(setIds, distributionSetInvalidation.getCancelationType());
|
||||
|
||||
return new DistributionSetInvalidationCount(rolloutsCount, autoAssignmentsCount, actionsCount);
|
||||
}
|
||||
|
||||
private long countRolloutsForInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(rolloutManagement::countByDistributionSetIdAndRolloutIsStoppable).sum();
|
||||
}
|
||||
|
||||
private long countAutoAssignmentsForInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(targetFilterQueryManagement::countByAutoAssignDistributionSetId).sum();
|
||||
}
|
||||
|
||||
private long countActionsForInvalidation(final Collection<Long> setIds, final CancelationType cancelationType) {
|
||||
long affectedActionsByDSInvalidation = 0;
|
||||
if (cancelationType == CancelationType.FORCE) {
|
||||
affectedActionsByDSInvalidation = countActionsForForcedInvalidation(setIds);
|
||||
} else if (cancelationType == CancelationType.SOFT) {
|
||||
affectedActionsByDSInvalidation = countActionsForSoftInvalidation(setIds);
|
||||
}
|
||||
return affectedActionsByDSInvalidation;
|
||||
}
|
||||
|
||||
private long countActionsForForcedInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(deploymentManagement::countActionsByDistributionSetIdAndActiveIsTrue).sum();
|
||||
}
|
||||
|
||||
private long countActionsForSoftInvalidation(final Collection<Long> setIds) {
|
||||
return setIds.stream().mapToLong(distributionSet -> deploymentManagement
|
||||
.countActionsByDistributionSetIdAndActiveIsTrueAndStatusIsNot(distributionSet, Status.CANCELING)).sum();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,6 +32,8 @@ import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
@@ -213,7 +215,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
public DistributionSet update(final DistributionSetUpdate u) {
|
||||
final GenericDistributionSetUpdate update = (GenericDistributionSetUpdate) u;
|
||||
|
||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(update.getId());
|
||||
final JpaDistributionSet set = (JpaDistributionSet) getValid(update.getId());
|
||||
|
||||
update.getName().ifPresent(set::setName);
|
||||
update.getDescription().ifPresent(set::setDescription);
|
||||
@@ -228,11 +230,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return distributionSetRepository.save(set);
|
||||
}
|
||||
|
||||
private JpaDistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return (JpaDistributionSet) get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
|
||||
private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long moduleId) {
|
||||
return softwareModuleRepository.findById(moduleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, moduleId));
|
||||
@@ -315,7 +312,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
assertDistributionSetIsNotAssignedToTargets(setId);
|
||||
|
||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||
final JpaDistributionSet set = (JpaDistributionSet) getValid(setId);
|
||||
|
||||
assertSoftwareModuleQuota(setId, modules.size());
|
||||
|
||||
@@ -329,7 +326,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Retryable(include = {
|
||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public DistributionSet unassignSoftwareModule(final long setId, final long moduleId) {
|
||||
final JpaDistributionSet set = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||
final JpaDistributionSet set = (JpaDistributionSet) getValid(setId);
|
||||
final JpaSoftwareModule module = findSoftwareModuleAndThrowExceptionIfNotFound(moduleId);
|
||||
|
||||
assertDistributionSetIsNotAssignedToTargets(setId);
|
||||
@@ -531,7 +528,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
* of the DS to touch
|
||||
*/
|
||||
private JpaDistributionSet touch(final Long distId) {
|
||||
return touch(get(distId).orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, distId)));
|
||||
return touch(getValid(distId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -595,7 +592,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
private static List<Specification<JpaDistributionSet>> buildDistributionSetSpecifications(
|
||||
final DistributionSetFilter distributionSetFilter) {
|
||||
final List<Specification<JpaDistributionSet>> specList = Lists.newArrayListWithExpectedSize(8);
|
||||
final List<Specification<JpaDistributionSet>> specList = Lists.newArrayListWithExpectedSize(9);
|
||||
|
||||
Specification<JpaDistributionSet> spec;
|
||||
|
||||
@@ -609,6 +606,11 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
specList.add(spec);
|
||||
}
|
||||
|
||||
if (distributionSetFilter.getIsValid() != null) {
|
||||
spec = DistributionSetSpecification.isValid(distributionSetFilter.getIsValid());
|
||||
specList.add(spec);
|
||||
}
|
||||
|
||||
if (distributionSetFilter.getType() != null) {
|
||||
spec = DistributionSetSpecification.byType(distributionSetFilter.getType());
|
||||
specList.add(spec);
|
||||
@@ -781,8 +783,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
public Page<DistributionSet> findByRsqlAndTag(final Pageable pageable, final String rsqlParam, final long tagId) {
|
||||
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
|
||||
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class,
|
||||
virtualPropertyReplacer, database);
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
|
||||
DistributionSetFields.class, virtualPropertyReplacer, database);
|
||||
|
||||
return convertDsPage(findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.hasTag(tagId),
|
||||
DistributionSetSpecification.isDeleted(false))), pageable);
|
||||
@@ -797,8 +799,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
@Override
|
||||
public Page<DistributionSet> findByRsql(final Pageable pageable, final String rsqlParam) {
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetFields.class,
|
||||
virtualPropertyReplacer, database);
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.buildRsqlSpecification(rsqlParam,
|
||||
DistributionSetFields.class, virtualPropertyReplacer, database);
|
||||
|
||||
return convertDsPage(
|
||||
findByCriteriaAPI(pageable, Arrays.asList(spec, DistributionSetSpecification.isDeleted(false))),
|
||||
@@ -815,4 +817,41 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return distributionSetRepository.existsById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSet getOrElseThrowException(final long id) {
|
||||
return get(id).orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSet getValidAndComplete(final long id) {
|
||||
final DistributionSet distributionSet = getValid(id);
|
||||
|
||||
if (!distributionSet.isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Distribution set of type "
|
||||
+ distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId());
|
||||
}
|
||||
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DistributionSet getValid(final long id) {
|
||||
final DistributionSet distributionSet = getOrElseThrowException(id);
|
||||
|
||||
if (!distributionSet.isValid()) {
|
||||
throw new InvalidDistributionSetException("Distribution set of type " + distributionSet.getType().getKey()
|
||||
+ " is invalid: " + distributionSet.getId());
|
||||
}
|
||||
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void invalidate(final DistributionSet set) {
|
||||
final JpaDistributionSet jpaSet = (JpaDistributionSet) set;
|
||||
jpaSet.invalidate();
|
||||
distributionSetRepository.save(jpaSet);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.RolloutHelper;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutGroupDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||
@@ -155,6 +156,9 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
case RUNNING:
|
||||
handleRunningRollout((JpaRollout) rollout);
|
||||
break;
|
||||
case STOPPING:
|
||||
handleStopRollout((JpaRollout) rollout);
|
||||
break;
|
||||
default:
|
||||
LOGGER.error("Rollout in status {} not supposed to be handled!", rollout.getStatus());
|
||||
break;
|
||||
@@ -244,6 +248,39 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
sendRolloutGroupDeletedEvents(rollout);
|
||||
}
|
||||
|
||||
private void handleStopRollout(final JpaRollout rollout) {
|
||||
LOGGER.debug("handleStopRollout called for {}", rollout.getId());
|
||||
// clean up all scheduled actions
|
||||
final Slice<JpaAction> scheduledActions = findScheduledActionsByRollout(rollout);
|
||||
deleteScheduledActions(rollout, scheduledActions);
|
||||
|
||||
// avoid another scheduler round and re-check if all scheduled actions
|
||||
// has been cleaned up. we flush first to ensure that the we include the
|
||||
// deletion above
|
||||
entityManager.flush();
|
||||
final boolean hasScheduledActionsLeft = actionRepository.countByRolloutIdAndStatus(rollout.getId(),
|
||||
Status.SCHEDULED) > 0;
|
||||
|
||||
if (hasScheduledActionsLeft) {
|
||||
return;
|
||||
}
|
||||
|
||||
rolloutGroupRepository.findByRolloutAndStatusNotIn(rollout,
|
||||
Arrays.asList(RolloutGroupStatus.FINISHED, RolloutGroupStatus.ERROR)).forEach(rolloutGroup -> {
|
||||
rolloutGroup.setStatus(RolloutGroupStatus.FINISHED);
|
||||
rolloutGroupRepository.save(rolloutGroup);
|
||||
});
|
||||
|
||||
rollout.setStatus(RolloutStatus.FINISHED);
|
||||
rolloutRepository.save(rollout);
|
||||
|
||||
final List<Long> groupIds = rollout.getRolloutGroups().stream().map(RolloutGroup::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
afterCommit.afterCommit(() -> eventPublisherHolder.getEventPublisher().publishEvent(new RolloutStoppedEvent(
|
||||
tenantAware.getCurrentTenant(), eventPublisherHolder.getApplicationId(), rollout.getId(), groupIds)));
|
||||
}
|
||||
|
||||
private void handleReadyRollout(final Rollout rollout) {
|
||||
if (rollout.getStartAt() != null && rollout.getStartAt() <= System.currentTimeMillis()) {
|
||||
LOGGER.debug(
|
||||
|
||||
@@ -100,7 +100,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaRolloutManagement.class);
|
||||
|
||||
private static final List<RolloutStatus> ACTIVE_ROLLOUTS = Arrays.asList(RolloutStatus.CREATING,
|
||||
RolloutStatus.DELETING, RolloutStatus.STARTING, RolloutStatus.READY, RolloutStatus.RUNNING);
|
||||
RolloutStatus.DELETING, RolloutStatus.STARTING, RolloutStatus.READY, RolloutStatus.RUNNING,
|
||||
RolloutStatus.STOPPING);
|
||||
|
||||
private static final List<RolloutStatus> ROLLOUT_STATUS_STOPPABLE = Arrays.asList(RolloutStatus.RUNNING,
|
||||
RolloutStatus.CREATING, RolloutStatus.PAUSED, RolloutStatus.READY, RolloutStatus.STARTING,
|
||||
RolloutStatus.WAITING_FOR_APPROVAL, RolloutStatus.APPROVAL_DENIED);
|
||||
|
||||
@Autowired
|
||||
private RolloutRepository rolloutRepository;
|
||||
@@ -126,8 +131,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
|
||||
private final Database database;
|
||||
|
||||
public JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
|
||||
final RolloutGroupManagement rolloutGroupManagement,
|
||||
public JpaRolloutManagement(final TargetManagement targetManagement,
|
||||
final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement,
|
||||
final DistributionSetManagement distributionSetManagement, final ApplicationContext context,
|
||||
final EventPublisherHolder eventPublisherHolder, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final PlatformTransactionManager txManager, final TenantAware tenantAware, final LockRegistry lockRegistry,
|
||||
@@ -151,7 +156,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
@Override
|
||||
public Page<Rollout> findByRsql(final Pageable pageable, final String rsqlParam, final boolean deleted) {
|
||||
final List<Specification<JpaRollout>> specList = Lists.newArrayListWithExpectedSize(2);
|
||||
specList.add(RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlParam, RolloutFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(RolloutSpecification.isDeletedWithDistributionSet(deleted));
|
||||
|
||||
return JpaRolloutHelper.convertPage(findByCriteriaAPI(pageable, specList), pageable);
|
||||
@@ -400,7 +406,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
|
||||
final String tenant = tenantAware.getCurrentTenant();
|
||||
|
||||
final String handlerId = tenant + "-rollout";
|
||||
final String handlerId = createRolloutLockKey(tenant);
|
||||
final Lock lock = lockRegistry.obtain(handlerId);
|
||||
if (!lock.tryLock()) {
|
||||
return;
|
||||
@@ -414,6 +420,10 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
}
|
||||
|
||||
public static String createRolloutLockKey(final String tenant) {
|
||||
return tenant + "-rollout";
|
||||
}
|
||||
|
||||
private long handleRollout(final long rolloutId) {
|
||||
final JpaRollout rollout = rolloutRepository.findById(rolloutId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||
@@ -451,6 +461,11 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
return rolloutRepository.count(JpaRolloutHelper.likeNameOrDescription(searchText, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByDistributionSetIdAndRolloutIsStoppable(final long setId) {
|
||||
return rolloutRepository.countByDistributionSetIdAndStatusIn(setId, ROLLOUT_STATUS_STOPPABLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<Rollout> findByFiltersWithDetailedStatus(final Pageable pageable, final String searchText,
|
||||
final boolean deleted) {
|
||||
@@ -483,8 +498,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
// null
|
||||
rollout.setStartAt(update.getStartAt().orElse(null));
|
||||
update.getSet().ifPresent(setId -> {
|
||||
final DistributionSet set = distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
final DistributionSet set = distributionSetManagement.getValidAndComplete(setId);
|
||||
|
||||
rollout.setDistributionSet(set);
|
||||
});
|
||||
@@ -596,7 +610,20 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
|
||||
private void runInUserContext(final BaseEntity rollout, final Runnable handler) {
|
||||
DeploymentHelper.runInNonSystemContext(handler, () -> Objects.requireNonNull(rollout.getCreatedBy()), tenantAware);
|
||||
DeploymentHelper.runInNonSystemContext(handler, () -> Objects.requireNonNull(rollout.getCreatedBy()),
|
||||
tenantAware);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelRolloutsForDistributionSet(final DistributionSet set) {
|
||||
// stop all rollouts for this distribution set
|
||||
rolloutRepository.findByDistributionSetAndStatusIn(set, ROLLOUT_STATUS_STOPPABLE).forEach(rollout -> {
|
||||
final JpaRollout jpaRollout = (JpaRollout) rollout;
|
||||
jpaRollout.setStatus(RolloutStatus.STOPPING);
|
||||
rolloutRepository.save(jpaRollout);
|
||||
LOGGER.debug("Rollout {} stopped", jpaRollout.getId());
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ 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.InvalidAutoAssignActionTypeException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTargetFilterQueryCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
@@ -72,7 +71,7 @@ import cz.jirutka.rsql.parser.RSQLParserException;
|
||||
public class JpaTargetFilterQueryManagement implements TargetFilterQueryManagement {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JpaTargetFilterQueryManagement.class);
|
||||
|
||||
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final TargetManagement targetManagement;
|
||||
|
||||
@@ -147,6 +146,11 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
return targetFilterQueryRepository.count();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByAutoAssignDistributionSetId(final long autoAssignDistributionSetId) {
|
||||
return targetFilterQueryRepository.countByAutoAssignDistributionSetId(autoAssignDistributionSetId);
|
||||
}
|
||||
|
||||
private static Page<TargetFilterQuery> convertPage(final Page<JpaTargetFilterQuery> findAll,
|
||||
final Pageable pageable) {
|
||||
return new PageImpl<>(new ArrayList<>(findAll.getContent()), pageable, findAll.getTotalElements());
|
||||
@@ -165,8 +169,8 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
public Page<TargetFilterQuery> findByRsql(final Pageable pageable, final String rsqlFilter) {
|
||||
List<Specification<JpaTargetFilterQuery>> specList = Collections.emptyList();
|
||||
if (!StringUtils.isEmpty(rsqlFilter)) {
|
||||
specList = Collections.singletonList(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database));
|
||||
specList = Collections.singletonList(RSQLUtility.buildRsqlSpecification(rsqlFilter,
|
||||
TargetFilterQueryFields.class, virtualPropertyReplacer, database));
|
||||
}
|
||||
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
|
||||
}
|
||||
@@ -185,13 +189,13 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
final String rsqlFilter) {
|
||||
final List<Specification<JpaTargetFilterQuery>> specList = Lists.newArrayListWithExpectedSize(2);
|
||||
|
||||
final DistributionSet distributionSet = findDistributionSetAndThrowExceptionIfNotFound(setId);
|
||||
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
|
||||
|
||||
specList.add(TargetFilterQuerySpecification.byAutoAssignDS(distributionSet));
|
||||
|
||||
if (!StringUtils.isEmpty(rsqlFilter)) {
|
||||
specList.add(
|
||||
RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class, virtualPropertyReplacer, database));
|
||||
specList.add(RSQLUtility.buildRsqlSpecification(rsqlFilter, TargetFilterQueryFields.class,
|
||||
virtualPropertyReplacer, database));
|
||||
}
|
||||
return convertPage(findTargetFilterQueryByCriteriaAPI(pageable, specList), pageable);
|
||||
}
|
||||
@@ -264,8 +268,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
// specify an
|
||||
// auto-assign distribution set when creating a target filter query
|
||||
assertMaxTargetsQuota(targetFilterQuery.getQuery());
|
||||
final JpaDistributionSet ds = findDistributionSetAndThrowExceptionIfNotFound(update.getDsId());
|
||||
verifyDistributionSetAndThrowExceptionIfNotValid(ds);
|
||||
final JpaDistributionSet ds = (JpaDistributionSet) distributionSetManagement
|
||||
.getValidAndComplete(update.getDsId());
|
||||
verifyDistributionSetAndThrowExceptionIfDeleted(ds);
|
||||
targetFilterQuery.setAutoAssignDistributionSet(ds);
|
||||
targetFilterQuery.setAutoAssignInitiatedBy(tenantAware.getCurrentUsername());
|
||||
targetFilterQuery.setAutoAssignActionType(sanitizeAutoAssignActionType(update.getActionType()));
|
||||
@@ -274,9 +279,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
return targetFilterQueryRepository.save(targetFilterQuery);
|
||||
}
|
||||
|
||||
private static void verifyDistributionSetAndThrowExceptionIfNotValid(final DistributionSet distributionSet) {
|
||||
if (!distributionSet.isComplete() || distributionSet.isDeleted()) {
|
||||
throw new InvalidAutoAssignDistributionSetException();
|
||||
private static void verifyDistributionSetAndThrowExceptionIfDeleted(final DistributionSet distributionSet) {
|
||||
if (distributionSet.isDeleted()) {
|
||||
throw new EntityNotFoundException(DistributionSet.class, distributionSet.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,11 +297,6 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
return actionType;
|
||||
}
|
||||
|
||||
private JpaDistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return (JpaDistributionSet) distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
|
||||
private JpaTargetFilterQuery findTargetFilterQueryOrThrowExceptionIfNotFound(final Long queryId) {
|
||||
return targetFilterQueryRepository.findById(queryId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, queryId));
|
||||
@@ -317,4 +317,11 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme
|
||||
QuotaHelper.assertAssignmentQuota(targetManagement.countByRsql(query),
|
||||
quotaManagement.getMaxTargetsPerAutoAssignment(), Target.class, TargetFilterQuery.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void cancelAutoAssignmentForDistributionSet(final long setId) {
|
||||
targetFilterQueryRepository.unsetAutoAssignDistributionSetAndActionType(setId);
|
||||
LOGGER.debug("Auto assignments for distribution sets {} deactivated", setId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ import org.eclipse.hawkbit.repository.jpa.rollout.condition.PauseRolloutGroupAct
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.StartNextGroupRolloutGroupSuccessAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupErrorCondition;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.ThresholdRolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParserValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.DefaultRsqlVisitorFactory;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlParserValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -238,13 +238,14 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
TargetBuilder targetBuilder(final TargetTypeManagement targetTypeManagement){
|
||||
TargetBuilder targetBuilder(final TargetTypeManagement targetTypeManagement) {
|
||||
return new JpaTargetBuilder(targetTypeManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dsTypeManagement
|
||||
* for loading {@link TargetType#getCompatibleDistributionSetTypes()}
|
||||
* for loading
|
||||
* {@link TargetType#getCompatibleDistributionSetTypes()}
|
||||
* @return TargetTypeBuilder bean
|
||||
*/
|
||||
@Bean
|
||||
@@ -434,7 +435,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
@Override
|
||||
@Bean
|
||||
public PlatformTransactionManager transactionManager(
|
||||
ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
final ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
|
||||
return new MultiTenantJpaTransactionManager();
|
||||
}
|
||||
|
||||
@@ -485,12 +486,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
DistributionSetTypeManagement distributionSetTypeManagement(
|
||||
final DistributionSetTypeRepository distributionSetTypeRepository,
|
||||
final SoftwareModuleTypeRepository softwareModuleTypeRepository,
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final TargetTypeRepository targetTypeRepository,
|
||||
final DistributionSetRepository distributionSetRepository, final TargetTypeRepository targetTypeRepository,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties,
|
||||
final QuotaManagement quotaManagement) {
|
||||
return new JpaDistributionSetTypeManagement(distributionSetTypeRepository, softwareModuleTypeRepository,
|
||||
distributionSetRepository, targetTypeRepository, virtualPropertyReplacer, properties.getDatabase(), quotaManagement);
|
||||
distributionSetRepository, targetTypeRepository, virtualPropertyReplacer, properties.getDatabase(),
|
||||
quotaManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,13 +542,15 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
final TargetRepository targetRepository, final TargetMetadataRepository targetMetadataRepository,
|
||||
final RolloutGroupRepository rolloutGroupRepository,
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final TargetTypeRepository targetTypeRepository,
|
||||
final TargetTagRepository targetTagRepository, final EventPublisherHolder eventPublisherHolder,
|
||||
final TenantAware tenantAware, final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final JpaProperties properties) {
|
||||
return new JpaTargetManagement(entityManager, quotaManagement, targetRepository, targetTypeRepository, targetMetadataRepository,
|
||||
rolloutGroupRepository, distributionSetRepository, targetFilterQueryRepository, targetTagRepository,
|
||||
eventPublisherHolder, tenantAware, afterCommit, virtualPropertyReplacer, properties.getDatabase());
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository,
|
||||
final TargetTypeRepository targetTypeRepository, final TargetTagRepository targetTagRepository,
|
||||
final EventPublisherHolder eventPublisherHolder, final TenantAware tenantAware,
|
||||
final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final JpaProperties properties) {
|
||||
return new JpaTargetManagement(entityManager, quotaManagement, targetRepository, targetTypeRepository,
|
||||
targetMetadataRepository, rolloutGroupRepository, distributionSetRepository,
|
||||
targetFilterQueryRepository, targetTagRepository, eventPublisherHolder, tenantAware, afterCommit,
|
||||
virtualPropertyReplacer, properties.getDatabase());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -718,17 +721,17 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
@ConditionalOnMissingBean
|
||||
DeploymentManagement deploymentManagement(final EntityManager entityManager,
|
||||
final ActionRepository actionRepository, final DistributionSetRepository distributionSetRepository,
|
||||
final TargetRepository targetRepository, final ActionStatusRepository actionStatusRepository,
|
||||
final AuditorAware<String> auditorProvider, final EventPublisherHolder eventPublisherHolder,
|
||||
final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer,
|
||||
final PlatformTransactionManager txManager,
|
||||
final DistributionSetManagement distributionSetManagement, final TargetRepository targetRepository,
|
||||
final ActionStatusRepository actionStatusRepository, final AuditorAware<String> auditorProvider,
|
||||
final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit,
|
||||
final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware,
|
||||
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetRepository, targetRepository,
|
||||
actionStatusRepository, auditorProvider, eventPublisherHolder, afterCommit, virtualPropertyReplacer,
|
||||
txManager, tenantConfigurationManagement, quotaManagement, systemSecurityContext, tenantAware,
|
||||
properties.getDatabase(), repositoryProperties);
|
||||
return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetManagement,
|
||||
distributionSetRepository, targetRepository, actionStatusRepository, auditorProvider,
|
||||
eventPublisherHolder, afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement,
|
||||
quotaManagement, systemSecurityContext, tenantAware, properties.getDatabase(), repositoryProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -813,7 +816,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link AutoAssignScheduler} bean.
|
||||
*
|
||||
*
|
||||
* Note: does not activate in test profile, otherwise it is hard to test the
|
||||
* auto assign functionality.
|
||||
*
|
||||
@@ -843,12 +846,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link AutoActionCleanup} bean.
|
||||
*
|
||||
*
|
||||
* @param deploymentManagement
|
||||
* Deployment management service
|
||||
* @param configManagement
|
||||
* Tenant configuration service
|
||||
*
|
||||
*
|
||||
* @return a new {@link AutoActionCleanup} bean
|
||||
*/
|
||||
@Bean
|
||||
@@ -859,7 +862,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link AutoCleanupScheduler} bean.
|
||||
*
|
||||
*
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param systemSecurityContext
|
||||
@@ -868,7 +871,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
* to lock the tenant for auto assignment
|
||||
* @param cleanupTasks
|
||||
* a list of cleanup tasks
|
||||
*
|
||||
*
|
||||
* @return a new {@link AutoCleanupScheduler} bean
|
||||
*/
|
||||
@Bean
|
||||
@@ -883,10 +886,10 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* {@link RolloutScheduler} bean.
|
||||
*
|
||||
*
|
||||
* Note: does not activate in test profile, otherwise it is hard to test the
|
||||
* rollout handling functionality.
|
||||
*
|
||||
*
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param rolloutManagement
|
||||
@@ -906,7 +909,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* Creates the {@link RsqlVisitorFactory} bean.
|
||||
*
|
||||
*
|
||||
* @return A new {@link RsqlVisitorFactory} bean.
|
||||
*/
|
||||
@Bean
|
||||
@@ -917,7 +920,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
|
||||
/**
|
||||
* Obtains the {@link RsqlVisitorFactoryHolder} bean.
|
||||
*
|
||||
*
|
||||
* @return The {@link RsqlVisitorFactoryHolder} singleton.
|
||||
*/
|
||||
@Bean
|
||||
@@ -925,4 +928,22 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return RsqlVisitorFactoryHolder.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link JpaDistributionSetInvalidationManagement} bean.
|
||||
*
|
||||
* @return a new {@link JpaDistributionSetInvalidationManagement}
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
JpaDistributionSetInvalidationManagement distributionSetInvalidationManagement(
|
||||
final DistributionSetManagement distributionSetManagement, final RolloutManagement rolloutManagement,
|
||||
final DeploymentManagement deploymentManagement,
|
||||
final TargetFilterQueryManagement targetFilterQueryManagement, final PlatformTransactionManager txManager,
|
||||
final RepositoryProperties repositoryProperties, final TenantAware tenantAware,
|
||||
final LockRegistry lockRegistry) {
|
||||
return new JpaDistributionSetInvalidationManagement(distributionSetManagement, rolloutManagement,
|
||||
deploymentManagement, targetFilterQueryManagement, txManager, repositoryProperties, tenantAware,
|
||||
lockRegistry);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
@@ -33,7 +34,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} referring a specific rollout in the
|
||||
* order of creating them. ID ASC.
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroups belong to
|
||||
* @return the rollout groups belonging to a rollout ordered by ID ASC.
|
||||
@@ -43,7 +44,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} referring a specific rollout in a
|
||||
* specific {@link RolloutGroupStatus}.
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroup belong to
|
||||
* @param status
|
||||
@@ -58,7 +59,7 @@ public interface RolloutGroupRepository
|
||||
* the spring-data, so this is specific usecase regarding to the
|
||||
* rollout-management to find out rolloutgroups which are in specific
|
||||
* states.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout the rolloutgroup belong to
|
||||
* @param rolloutGroupStatus1
|
||||
@@ -74,10 +75,10 @@ public interface RolloutGroupRepository
|
||||
@Param("status2") RolloutGroupStatus rolloutGroupStatus2);
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Counts all rollout-groups refering to a given {@link Rollout} by its ID
|
||||
* and groups which not having the given status.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout refering the groups
|
||||
* @param status1
|
||||
@@ -97,7 +98,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} for a specific parent in a specific
|
||||
* status. Retrieves the child rolloutgroup for a specific status.
|
||||
*
|
||||
*
|
||||
* @param rolloutGroupId
|
||||
* the rolloutgroupId to find the parents
|
||||
* @param status
|
||||
@@ -111,7 +112,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Updates all {@link RolloutGroup#getStatus()} of children for given
|
||||
* parent.
|
||||
*
|
||||
*
|
||||
* @param parent
|
||||
* the parent rolloutgroup
|
||||
* @param status
|
||||
@@ -125,7 +126,7 @@ public interface RolloutGroupRepository
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} for a specific rollout and status not
|
||||
* having ordered by ID DESC, latest top.
|
||||
*
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroup belong to
|
||||
* @param notStatus
|
||||
@@ -135,9 +136,22 @@ public interface RolloutGroupRepository
|
||||
*/
|
||||
List<JpaRolloutGroup> findByRolloutAndStatusNotOrderByIdDesc(JpaRollout rollout, RolloutGroupStatus notStatus);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup}s for a specific rollout and status not
|
||||
* having.
|
||||
*
|
||||
* @param rollout
|
||||
* the rollout the rolloutgroup belong to
|
||||
* @param status
|
||||
* the status which the rolloutgroup should not have
|
||||
* @return rolloutgroup referring to a rollout and not having a specific
|
||||
* status.
|
||||
*/
|
||||
List<JpaRolloutGroup> findByRolloutAndStatusNotIn(JpaRollout rollout, Collection<RolloutGroupStatus> status);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link RolloutGroup} for a specific rollout.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to find the rollout groups
|
||||
* @param page
|
||||
@@ -148,10 +162,10 @@ public interface RolloutGroupRepository
|
||||
|
||||
/**
|
||||
* Counts all {@link RolloutGroup} for a specific rollout.
|
||||
*
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to find the rollout groups
|
||||
*
|
||||
*
|
||||
* @return the amount of found {@link RolloutGroup}s.
|
||||
*/
|
||||
long countByRolloutId(Long rolloutId);
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.Optional;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
@@ -33,7 +34,7 @@ public interface RolloutRepository
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Rollout} for given status.
|
||||
*
|
||||
*
|
||||
* @param status
|
||||
* the status of the rollouts to find
|
||||
* @return the list of {@link Rollout} for specific status
|
||||
@@ -44,7 +45,7 @@ public interface RolloutRepository
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Rollout} for a specific {@code name}
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* the rollout name
|
||||
* @return {@link Rollout} for specific name
|
||||
@@ -64,4 +65,28 @@ public interface RolloutRepository
|
||||
@Transactional
|
||||
@Query("DELETE FROM JpaRollout t WHERE t.tenant = :tenant")
|
||||
void deleteByTenant(@Param("tenant") String tenant);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link Rollout}s for a specific {@link DistributionSet} in
|
||||
* a given {@link RolloutStatus}.
|
||||
*
|
||||
* @param set
|
||||
* the distribution set
|
||||
* @param status
|
||||
* the status of the rollout
|
||||
* @return {@link Rollout} for specific distribution set
|
||||
*/
|
||||
List<Rollout> findByDistributionSetAndStatusIn(DistributionSet set, Collection<RolloutStatus> status);
|
||||
|
||||
/**
|
||||
* Counts all {@link Rollout}s for a specific {@link DistributionSet} in a
|
||||
* given {@link RolloutStatus}.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the distribution set
|
||||
* @param status
|
||||
* the status of the rollout
|
||||
* @return the count
|
||||
*/
|
||||
long countByDistributionSetIdAndStatusIn(long distributionSetId, Collection<RolloutStatus> status);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public interface TargetFilterQueryRepository
|
||||
|
||||
/**
|
||||
* Find customer target filter by name
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* @return custom target filter
|
||||
*/
|
||||
@@ -56,6 +56,16 @@ public interface TargetFilterQueryRepository
|
||||
@Query("update JpaTargetFilterQuery d set d.autoAssignDistributionSet = NULL, d.autoAssignActionType = NULL where d.autoAssignDistributionSet in :ids")
|
||||
void unsetAutoAssignDistributionSetAndActionType(@Param("ids") Long... dsIds);
|
||||
|
||||
/**
|
||||
* Counts all target filters that have a given auto assign distribution set
|
||||
* assigned.
|
||||
*
|
||||
* @param autoAssignDistributionSetId
|
||||
* the id of the distribution set
|
||||
* @return the count
|
||||
*/
|
||||
long countByAutoAssignDistributionSetId(long autoAssignDistributionSetId);
|
||||
|
||||
/**
|
||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||
|
||||
@@ -11,9 +11,7 @@ package org.eclipse.hawkbit.repository.jpa.builder;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.builder.AbstractRolloutUpdateCreate;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
public class JpaRolloutCreate extends AbstractRolloutUpdateCreate<RolloutCreate> implements RolloutCreate {
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
@@ -28,7 +26,7 @@ public class JpaRolloutCreate extends AbstractRolloutUpdateCreate<RolloutCreate>
|
||||
|
||||
rollout.setName(name);
|
||||
rollout.setDescription(description);
|
||||
rollout.setDistributionSet(findDistributionSetAndThrowExceptionIfNotFound(set));
|
||||
rollout.setDistributionSet(distributionSetManagement.getValidAndComplete(set));
|
||||
rollout.setTargetFilterQuery(targetFilterQuery);
|
||||
rollout.setStartAt(startAt);
|
||||
rollout.setWeight(weight);
|
||||
@@ -43,9 +41,4 @@ public class JpaRolloutCreate extends AbstractRolloutUpdateCreate<RolloutCreate>
|
||||
|
||||
return rollout;
|
||||
}
|
||||
|
||||
private DistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,9 @@ 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.EntityNotFoundException;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -35,16 +33,11 @@ public class JpaTargetFilterQueryCreate extends AbstractTargetFilterQueryUpdateC
|
||||
public JpaTargetFilterQuery build() {
|
||||
|
||||
return new JpaTargetFilterQuery(name, query,
|
||||
getAutoAssignDistributionSetId().map(this::findDistributionSetAndThrowExceptionIfNotFound).orElse(null),
|
||||
getAutoAssignDistributionSetId().map(distributionSetManagement::getValidAndComplete).orElse(null),
|
||||
getAutoAssignActionType().filter(JpaTargetFilterQueryCreate::isAutoAssignActionTypeValid).orElse(null),
|
||||
weight);
|
||||
}
|
||||
|
||||
private DistributionSet findDistributionSetAndThrowExceptionIfNotFound(final Long setId) {
|
||||
return distributionSetManagement.get(setId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, setId));
|
||||
}
|
||||
|
||||
private static boolean isAutoAssignActionTypeValid(final ActionType actionType) {
|
||||
if (!TargetFilterQuery.ALLOWED_AUTO_ASSIGN_ACTION_TYPES.contains(actionType)) {
|
||||
throw new InvalidAutoAssignActionTypeException();
|
||||
|
||||
@@ -116,6 +116,9 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
@Column(name = "complete")
|
||||
private boolean complete;
|
||||
|
||||
@Column(name = "valid")
|
||||
private boolean valid;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@@ -145,6 +148,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
super(name, version, description);
|
||||
|
||||
this.requiredMigrationStep = requiredMigrationStep;
|
||||
this.valid = true;
|
||||
this.type = type;
|
||||
if (moduleList != null) {
|
||||
moduleList.forEach(this::addModule);
|
||||
@@ -327,6 +331,15 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
return complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
this.valid = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fireCreateEvent(final DescriptorEvent descriptorEvent) {
|
||||
publishEventWithEventPublisher(
|
||||
|
||||
@@ -93,7 +93,8 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
|
||||
@ConversionValue(objectValue = "DELETING", dataValue = "9"),
|
||||
@ConversionValue(objectValue = "DELETED", dataValue = "10"),
|
||||
@ConversionValue(objectValue = "WAITING_FOR_APPROVAL", dataValue = "11"),
|
||||
@ConversionValue(objectValue = "APPROVAL_DENIED", dataValue = "12") })
|
||||
@ConversionValue(objectValue = "APPROVAL_DENIED", dataValue = "12"),
|
||||
@ConversionValue(objectValue = "STOPPING", dataValue = "13") })
|
||||
@Convert("rolloutstatus")
|
||||
@NotNull
|
||||
private RolloutStatus status = RolloutStatus.CREATING;
|
||||
|
||||
@@ -45,7 +45,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* DELETED attribute.
|
||||
*
|
||||
*
|
||||
* @param isDeleted
|
||||
* TRUE/FALSE are compared to the attribute DELETED. If NULL the
|
||||
* attribute is ignored
|
||||
@@ -59,7 +59,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* COMPLETED attribute.
|
||||
*
|
||||
*
|
||||
* @param isCompleted
|
||||
* TRUE/FALSE are compared to the attribute COMPLETED. If NULL
|
||||
* the attribute is ignored
|
||||
@@ -70,6 +70,20 @@ public final class DistributionSetSpecification {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* VALID attribute.
|
||||
*
|
||||
* @param isValid
|
||||
* TRUE/FALSE are compared to the attribute VALID. If NULL the
|
||||
* attribute is ignored
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSet> isValid(final Boolean isValid) {
|
||||
return (targetRoot, query, cb) -> cb.equal(targetRoot.<Boolean> get(JpaDistributionSet_.valid), isValid);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet} with given
|
||||
* {@link DistributionSet#getId()}.
|
||||
@@ -111,7 +125,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by "like
|
||||
* name or like description or like version".
|
||||
*
|
||||
*
|
||||
* @param subString
|
||||
* to be filtered on
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
@@ -126,7 +140,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by "like
|
||||
* name and like version".
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* to be filtered on
|
||||
* @param version
|
||||
@@ -142,7 +156,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by "has at
|
||||
* least one of the given tag names".
|
||||
*
|
||||
*
|
||||
* @param tagNames
|
||||
* to be filtered on
|
||||
* @param selectDSWithNoTag
|
||||
@@ -187,7 +201,7 @@ public final class DistributionSetSpecification {
|
||||
/**
|
||||
* returns query criteria {@link Specification} comparing case insensitive
|
||||
* "NAME == AND VERSION ==".
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* to be filtered on
|
||||
* @param version
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE sp_distribution_set ADD COLUMN valid BOOLEAN;
|
||||
|
||||
UPDATE sp_distribution_set SET valid = 1;
|
||||
Reference in New Issue
Block a user