Remove unlimited collections from the repository API (#496)
* Started to get rid of unlimited collections Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Align API usage. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * fix compile issues. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix tests. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove comments Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Performance optimizations. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove dead code. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Allign method names Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Wait until the action update event is processed Conflicts: hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageHandlerServiceIntegrationTest.java Signed-off-by: SirWayne <dennis.melzer@bosch-si.com> * Started new tag APIs Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Quotas into central interface. Tag tests added. Event names fixed. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Simplified consumer run for every tenant. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * remove unused fields. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Alligned beans. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Deprecated client methods for old resources. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix new foreach method. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix transaction for foreach. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Extended DS creating to handle larger volumes. Fix on Readme. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fixed simulator bug and cleaned up tests. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix in sorting. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Remove configuration processor. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix wrong usage of sanitize. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Missing brackets. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix README API compatability. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix misinterpretation of pessimistic locking exceptions. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix stability sentence. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Code cleanup. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fixed page calculation Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -172,7 +172,8 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction, Long>,
|
||||
*/
|
||||
@EntityGraph(value = "Action.ds", type = EntityGraphType.LOAD)
|
||||
@Query("Select a from JpaAction a where a.target.controllerId = :target and a.active= :active order by a.id")
|
||||
List<Action> findByActiveAndTarget(@Param("target") String target, @Param("active") boolean active);
|
||||
Page<Action> findByActiveAndTarget(Pageable pageable, @Param("target") String target,
|
||||
@Param("active") boolean active);
|
||||
|
||||
/**
|
||||
* Switches the status of actions from one specific status into another,
|
||||
|
||||
@@ -17,11 +17,12 @@ import javax.persistence.EntityManager;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Tag;
|
||||
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
@@ -38,13 +39,29 @@ public interface DistributionSetRepository
|
||||
|
||||
/**
|
||||
* Finds {@link DistributionSet}s by assigned {@link Tag}.
|
||||
*
|
||||
* @param pageable
|
||||
* paging and sorting information
|
||||
*
|
||||
* @param tag
|
||||
* @param tagId
|
||||
* to be found
|
||||
* @return list of found {@link DistributionSet}s
|
||||
*/
|
||||
@Query(value = "Select Distinct ds from JpaDistributionSet ds join ds.tags dst where dst = :tag")
|
||||
List<JpaDistributionSet> findByTag(@Param("tag") final DistributionSetTag tag);
|
||||
@Query(value = "Select Distinct ds from JpaDistributionSet ds join ds.tags dst where dst.id = :tag")
|
||||
Page<JpaDistributionSet> findByTag(Pageable pageable, @Param("tag") final Long tagId);
|
||||
|
||||
/**
|
||||
* Finds {@link DistributionSet}s by assigned {@link Tag}.
|
||||
*
|
||||
* @param pageable
|
||||
* paging and sorting information
|
||||
*
|
||||
* @param tagId
|
||||
* to be found
|
||||
* @return page of found {@link DistributionSet}s
|
||||
*/
|
||||
@Query(value = "Select Distinct ds from JpaDistributionSet ds join ds.tags dst where dst.id = :tagId")
|
||||
Page<JpaDistributionSet> findByTagId(Pageable pageable, @Param("tagId") final Long tagId);
|
||||
|
||||
/**
|
||||
* deletes the {@link DistributionSet}s with the given IDs.
|
||||
@@ -147,9 +164,9 @@ public interface DistributionSetRepository
|
||||
|
||||
/**
|
||||
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety
|
||||
* reasons (this is a "delete everything" query after all) we add the tenant manually to
|
||||
* query even if this will by done by {@link EntityManager} anyhow. The DB
|
||||
* should take care of optimizing this away.
|
||||
* reasons (this is a "delete everything" query after all) we add the tenant
|
||||
* manually to query even if this will by done by {@link EntityManager}
|
||||
* anyhow. The DB should take care of optimizing this away.
|
||||
*
|
||||
* @param tenant
|
||||
* to delete data from
|
||||
|
||||
@@ -51,6 +51,16 @@ public interface DistributionSetTagRepository
|
||||
*/
|
||||
Optional<DistributionSetTag> findByNameEquals(final String tagName);
|
||||
|
||||
/**
|
||||
* Checks if tag with given name exists.
|
||||
*
|
||||
* @param tagName
|
||||
* to check for
|
||||
* @return <code>true</code> is tag with given name exists
|
||||
*/
|
||||
@Query("SELECT CASE WHEN COUNT(t)>0 THEN 'true' ELSE 'false' END FROM JpaDistributionSetTag t WHERE t.name=:tagName")
|
||||
boolean existsByName(@Param("tagName") String tagName);
|
||||
|
||||
/**
|
||||
* Returns all instances of the type.
|
||||
*
|
||||
|
||||
@@ -20,6 +20,7 @@ import javax.persistence.criteria.Root;
|
||||
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
@@ -47,7 +48,6 @@ import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
@@ -92,7 +92,7 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
private ActionStatusRepository actionStatusRepository;
|
||||
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
private QuotaManagement quotaManagement;
|
||||
|
||||
@Autowired
|
||||
private RepositoryProperties repositoryProperties;
|
||||
@@ -313,15 +313,14 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
private Action handleAddUpdateActionStatus(final JpaActionStatus actionStatus, final JpaAction action) {
|
||||
LOG.debug("addUpdateActionStatus for action {}", action.getId());
|
||||
|
||||
JpaTarget target = (JpaTarget) action.getTarget();
|
||||
|
||||
switch (actionStatus.getStatus()) {
|
||||
case ERROR:
|
||||
target = DeploymentHelper.updateTargetInfo(target, TargetUpdateStatus.ERROR, false);
|
||||
final JpaTarget target = DeploymentHelper.updateTargetInfo((JpaTarget) action.getTarget(),
|
||||
TargetUpdateStatus.ERROR, false);
|
||||
handleErrorOnAction(action, target);
|
||||
break;
|
||||
case FINISHED:
|
||||
handleFinishedAndStoreInTargetStatus(target, action);
|
||||
handleFinishedAndStoreInTargetStatus(action);
|
||||
break;
|
||||
default:
|
||||
// information status entry - check for a potential DOS attack
|
||||
@@ -332,7 +331,7 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
actionStatus.setAction(action);
|
||||
actionStatusRepository.save(actionStatus);
|
||||
|
||||
LOG.debug("addUpdateActionStatus {} for target {} is finished.", action, target.getId());
|
||||
LOG.debug("addUpdateActionStatus for action {} isfinished.", action.getId());
|
||||
|
||||
return actionRepository.save(action);
|
||||
}
|
||||
@@ -346,21 +345,21 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
}
|
||||
|
||||
private void checkForToManyStatusEntries(final JpaAction action) {
|
||||
if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) {
|
||||
if (quotaManagement.getMaxStatusEntriesPerAction() > 0) {
|
||||
|
||||
final Long statusCount = actionStatusRepository.countByAction(action);
|
||||
|
||||
if (statusCount >= securityProperties.getDos().getMaxStatusEntriesPerAction()) {
|
||||
if (statusCount >= quotaManagement.getMaxStatusEntriesPerAction()) {
|
||||
LOG_DOS.error(
|
||||
"Potential denial of service (DOS) attack identfied. More status entries in the system than permitted ({})!",
|
||||
securityProperties.getDos().getMaxStatusEntriesPerAction());
|
||||
throw new TooManyStatusEntriesException(
|
||||
String.valueOf(securityProperties.getDos().getMaxStatusEntriesPerAction()));
|
||||
quotaManagement.getMaxStatusEntriesPerAction());
|
||||
throw new TooManyStatusEntriesException(String.valueOf(quotaManagement.getMaxStatusEntriesPerAction()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleFinishedAndStoreInTargetStatus(final JpaTarget target, final JpaAction action) {
|
||||
private void handleFinishedAndStoreInTargetStatus(final JpaAction action) {
|
||||
final JpaTarget target = (JpaTarget) action.getTarget();
|
||||
action.setActive(false);
|
||||
action.setStatus(Status.FINISHED);
|
||||
final JpaDistributionSet ds = (JpaDistributionSet) entityManager.merge(action.getDistributionSet());
|
||||
@@ -388,11 +387,11 @@ public class JpaControllerManagement implements ControllerManagement {
|
||||
|
||||
target.getControllerAttributes().putAll(data);
|
||||
|
||||
if (target.getControllerAttributes().size() > securityProperties.getDos().getMaxAttributeEntriesPerTarget()) {
|
||||
if (target.getControllerAttributes().size() > quotaManagement.getMaxAttributeEntriesPerTarget()) {
|
||||
LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
|
||||
securityProperties.getDos().getMaxAttributeEntriesPerTarget());
|
||||
quotaManagement.getMaxAttributeEntriesPerTarget());
|
||||
throw new ToManyAttributeEntriesException(
|
||||
String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget()));
|
||||
String.valueOf(quotaManagement.getMaxAttributeEntriesPerTarget()));
|
||||
}
|
||||
|
||||
target.setRequestControllerAttributes(false);
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.stream.Collectors;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Join;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.ListJoin;
|
||||
import javax.persistence.criteria.Root;
|
||||
@@ -43,13 +42,10 @@ import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecuto
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionWithStatusCount;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||
@@ -58,7 +54,6 @@ import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
@@ -538,31 +533,6 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
||||
return actionRepository.findByTargetControllerId(pageable, controllerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActionWithStatusCount> findActionsWithStatusCountByTargetOrderByIdDesc(final String controllerId) {
|
||||
throwExceptionIfTargetDoesNotExist(controllerId);
|
||||
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<JpaActionWithStatusCount> query = cb.createQuery(JpaActionWithStatusCount.class);
|
||||
final Root<JpaAction> actionRoot = query.from(JpaAction.class);
|
||||
final ListJoin<JpaAction, JpaActionStatus> actionStatusJoin = actionRoot.join(JpaAction_.actionStatus,
|
||||
JoinType.LEFT);
|
||||
final Join<JpaAction, JpaDistributionSet> actionDsJoin = actionRoot.join(JpaAction_.distributionSet);
|
||||
final Join<JpaAction, JpaRollout> actionRolloutJoin = actionRoot.join(JpaAction_.rollout, JoinType.LEFT);
|
||||
|
||||
final CriteriaQuery<JpaActionWithStatusCount> multiselect = query.distinct(true).multiselect(
|
||||
actionRoot.get(JpaAction_.id), actionRoot.get(JpaAction_.actionType), actionRoot.get(JpaAction_.active),
|
||||
actionRoot.get(JpaAction_.forcedTime), actionRoot.get(JpaAction_.status),
|
||||
actionRoot.get(JpaAction_.createdAt), actionRoot.get(JpaAction_.lastModifiedAt),
|
||||
actionDsJoin.get(JpaDistributionSet_.id), actionDsJoin.get(JpaDistributionSet_.name),
|
||||
actionDsJoin.get(JpaDistributionSet_.version), cb.count(actionStatusJoin),
|
||||
actionRolloutJoin.get(JpaRollout_.name));
|
||||
multiselect.where(cb.equal(actionRoot.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId));
|
||||
multiselect.orderBy(cb.desc(actionRoot.get(JpaAction_.id)));
|
||||
multiselect.groupBy(actionRoot.get(JpaAction_.id));
|
||||
return Collections.unmodifiableList(entityManager.createQuery(multiselect).getResultList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Action> findActionsByTarget(final String rsqlParam, final String controllerId,
|
||||
final Pageable pageable) {
|
||||
@@ -584,17 +554,17 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Action> findActiveActionsByTarget(final String controllerId) {
|
||||
public Page<Action> findActiveActionsByTarget(final Pageable pageable, final String controllerId) {
|
||||
throwExceptionIfTargetDoesNotExist(controllerId);
|
||||
|
||||
return actionRepository.findByActiveAndTarget(controllerId, true);
|
||||
return actionRepository.findByActiveAndTarget(pageable, controllerId, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Action> findInActiveActionsByTarget(final String controllerId) {
|
||||
public Page<Action> findInActiveActionsByTarget(final Pageable pageable, final String controllerId) {
|
||||
throwExceptionIfTargetDoesNotExist(controllerId);
|
||||
|
||||
return actionRepository.findByActiveAndTarget(controllerId, false);
|
||||
return actionRepository.findByActiveAndTarget(pageable, controllerId, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -645,15 +615,6 @@ public class JpaDeploymentManagement implements DeploymentManagement {
|
||||
return actionStatusRepository.findByActionId(pageReq, actionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ActionStatus> findActionStatusByActionWithMessages(final Pageable pageReq, final Long actionId) {
|
||||
if (!actionRepository.exists(actionId)) {
|
||||
throw new EntityNotFoundException(Action.class, actionId);
|
||||
}
|
||||
|
||||
return actionStatusRepository.getByActionId(pageReq, actionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<String> findMessagesByActionStatusId(final Pageable pageable, final Long actionStatusId) {
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
|
||||
@@ -125,6 +125,9 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Autowired
|
||||
private SoftwareModuleTypeRepository softwareModuleTypeRepository;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetTagRepository distributionSetTagRepository;
|
||||
|
||||
@Override
|
||||
public Optional<DistributionSet> findDistributionSetByIdWithDetails(final Long distid) {
|
||||
return Optional.ofNullable(distributionSetRepository.findOne(DistributionSetSpecification.byId(distid)));
|
||||
@@ -235,7 +238,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteDistributionSet(final Collection<Long> distributionSetIDs) {
|
||||
final List<DistributionSet> setsFound = findDistributionSetAllById(distributionSetIDs);
|
||||
final List<DistributionSet> setsFound = findDistributionSetsById(distributionSetIDs);
|
||||
|
||||
if (setsFound.size() < distributionSetIDs.size()) {
|
||||
throw new EntityNotFoundException(DistributionSet.class, distributionSetIDs,
|
||||
@@ -485,6 +488,17 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return convertDsPage(findByCriteriaAPI(pageReq, specList), pageReq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSet> findDistributionSetsAll(final Pageable pageReq, final Boolean deleted) {
|
||||
|
||||
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>(1);
|
||||
if (deleted != null) {
|
||||
specList.add(DistributionSetSpecification.isDeleted(deleted));
|
||||
}
|
||||
|
||||
return convertDsPage(findByCriteriaAPI(pageReq, specList), pageReq);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSet> findDistributionSetsAllOrderedByLinkTarget(final Pageable pageable,
|
||||
final DistributionSetFilterBuilder distributionSetFilterBuilder, final String assignedOrInstalled) {
|
||||
@@ -536,12 +550,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DistributionSet> findDistributionSetsAll(final Collection<Long> dist) {
|
||||
return Collections
|
||||
.unmodifiableList(distributionSetRepository.findAll(DistributionSetSpecification.byIds(dist)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long countDistributionSetsAll() {
|
||||
final Specification<JpaDistributionSet> spec = DistributionSetSpecification.isDeleted(Boolean.FALSE);
|
||||
@@ -827,20 +835,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
.unmodifiableList(allDs.stream().map(distributionSetRepository::save).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public List<DistributionSet> unAssignAllDistributionSetsByTag(final Long dsTagId) {
|
||||
|
||||
final DistributionSetTag distributionSetTag = tagManagement.findDistributionSetTagById(dsTagId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, dsTagId));
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
final Collection<JpaDistributionSet> distributionSets = (Collection) distributionSetTag
|
||||
.getAssignedToDistributionSet();
|
||||
|
||||
return Collections.unmodifiableList(unAssignTag(distributionSets, distributionSetTag));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public DistributionSet unAssignTag(final Long dsId, final Long dsTagId) {
|
||||
@@ -894,8 +888,36 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DistributionSet> findDistributionSetAllById(final Collection<Long> ids) {
|
||||
public List<DistributionSet> findDistributionSetsById(final Collection<Long> ids) {
|
||||
return Collections.unmodifiableList(distributionSetRepository.findAll(ids));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSet> findDistributionSetsByTag(final Pageable pageable, final Long tagId) {
|
||||
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
|
||||
|
||||
return convertDsPage(distributionSetRepository.findByTag(pageable, tagId), pageable);
|
||||
|
||||
}
|
||||
|
||||
private void throwEntityNotFoundExceptionIfDsTagDoesNotExist(final Long tagId) {
|
||||
if (!distributionSetTagRepository.exists(tagId)) {
|
||||
throw new EntityNotFoundException(DistributionSetTag.class, tagId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSet> findDistributionSetsByTag(final Pageable pageable, final String rsqlParam,
|
||||
final Long tagId) {
|
||||
throwEntityNotFoundExceptionIfDsTagDoesNotExist(tagId);
|
||||
|
||||
final Specification<JpaDistributionSet> spec = RSQLUtility.parse(rsqlParam, DistributionSetFields.class,
|
||||
virtualPropertyReplacer);
|
||||
|
||||
return convertDsPage(distributionSetRepository.findAll((Specification<JpaDistributionSet>) (root, query,
|
||||
cb) -> cb.and(DistributionSetSpecification.hasTag(tagId).toPredicate(root, query, cb),
|
||||
spec.toPredicate(root, query, cb)),
|
||||
pageable), pageable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,6 +86,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
|
||||
@Override
|
||||
public Page<RolloutGroup> findRolloutGroupsByRolloutId(final Long rolloutId, final Pageable pageable) {
|
||||
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
|
||||
|
||||
return convertPage(rolloutGroupRepository.findByRolloutId(rolloutId, pageable), pageable);
|
||||
}
|
||||
|
||||
@@ -100,6 +102,7 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
@Override
|
||||
public Page<RolloutGroup> findRolloutGroupsAll(final Long rolloutId, final String rsqlParam,
|
||||
final Pageable pageable) {
|
||||
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
|
||||
|
||||
final Specification<JpaRolloutGroup> specification = RSQLUtility.parse(rsqlParam, RolloutGroupFields.class,
|
||||
virtualPropertyReplacer);
|
||||
@@ -115,11 +118,15 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RolloutGroup> findAllRolloutGroupsWithDetailedStatus(final Long rolloutId, final Pageable pageable) {
|
||||
private void throwEntityNotFoundExceptionIfRolloutDoesNotExist(final Long rolloutId) {
|
||||
if (!rolloutRepository.exists(rolloutId)) {
|
||||
throw new EntityNotFoundException(Rollout.class, rolloutId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RolloutGroup> findAllRolloutGroupsWithDetailedStatus(final Long rolloutId, final Pageable pageable) {
|
||||
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
|
||||
|
||||
final Page<JpaRolloutGroup> rolloutGroups = rolloutGroupRepository.findByRolloutId(rolloutId, pageable);
|
||||
final List<Long> rolloutGroupIds = rolloutGroups.getContent().stream().map(RolloutGroup::getId)
|
||||
@@ -173,6 +180,8 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
public Page<Target> findRolloutGroupTargets(final Long rolloutGroupId, final String rsqlParam,
|
||||
final Pageable pageable) {
|
||||
|
||||
throwExceptionIfRolloutGroupDoesNotExist(rolloutGroupId);
|
||||
|
||||
final Specification<JpaTarget> rsqlSpecification = RSQLUtility.parse(rsqlParam, TargetFields.class,
|
||||
virtualPropertyReplacer);
|
||||
|
||||
@@ -253,4 +262,11 @@ public class JpaRolloutGroupManagement implements RolloutGroupManagement {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countRolloutGroupsByRolloutId(final Long rolloutId) {
|
||||
throwEntityNotFoundExceptionIfRolloutDoesNotExist(rolloutId);
|
||||
|
||||
return rolloutGroupRepository.countByRolloutId(rolloutId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.eclipse.hawkbit.repository.AbstractRolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutFields;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutHelper;
|
||||
@@ -77,6 +78,8 @@ import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
@@ -129,6 +132,9 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Autowired
|
||||
private QuotaManagement quotaManagement;
|
||||
|
||||
JpaRolloutManagement(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
|
||||
final RolloutGroupManagement rolloutGroupManagement,
|
||||
final DistributionSetManagement distributionSetManagement, final ApplicationContext context,
|
||||
@@ -175,7 +181,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
@Transactional
|
||||
public Rollout createRollout(final RolloutCreate rollout, final int amountGroup,
|
||||
final RolloutGroupConditions conditions) {
|
||||
RolloutHelper.verifyRolloutGroupParameter(amountGroup);
|
||||
RolloutHelper.verifyRolloutGroupParameter(amountGroup, quotaManagement);
|
||||
final JpaRollout savedRollout = createRollout((JpaRollout) rollout.build());
|
||||
return createRolloutGroups(amountGroup, conditions, savedRollout);
|
||||
}
|
||||
@@ -184,7 +190,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
@Transactional
|
||||
public Rollout createRollout(final RolloutCreate rollout, final List<RolloutGroupCreate> groups,
|
||||
final RolloutGroupConditions conditions) {
|
||||
RolloutHelper.verifyRolloutGroupParameter(groups.size());
|
||||
RolloutHelper.verifyRolloutGroupParameter(groups.size(), quotaManagement);
|
||||
final JpaRollout savedRollout = createRollout((JpaRollout) rollout.build());
|
||||
return createRolloutGroups(groups, conditions, savedRollout);
|
||||
}
|
||||
@@ -297,7 +303,10 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
private void handleCreateRollout(final JpaRollout rollout) {
|
||||
LOGGER.debug("handleCreateRollout called for rollout {}", rollout.getId());
|
||||
|
||||
final List<RolloutGroup> rolloutGroups = RolloutHelper.getOrderedGroups(rollout);
|
||||
final List<RolloutGroup> rolloutGroups = rolloutGroupManagement.findRolloutGroupsByRolloutId(rollout.getId(),
|
||||
new PageRequest(0, quotaManagement.getMaxRolloutGroupsPerRollout(), new Sort(Direction.ASC, "id")))
|
||||
.getContent();
|
||||
|
||||
int readyGroups = 0;
|
||||
int totalTargets = 0;
|
||||
for (final RolloutGroup group : rolloutGroups) {
|
||||
@@ -325,7 +334,7 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
}
|
||||
|
||||
private RolloutGroup fillRolloutGroupWithTargets(final Rollout rollout, final RolloutGroup group1) {
|
||||
private RolloutGroup fillRolloutGroupWithTargets(final JpaRollout rollout, final RolloutGroup group1) {
|
||||
RolloutHelper.verifyRolloutInStatus(rollout, RolloutStatus.CREATING);
|
||||
|
||||
final JpaRolloutGroup group = (JpaRolloutGroup) group1;
|
||||
@@ -338,8 +347,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
groupTargetFilter = baseFilter + ";" + group.getTargetFilterQuery();
|
||||
}
|
||||
|
||||
final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout, RolloutGroupStatus.READY,
|
||||
group);
|
||||
final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(),
|
||||
RolloutGroupStatus.READY, group);
|
||||
|
||||
final long targetsInGroupFilter = runInNewTransaction("countAllTargetsByTargetFilterQueryAndNotInRolloutGroups",
|
||||
count -> targetManagement.countAllTargetsByTargetFilterQueryAndNotInRolloutGroups(readyGroups,
|
||||
@@ -376,12 +385,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
||||
}
|
||||
}
|
||||
|
||||
private Long assignTargetsToGroupInNewTransaction(final Rollout rollout, final RolloutGroup group,
|
||||
private Long assignTargetsToGroupInNewTransaction(final JpaRollout rollout, final RolloutGroup group,
|
||||
final String targetFilter, final long limit) {
|
||||
|
||||
return runInNewTransaction("assignTargetsToRolloutGroup", status -> {
|
||||
final PageRequest pageRequest = new PageRequest(0, Math.toIntExact(limit));
|
||||
final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout,
|
||||
final List<Long> readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(),
|
||||
RolloutGroupStatus.READY, group);
|
||||
final Page<Target> targets = targetManagement
|
||||
.findAllTargetsByTargetFilterQueryAndNotInRolloutGroups(pageRequest, readyGroups, targetFilter);
|
||||
|
||||
@@ -622,7 +622,7 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
||||
return convertSmMdPage(
|
||||
softwareModuleMetadataRepository
|
||||
.findAll(
|
||||
(Specification<JpaSoftwareModuleMetadata>) (root, query, cb) -> cb.and(
|
||||
(root, query, cb) -> cb.and(
|
||||
cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule)
|
||||
.get(JpaSoftwareModule_.id), softwareModuleId),
|
||||
spec.toPredicate(root, query, cb)),
|
||||
@@ -631,13 +631,13 @@ public class JpaSoftwareManagement implements SoftwareManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Long softwareModuleId) {
|
||||
public Page<SoftwareModuleMetadata> findSoftwareModuleMetadataBySoftwareModuleId(final Pageable pageable,
|
||||
final Long softwareModuleId) {
|
||||
throwExceptionIfSoftwareModuleDoesNotExist(softwareModuleId);
|
||||
|
||||
return Collections.unmodifiableList(softwareModuleMetadataRepository
|
||||
.findAll((Specification<JpaSoftwareModuleMetadata>) (root, query, cb) -> cb
|
||||
.and(cb.equal(root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id),
|
||||
softwareModuleId))));
|
||||
return convertSmMdPage(softwareModuleMetadataRepository.findAll((root, query, cb) -> cb.equal(
|
||||
root.get(JpaSoftwareModuleMetadata_.softwareModule).get(JpaSoftwareModule_.id), softwareModuleId),
|
||||
pageable), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
package org.eclipse.hawkbit.repository.jpa;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
@@ -32,6 +34,10 @@ import org.eclipse.persistence.config.PersistenceUnitProperties;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
@@ -47,6 +53,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
@Transactional(readOnly = true)
|
||||
@Validated
|
||||
public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement {
|
||||
private static final int MAX_TENANTS_QUERY = 500;
|
||||
|
||||
@Autowired
|
||||
private EntityManager entityManager;
|
||||
|
||||
@@ -135,7 +143,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
}
|
||||
|
||||
private void usageStatsPerTenant(final SystemUsageReport report) {
|
||||
final List<String> tenants = findTenants();
|
||||
final List<String> tenants = findTenants(new PageRequest(0, MAX_TENANTS_QUERY)).getContent();
|
||||
|
||||
tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> {
|
||||
report.addTenantData(systemStatsManagement.getStatsOfTenant());
|
||||
@@ -192,8 +200,13 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> findTenants() {
|
||||
return tenantMetaDataRepository.findAll().stream().map(TenantMetaData::getTenant).collect(Collectors.toList());
|
||||
public Page<String> findTenants(final Pageable pageable) {
|
||||
final Page<JpaTenantMetaData> result = tenantMetaDataRepository.findAll(pageable);
|
||||
|
||||
return new PageImpl<>(
|
||||
Collections.unmodifiableList(
|
||||
result.getContent().stream().map(TenantMetaData::getTenant).collect(Collectors.toList())),
|
||||
pageable, result.getTotalElements());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -271,4 +284,20 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
public TenantMetaData getTenantMetadata(final Long tenantId) {
|
||||
return tenantMetaDataRepository.findOne(tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
||||
public void forEachTenant(final Consumer<String> consumer) {
|
||||
|
||||
Page<String> tenants;
|
||||
Pageable query = new PageRequest(0, MAX_TENANTS_QUERY);
|
||||
do {
|
||||
tenants = findTenants(query);
|
||||
tenants.forEach(tenant -> tenantAware.runAsTenant(tenant, () -> {
|
||||
consumer.accept(tenant);
|
||||
return null;
|
||||
}));
|
||||
} while (tenants.hasNext() && (query = tenants.nextPageable()) != null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.RSQLUtility;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.TagSpecification;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -85,17 +87,12 @@ public class JpaTagManagement implements TagManagement {
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteTargetTag(final String targetTagName) {
|
||||
final TargetTag tag = targetTagRepository.findByNameEquals(targetTagName)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagName));
|
||||
|
||||
targetRepository.findByTag(tag.getId()).forEach(set -> {
|
||||
set.removeTag(tag);
|
||||
targetRepository.save(set);
|
||||
});
|
||||
if (!targetTagRepository.existsByName(targetTagName)) {
|
||||
throw new EntityNotFoundException(TargetTag.class, targetTagName);
|
||||
}
|
||||
|
||||
// finally delete the tag itself
|
||||
targetTagRepository.deleteByName(targetTagName);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,22 +174,13 @@ public class JpaTagManagement implements TagManagement {
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteDistributionSetTag(final String tagName) {
|
||||
final DistributionSetTag tag = distributionSetTagRepository.findByNameEquals(tagName)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName));
|
||||
|
||||
distributionSetRepository.findByTag(tag).forEach(set -> {
|
||||
set.removeTag(tag);
|
||||
distributionSetRepository.save(set);
|
||||
});
|
||||
if (!distributionSetTagRepository.existsByName(tagName)) {
|
||||
throw new EntityNotFoundException(DistributionSetTag.class, tagName);
|
||||
}
|
||||
|
||||
distributionSetTagRepository.deleteByName(tagName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DistributionSetTag> findAllDistributionSetTags() {
|
||||
return Collections.unmodifiableList(distributionSetTagRepository.findAll());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<TargetTag> findTargetTagById(final Long id) {
|
||||
return Optional.ofNullable(targetTagRepository.findOne(id));
|
||||
@@ -223,7 +211,21 @@ public class JpaTagManagement implements TagManagement {
|
||||
|
||||
@Override
|
||||
public Page<TargetTag> findAllTargetTags(final Pageable pageable, final String controllerId) {
|
||||
if (!targetRepository.existsByControllerId(controllerId)) {
|
||||
throw new EntityNotFoundException(Target.class, controllerId);
|
||||
}
|
||||
|
||||
return convertTPage(targetTagRepository.findAll(TagSpecification.ofTarget(controllerId), pageable), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetTag> findDistributionSetTagsByDistributionSet(final Pageable pageable,
|
||||
final Long setId) {
|
||||
if (!distributionSetRepository.exists(setId)) {
|
||||
throw new EntityNotFoundException(DistributionSet.class, setId);
|
||||
}
|
||||
|
||||
return convertDsPage(distributionSetTagRepository.findAll(TagSpecification.ofDistributionSet(setId), pageable),
|
||||
pageable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Target> findTargetByControllerID(final Collection<String> controllerIDs) {
|
||||
public List<Target> findTargetsByControllerID(final Collection<String> controllerIDs) {
|
||||
return Collections.unmodifiableList(
|
||||
targetRepository.findAll(TargetSpecifications.byControllerIdWithAssignedDsInJoin(controllerIDs)));
|
||||
}
|
||||
@@ -376,41 +376,18 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
.unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private List<Target> unAssignTag(final Collection<Target> targets, final TargetTag tag) {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
final Collection<JpaTarget> toUnassign = (Collection) targets;
|
||||
|
||||
toUnassign.forEach(target -> target.removeTag(tag));
|
||||
|
||||
return Collections
|
||||
.unmodifiableList(toUnassign.stream().map(targetRepository::save).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public List<Target> unAssignAllTargetsByTag(final Long targetTagId) {
|
||||
|
||||
final TargetTag tag = targetTagRepository.findById(targetTagId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId));
|
||||
|
||||
if (tag.getAssignedToTargets().isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return unAssignTag(tag.getAssignedToTargets(), tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Target unAssignTag(final String controllerID, final Long targetTagId) {
|
||||
final Target target = targetRepository.findByControllerId(controllerID)
|
||||
final JpaTarget target = (JpaTarget) targetRepository.findByControllerId(controllerID)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerID));
|
||||
|
||||
final TargetTag tag = targetTagRepository.findById(targetTagId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId));
|
||||
|
||||
final List<Target> unAssignTag = unAssignTag(Lists.newArrayList(target), tag);
|
||||
return unAssignTag.isEmpty() ? null : unAssignTag.get(0);
|
||||
target.removeTag(tag);
|
||||
|
||||
return targetRepository.save(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -559,13 +536,28 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Target> findTargetsByTag(final String tagName) {
|
||||
final Optional<TargetTag> tag = targetTagRepository.findByNameEquals(tagName);
|
||||
if (!tag.isPresent()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
public Page<Target> findTargetsByTag(final Pageable pageable, final Long tagId) {
|
||||
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
|
||||
|
||||
return Collections.unmodifiableList(targetRepository.findByTag(tag.get().getId()));
|
||||
return convertPage(targetRepository.findByTag(pageable, tagId), pageable);
|
||||
}
|
||||
|
||||
private void throwEntityNotFoundExceptionIfTagDoesNotExist(final Long tagId) {
|
||||
if (!targetTagRepository.exists(tagId)) {
|
||||
throw new EntityNotFoundException(TargetTag.class, tagId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Target> findTargetsByTag(final Pageable pageable, final String rsqlParam, final Long tagId) {
|
||||
|
||||
throwEntityNotFoundExceptionIfTagDoesNotExist(tagId);
|
||||
|
||||
final Specification<JpaTarget> spec = RSQLUtility.parse(rsqlParam, TargetFields.class, virtualPropertyReplacer);
|
||||
|
||||
return convertPage(targetRepository.findAll((Specification<JpaTarget>) (root, query, cb) -> cb.and(
|
||||
TargetSpecifications.hasTag(tagId).toPredicate(root, query, cb), spec.toPredicate(root, query, cb)),
|
||||
pageable), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -594,7 +586,7 @@ public class JpaTargetManagement implements TargetManagement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Target> findTargetAllById(final Collection<Long> ids) {
|
||||
public List<Target> findTargetsById(final Collection<Long> ids) {
|
||||
return Collections.unmodifiableList(targetRepository.findAll(ids));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||
import org.eclipse.hawkbit.repository.PropertiesQuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TagManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
@@ -63,6 +64,7 @@ import org.eclipse.hawkbit.repository.model.helper.SystemManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
|
||||
import org.eclipse.hawkbit.repository.rsql.RsqlValidationOracle;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
@@ -123,6 +125,11 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
return new RsqlParserValidationOracle();
|
||||
}
|
||||
|
||||
@Bean
|
||||
PropertiesQuotaManagement staticQuotaManagement(final HawkbitSecurityProperties securityProperties) {
|
||||
return new PropertiesQuotaManagement(securityProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param distributionSetManagement
|
||||
* to loading the {@link DistributionSetType}
|
||||
@@ -557,8 +564,7 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
AutoAssignScheduler autoAssignScheduler(final TenantAware tenantAware, final SystemManagement systemManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final AutoAssignChecker autoAssignChecker,
|
||||
final LockRegistry lockRegistry) {
|
||||
return new AutoAssignScheduler(tenantAware, systemManagement, systemSecurityContext, autoAssignChecker,
|
||||
lockRegistry);
|
||||
return new AutoAssignScheduler(systemManagement, systemSecurityContext, autoAssignChecker, lockRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -567,8 +573,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
* Note: does not activate in test profile, otherwise it is hard to test the
|
||||
* rollout handling functionality.
|
||||
*
|
||||
* @param tenantAware
|
||||
* to run as specific tenant
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param rolloutManagement
|
||||
@@ -583,6 +587,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
|
||||
@ConditionalOnProperty(prefix = "hawkbit.rollout.scheduler", name = "enabled", matchIfMissing = true)
|
||||
RolloutScheduler rolloutScheduler(final TenantAware tenantAware, final SystemManagement systemManagement,
|
||||
final RolloutManagement rolloutManagement, final SystemSecurityContext systemSecurityContext) {
|
||||
return new RolloutScheduler(tenantAware, systemManagement, rolloutManagement, systemSecurityContext);
|
||||
return new RolloutScheduler(systemManagement, rolloutManagement, systemSecurityContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +146,16 @@ public interface RolloutGroupRepository
|
||||
*/
|
||||
Page<JpaRolloutGroup> findByRolloutId(final Long rolloutId, Pageable page);
|
||||
|
||||
/**
|
||||
* 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(final Long rolloutId);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM JpaRolloutGroup g where g.id in :rolloutGroupIds")
|
||||
void deleteByIds(@Param("rolloutGroupIds") List<Long> rolloutGroups);
|
||||
|
||||
@@ -94,13 +94,16 @@ public interface TargetRepository extends BaseEntityRepository<JpaTarget, Long>,
|
||||
|
||||
/**
|
||||
* Finds {@link Target}s by assigned {@link Tag}.
|
||||
*
|
||||
* @param page
|
||||
* pages query and sorting information
|
||||
*
|
||||
* @param tagId
|
||||
* to be found
|
||||
* @return list of found targets
|
||||
* @return page of found targets
|
||||
*/
|
||||
@Query(value = "SELECT DISTINCT t FROM JpaTarget t JOIN t.tags tt WHERE tt.id = :tag")
|
||||
List<JpaTarget> findByTag(@Param("tag") final Long tagId);
|
||||
Page<JpaTarget> findByTag(Pageable page, @Param("tag") final Long tagId);
|
||||
|
||||
/**
|
||||
* Finds all {@link Target}s based on given {@link Target#getControllerId()}
|
||||
|
||||
@@ -50,6 +50,16 @@ public interface TargetTagRepository
|
||||
*/
|
||||
Optional<TargetTag> findByNameEquals(String tagName);
|
||||
|
||||
/**
|
||||
* Checks if tag with given name exists.
|
||||
*
|
||||
* @param tagName
|
||||
* to check for
|
||||
* @return <code>true</code> is tag with given name exists
|
||||
*/
|
||||
@Query("SELECT CASE WHEN COUNT(t)>0 THEN 'true' ELSE 'false' END FROM JpaTargetTag t WHERE t.name=:tagName")
|
||||
boolean existsByName(@Param("tagName") String tagName);
|
||||
|
||||
/**
|
||||
* Returns all instances of the type.
|
||||
*
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
package org.eclipse.hawkbit.repository.jpa.aspects;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,16 +24,17 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
|
||||
import org.springframework.orm.jpa.JpaSystemException;
|
||||
import org.springframework.orm.jpa.JpaVendorAdapter;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
@@ -54,8 +54,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
||||
* most specific mappable exception according to the type hierarchy of the
|
||||
* exception.
|
||||
*/
|
||||
private static final List<Class<?>> MAPPED_EXCEPTION_ORDER = new ArrayList<>(4);
|
||||
|
||||
private static final List<Class<?>> MAPPED_EXCEPTION_ORDER = Lists.newArrayListWithExpectedSize(4);
|
||||
@Autowired
|
||||
private JpaVendorAdapter jpaVendorAdapter;
|
||||
|
||||
@@ -65,14 +64,14 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
||||
|
||||
MAPPED_EXCEPTION_ORDER.add(DuplicateKeyException.class);
|
||||
MAPPED_EXCEPTION_ORDER.add(DataIntegrityViolationException.class);
|
||||
MAPPED_EXCEPTION_ORDER.add(ConcurrencyFailureException.class);
|
||||
MAPPED_EXCEPTION_ORDER.add(OptimisticLockingFailureException.class);
|
||||
MAPPED_EXCEPTION_ORDER.add(AccessDeniedException.class);
|
||||
|
||||
EXCEPTION_MAPPING.put(DuplicateKeyException.class.getName(), EntityAlreadyExistsException.class.getName());
|
||||
EXCEPTION_MAPPING.put(DataIntegrityViolationException.class.getName(),
|
||||
EntityAlreadyExistsException.class.getName());
|
||||
|
||||
EXCEPTION_MAPPING.put(ConcurrencyFailureException.class.getName(),
|
||||
EXCEPTION_MAPPING.put(OptimisticLockingFailureException.class.getName(),
|
||||
ConcurrentModificationException.class.getName());
|
||||
EXCEPTION_MAPPING.put(AccessDeniedException.class.getName(), InsufficientPermissionException.class.getName());
|
||||
}
|
||||
@@ -86,10 +85,7 @@ public class ExceptionMappingAspectHandler implements Ordered {
|
||||
* @throws Throwable
|
||||
*/
|
||||
@AfterThrowing(pointcut = "( execution( * org.springframework.transaction..*.*(..)) "
|
||||
+ " || execution( * org.eclipse.hawkbit.repository.*.*(..)) "
|
||||
+ " || execution( * org.eclipse.hawkbit.controller.*.*(..)) "
|
||||
+ " || execution( * org.eclipse.hawkbit.rest.resource.*.*(..)) "
|
||||
+ " || execution( * org.eclipse.hawkbit.service.*.*(..)) )", throwing = "ex")
|
||||
+ " || execution( * org.eclipse.hawkbit.repository.*.*(..)) )", throwing = "ex")
|
||||
// Exception for squid:S00112, squid:S1162
|
||||
// It is a AspectJ proxy which deals with exceptions.
|
||||
@SuppressWarnings({ "squid:S00112", "squid:S1162" })
|
||||
|
||||
@@ -8,12 +8,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.autoassign;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
@@ -27,8 +25,6 @@ public class AutoAssignScheduler {
|
||||
|
||||
private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.autoassign.scheduler.fixedDelay:2000}";
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
private final SystemManagement systemManagement;
|
||||
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
@@ -40,8 +36,6 @@ public class AutoAssignScheduler {
|
||||
/**
|
||||
* Instantiates a new AutoAssignScheduler
|
||||
*
|
||||
* @param tenantAware
|
||||
* to run as specific tenant
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param systemSecurityContext
|
||||
@@ -51,10 +45,9 @@ public class AutoAssignScheduler {
|
||||
* @param lockRegistry
|
||||
* to acquire a lock per tenant
|
||||
*/
|
||||
public AutoAssignScheduler(final TenantAware tenantAware, final SystemManagement systemManagement,
|
||||
public AutoAssignScheduler(final SystemManagement systemManagement,
|
||||
final SystemSecurityContext systemSecurityContext, final AutoAssignChecker autoAssignChecker,
|
||||
final LockRegistry lockRegistry) {
|
||||
this.tenantAware = tenantAware;
|
||||
this.systemManagement = systemManagement;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
this.autoAssignChecker = autoAssignChecker;
|
||||
@@ -82,24 +75,17 @@ public class AutoAssignScheduler {
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458. So
|
||||
// iterate through all tenants and execute the rollout check for
|
||||
// each tenant separately.
|
||||
final List<String> tenants = systemManagement.findTenants();
|
||||
LOGGER.info("Checking target filter queries for tenants: {}", tenants.size());
|
||||
|
||||
final Lock lock = lockRegistry.obtain("autoassign");
|
||||
if (!lock.tryLock()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
for (final String tenant : tenants) {
|
||||
tenantAware.runAsTenant(tenant, () -> {
|
||||
autoAssignChecker.check();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
systemManagement.forEachTenant(tenant -> autoAssignChecker.check());
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,6 @@ public class JpaAction extends AbstractJpaTenantAwareBaseEntity implements Actio
|
||||
return actionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActionStatus> getActionStatus() {
|
||||
if (actionStatus == null) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -142,7 +142,6 @@ public class JpaActionStatus extends AbstractJpaTenantAwareBaseEntity implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMessages() {
|
||||
if (messages == null) {
|
||||
messages = Collections.emptyList();
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations 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.model;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
|
||||
|
||||
/**
|
||||
* Custom JPA Model for querying {@link Action} include the count of the
|
||||
* action's {@link ActionStatus}.
|
||||
*
|
||||
*/
|
||||
public class JpaActionWithStatusCount implements ActionWithStatusCount {
|
||||
private final Long actionStatusCount;
|
||||
private final Long dsId;
|
||||
private final String dsName;
|
||||
private final String dsVersion;
|
||||
private final JpaAction action;
|
||||
private final String rolloutName;
|
||||
|
||||
/**
|
||||
* JPA constructor, the parameter are the result set columns of the custom
|
||||
* query.
|
||||
*
|
||||
* @param actionId
|
||||
* the ID of the action
|
||||
* @param actionType
|
||||
* the action type
|
||||
* @param active
|
||||
* the active attribute of the action
|
||||
* @param forcedTime
|
||||
* the forced time attribute of the action
|
||||
* @param status
|
||||
* the status attribute of the action
|
||||
* @param actionCreatedAt
|
||||
* the createdAt timestamp of the action
|
||||
* @param actionLastModifiedAt
|
||||
* the last modified timestamp of the action
|
||||
* @param dsId
|
||||
* the ID of the distributionset
|
||||
* @param dsName
|
||||
* the name of the distributionset
|
||||
* @param dsVersion
|
||||
* the version of the distributionset
|
||||
* @param actionStatusCount
|
||||
* the count of the action status for this action
|
||||
* @param rolloutName
|
||||
* the rollout name
|
||||
*/
|
||||
// Exception squid:S00107 - needed this way for JPA to fill the view
|
||||
@SuppressWarnings("squid:S00107")
|
||||
public JpaActionWithStatusCount(final Long actionId, final ActionType actionType, final boolean active,
|
||||
final Long forcedTime, final Status status, final Long actionCreatedAt, final Long actionLastModifiedAt,
|
||||
final Long dsId, final String dsName, final String dsVersion, final Long actionStatusCount,
|
||||
final String rolloutName) {
|
||||
this.dsId = dsId;
|
||||
this.dsName = dsName;
|
||||
this.dsVersion = dsVersion;
|
||||
this.actionStatusCount = actionStatusCount;
|
||||
this.rolloutName = rolloutName;
|
||||
|
||||
action = new JpaAction();
|
||||
action.setActionType(actionType);
|
||||
action.setActive(active);
|
||||
action.setForcedTime(forcedTime);
|
||||
action.setStatus(status);
|
||||
action.setId(actionId);
|
||||
action.setActionType(actionType);
|
||||
action.setCreatedAt(actionCreatedAt);
|
||||
action.setLastModifiedAt(actionLastModifiedAt);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getDsId() {
|
||||
return dsId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDsName() {
|
||||
return dsName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDsVersion() {
|
||||
return dsVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getActionStatusCount() {
|
||||
return actionStatusCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRolloutName() {
|
||||
return rolloutName;
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.repository.event.remote.DistributionSetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
@@ -174,7 +174,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
this(name, version, description, type, moduleList, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<DistributionSetTag> getTags() {
|
||||
if (tags == null) {
|
||||
return Collections.emptySet();
|
||||
@@ -339,7 +338,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
|
||||
publishEventWithEventPublisher(
|
||||
new DistributionSetUpdateEvent(this, EventPublisherHolder.getInstance().getApplicationId()));
|
||||
new DistributionSetUpdatedEvent(this, EventPublisherHolder.getInstance().getApplicationId()));
|
||||
|
||||
if (isSoftDeleted(descriptorEvent)) {
|
||||
publishEventWithEventPublisher(new DistributionSetDeletedEvent(getTenant(), getId(), getClass().getName(),
|
||||
|
||||
@@ -20,7 +20,7 @@ import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.event.remote.DistributionSetTagDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTagUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||
@@ -64,7 +64,6 @@ public class JpaDistributionSetTag extends JpaTag implements DistributionSetTag,
|
||||
// Default constructor for JPA.
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DistributionSet> getAssignedToDistributionSet() {
|
||||
if (assignedToDistributionSet == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -82,7 +81,7 @@ public class JpaDistributionSetTag extends JpaTag implements DistributionSetTag,
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventPublisherHolder.getInstance().getEventPublisher().publishEvent(
|
||||
new DistributionSetTagUpdateEvent(this, EventPublisherHolder.getInstance().getApplicationId()));
|
||||
new DistributionSetTagUpdatedEvent(this, EventPublisherHolder.getInstance().getApplicationId()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,6 @@ public class JpaRollout extends AbstractJpaNamedEntity implements Rollout, Event
|
||||
this.distributionSet = (JpaDistributionSet) distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RolloutGroup> getRolloutGroups() {
|
||||
if (rolloutGroups == null) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -20,7 +20,7 @@ import javax.persistence.UniqueConstraint;
|
||||
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetTagDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagUpdateEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||
@@ -61,7 +61,6 @@ public class JpaTargetTag extends JpaTag implements TargetTag, EventAwareEntity
|
||||
// Default constructor for JPA.
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Target> getAssignedToTargets() {
|
||||
if (assignedToTargets == null) {
|
||||
return Collections.emptyList();
|
||||
@@ -80,7 +79,7 @@ public class JpaTargetTag extends JpaTag implements TargetTag, EventAwareEntity
|
||||
@Override
|
||||
public void fireUpdateEvent(final DescriptorEvent descriptorEvent) {
|
||||
EventPublisherHolder.getInstance().getEventPublisher()
|
||||
.publishEvent(new TargetTagUpdateEvent(this, EventPublisherHolder.getInstance().getApplicationId()));
|
||||
.publishEvent(new TargetTagUpdatedEvent(this, EventPublisherHolder.getInstance().getApplicationId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,12 +8,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rollout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
@@ -29,8 +26,6 @@ public class RolloutScheduler {
|
||||
|
||||
private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.rollout.scheduler.fixedDelay:2000}";
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
private final SystemManagement systemManagement;
|
||||
|
||||
private final RolloutManagement rolloutManagement;
|
||||
@@ -40,8 +35,6 @@ public class RolloutScheduler {
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenantAware
|
||||
* to run as specific tenant
|
||||
* @param systemManagement
|
||||
* to find all tenants
|
||||
* @param rolloutManagement
|
||||
@@ -49,9 +42,8 @@ public class RolloutScheduler {
|
||||
* @param systemSecurityContext
|
||||
* to run as system
|
||||
*/
|
||||
public RolloutScheduler(final TenantAware tenantAware, final SystemManagement systemManagement,
|
||||
final RolloutManagement rolloutManagement, final SystemSecurityContext systemSecurityContext) {
|
||||
this.tenantAware = tenantAware;
|
||||
public RolloutScheduler(final SystemManagement systemManagement, final RolloutManagement rolloutManagement,
|
||||
final SystemSecurityContext systemSecurityContext) {
|
||||
this.systemManagement = systemManagement;
|
||||
this.rolloutManagement = rolloutManagement;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
@@ -76,22 +68,9 @@ public class RolloutScheduler {
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458. So
|
||||
// iterate through all tenants and execute the rollout check for
|
||||
// each tenant seperately.
|
||||
final List<String> tenants = systemManagement.findTenants();
|
||||
LOGGER.info("Checking rollouts for {} tenants", tenants.size());
|
||||
for (final String tenant : tenants) {
|
||||
tenantAware.runAsTenant(tenant, () -> {
|
||||
try {
|
||||
rolloutManagement.handleRollouts();
|
||||
// We catch all potential runtime exceptions here to
|
||||
// ensure that not all tenants are blocked if we have a
|
||||
// problem with a rollout.
|
||||
} catch (@SuppressWarnings("squid:S1166") final RuntimeException e) {
|
||||
LOGGER.error("Failed to handle rollouts for tenant {}. I will move on to next tenant.", tenant,
|
||||
e);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
systemManagement.forEachTenant(tenant -> rolloutManagement.handleRollouts());
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ public final class DistributionSetSpecification {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaDistributionSet_.id), distid);
|
||||
targetRoot.fetch(JpaDistributionSet_.modules, JoinType.LEFT);
|
||||
targetRoot.fetch(JpaDistributionSet_.tags, JoinType.LEFT);
|
||||
targetRoot.fetch(JpaDistributionSet_.type, JoinType.LEFT);
|
||||
query.distinct(true);
|
||||
|
||||
@@ -218,4 +217,20 @@ public final class DistributionSetSpecification {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by tag.
|
||||
*
|
||||
* @param tagId
|
||||
* the ID of the distribution set which must be assigned
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSet> hasTag(final Long tagId) {
|
||||
|
||||
return (targetRoot, query, cb) -> {
|
||||
final SetJoin<JpaDistributionSet, JpaDistributionSetTag> tags = targetRoot.join(JpaDistributionSet_.tags,
|
||||
JoinType.LEFT);
|
||||
return cb.equal(tags.get(JpaDistributionSetTag_.id), tagId);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.specifications;
|
||||
|
||||
import javax.persistence.criteria.JoinType;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType_;
|
||||
@@ -28,24 +25,6 @@ public final class SoftwareModuleSpecification {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by its ID
|
||||
* attribute.
|
||||
*
|
||||
* @param moduleId
|
||||
* to search for
|
||||
* @return the {@link SoftwareModule} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaSoftwareModule> byId(final Long moduleId) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final Predicate predicate = cb.equal(targetRoot.<Long> get(JpaSoftwareModule_.id), moduleId);
|
||||
targetRoot.fetch(JpaSoftwareModule_.type);
|
||||
targetRoot.fetch(JpaSoftwareModule_.metadata, JoinType.LEFT);
|
||||
query.distinct(true);
|
||||
return predicate;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s where its
|
||||
* DELETED attribute is false.
|
||||
@@ -57,8 +36,8 @@ public final class SoftwareModuleSpecification {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by
|
||||
* "like name or like version".
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by "like
|
||||
* name or like version".
|
||||
*
|
||||
* @param subString
|
||||
* to be filtered on
|
||||
@@ -71,8 +50,8 @@ public final class SoftwareModuleSpecification {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by
|
||||
* "like name or like version".
|
||||
* {@link Specification} for retrieving {@link SoftwareModule}s by "like
|
||||
* name or like version".
|
||||
*
|
||||
* @param type
|
||||
* to be filtered on
|
||||
|
||||
@@ -10,11 +10,18 @@ package org.eclipse.hawkbit.repository.jpa.specifications;
|
||||
|
||||
import javax.persistence.criteria.Join;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
/**
|
||||
@@ -28,13 +35,13 @@ public final class TagSpecification {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSet}s by its
|
||||
* DELETED attribute.
|
||||
* {@link Specification} for retrieving {@link TargetTag}s by assigned
|
||||
* {@link Target}.
|
||||
*
|
||||
* @param isDeleted
|
||||
* TRUE/FALSE are compared to the attribute DELETED. If NULL the
|
||||
* attribute is ignored
|
||||
* @return the {@link DistributionSet} {@link Specification}
|
||||
* @param controllerId
|
||||
* of the target
|
||||
*
|
||||
* @return the {@link JpaTargetTag} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTargetTag> ofTarget(final String controllerId) {
|
||||
return (targetRoot, query, criteriaBuilder) -> {
|
||||
@@ -47,4 +54,25 @@ public final class TagSpecification {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link DistributionSetTag}s by
|
||||
* assigned {@link DistributionSet}.
|
||||
*
|
||||
* @param dsId
|
||||
* of the distribution set
|
||||
*
|
||||
* @return the {@link JpaDistributionSetTag} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaDistributionSetTag> ofDistributionSet(final Long dsId) {
|
||||
return (dsRoot, query, criteriaBuilder) -> {
|
||||
final Join<JpaDistributionSetTag, JpaDistributionSet> tagJoin = dsRoot
|
||||
.join(JpaDistributionSetTag_.assignedToDistributionSet);
|
||||
|
||||
query.distinct(true);
|
||||
|
||||
return criteriaBuilder.equal(tagJoin.get(JpaDistributionSet_.id), dsId);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -287,4 +287,19 @@ public final class TargetSpecifications {
|
||||
return (targetRoot, query, cb) -> cb.equal(
|
||||
targetRoot.get(JpaTarget_.installedDistributionSet).get(JpaDistributionSet_.id), distributionSetId);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s by tag.
|
||||
*
|
||||
* @param tagId
|
||||
* the ID of the distribution set which must be assigned
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> hasTag(final Long tagId) {
|
||||
|
||||
return (targetRoot, query, cb) -> {
|
||||
final SetJoin<JpaTarget, JpaTargetTag> tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT);
|
||||
return cb.equal(tags.get(JpaTargetTag_.id), tagId);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user