Feature target type filter (#1197)

* Added Target type filter with drag and drop support

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Removed the unused enums and target type filter button class

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Resolved merge conflicts

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed java doc issue with the method link in the comment

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed the IN query overflow for target Type assignment

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>

* Fixed Review comments

Signed-off-by: Anand kumar <anand.kumar@bosch-si.com>
This commit is contained in:
Anand Kumar
2021-10-27 15:24:09 +02:00
committed by GitHub
parent dea6fa3ce6
commit 70779d1ac7
38 changed files with 1409 additions and 398 deletions

View File

@@ -27,9 +27,11 @@ public class FilterParams {
private final Boolean selectTargetWithNoTag;
private final String[] filterByTagNames;
private final Long filterByDistributionId;
private final Boolean selectTargetWithNoTargetType;
private final Long filterByTargetType;
/**
* Constructor.
* Constructor for the filter parameters of a Simple Filter.
*
* @param filterByInstalledOrAssignedDistributionSetId
* if set, a filter is added for the given
@@ -56,6 +58,34 @@ public class FilterParams {
this.filterByDistributionId = filterByInstalledOrAssignedDistributionSetId;
this.selectTargetWithNoTag = selectTargetWithNoTag;
this.filterByTagNames = filterByTagNames;
this.selectTargetWithNoTargetType = false;
this.filterByTargetType = null;
}
/**
* Constructor for the filter parameters of a Type Filter.
*
* @param filterBySearchText
* if set, a filter is added for the given search text
* @param filterByInstalledOrAssignedDistributionSetId
* if set, a filter is added for the given
* {@link DistributionSet#getId()}
* @param selectTargetWithNoType
* if true, a filter is added with no type
* @param filterByType
* if set, a filter is added for the given target type
*/
public FilterParams(final String filterBySearchText, final Long filterByInstalledOrAssignedDistributionSetId,
final Boolean selectTargetWithNoType, final Long filterByType) {
this.filterBySearchText = filterBySearchText;
this.filterByDistributionId = filterByInstalledOrAssignedDistributionSetId;
this.filterByStatus = null;
this.overdueState = null;
this.selectTargetWithNoTag = false;
this.filterByTagNames = null;
this.selectTargetWithNoTargetType = selectTargetWithNoType;
this.filterByTargetType = filterByType;
}
/**
@@ -120,4 +150,23 @@ public class FilterParams {
public String[] getFilterByTagNames() {
return filterByTagNames;
}
/**
* Gets the flag indicating if no target type filter is used. <br>
* If set to <code>false</code> this filter is disabled.
*
* @return the flag indicating if no target type filter is used
*/
public Boolean getSelectTargetWithNoTargetType() {
return selectTargetWithNoTargetType;
}
/**
* Gets the target type
*
* @return the target type that are used to filter for
*/
public Long getFilterByTargetType() {
return filterByTargetType;
}
}

View File

@@ -8,14 +8,6 @@
*/
package org.eclipse.hawkbit.repository;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.validation.ConstraintViolationException;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TargetCreate;
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
@@ -35,12 +27,22 @@ import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.security.access.prepost.PreAuthorize;
import javax.validation.ConstraintViolationException;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* Management service for {@link Target}s.
*
@@ -106,11 +108,29 @@ public interface TargetManagement {
*
* @throws EntityNotFoundException
* if distribution set with given ID does not exist
*
* @deprecated this method {@link TargetManagement#countByFilters(FilterParams)} should be used instead.
*/
@Deprecated
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long countByFilters(Collection<TargetUpdateStatus> status, Boolean overdueState, String searchText,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag, String... tagNames);
/**
* Count {@link Target}s for all the given filter parameters.
*
* @param filterParams
* the filters to apply; only filters are enabled that have
* non-null value; filters are AND-gated
*
* @return the found number {@link Target}s
*
* @throws EntityNotFoundException
* if distribution set with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
long countByFilters(@NotNull final FilterParams filterParams);
/**
* Counts number of targets with given with given distribution set Id
*
@@ -607,6 +627,38 @@ public interface TargetManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetTagAssignmentResult toggleTagAssignment(@NotEmpty Collection<String> controllerIds, @NotEmpty String tagName);
/**
* Initiates {@link TargetType} assignment to given {@link Target}s. If some
* targets in the list have the {@link TargetType} not yet assigned, they will
* get assigned. If all targets are already of that type, there will be no
* un-assignment.
*
* @param controllerIds
* to set the type to
* @param typeId
* to assign targets to
* @return {@link TargetTypeAssignmentResult} with all meta data of the
* assignment outcome.
*
* @throws EntityNotFoundException
* if target type with given id does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetTypeAssignmentResult assignType(@NotEmpty Collection<String> controllerIds, @NotNull Long typeId);
/**
* Initiates {@link TargetType} un-assignment to given {@link Target}s. The type
* of the targets will be set to {@code null}
*
* @param controllerIds
* to remove the type from
* @return {@link TargetTypeAssignmentResult} with all meta data of the
* assignment outcome.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
TargetTypeAssignmentResult unAssignType(@NotEmpty Collection<String> controllerIds);
/**
* Un-assign a {@link TargetTag} assignment to given {@link Target}.
*
@@ -638,6 +690,8 @@ public interface TargetManagement {
*
* @param controllerID
* to un-assign for
* @param targetTypeId
* Target type id
* @return the unassigned target
*
* @throws EntityNotFoundException
@@ -854,4 +908,5 @@ public interface TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
TargetMetadata updateMetadata(@NotEmpty String controllerId, @NotNull MetaData metadata);
}

View File

@@ -0,0 +1,42 @@
/**
* 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.model;
import java.util.List;
/**
* Result object for {@link TargetType} assignments.
*
*/
public class TargetTypeAssignmentResult extends AbstractAssignmentResult<Target> {
private final TargetType targetType;
/**
* Constructor.
*
* @param alreadyAssigned
* count of already assigned (ignored) elements
* @param assigned
* {@link List} of assigned {@link Target}s.
* @param unassigned
* {@link List} of unassigned {@link Target}s.
* @param targetType
* the assigned or unassigned tag
*/
public TargetTypeAssignmentResult(final int alreadyAssigned, final List<? extends Target> assigned,
final List<? extends Target> unassigned, final TargetType targetType) {
super(alreadyAssigned, assigned, unassigned);
this.targetType = targetType;
}
public TargetType getTargetType() {
return targetType;
}
}

View File

@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetFilterQueryDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetTagDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetTypeDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.TenantConfigurationDeletedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
@@ -53,6 +54,8 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryCreat
import org.eclipse.hawkbit.repository.event.remote.entity.TargetFilterQueryUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationUpdatedEvent;
@@ -150,6 +153,11 @@ public class EventType {
// rollout stopped due to invalidated distribution set
TYPES.put(43, RolloutStoppedEvent.class);
// target type
TYPES.put(44, TargetTypeCreatedEvent.class);
TYPES.put(45, TargetTypeUpdatedEvent.class);
TYPES.put(46, TargetTypeDeletedEvent.class);
}
private int value;

View File

@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository.jpa;
import static org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications.orderedByLinkedDistributionSet;
import com.google.common.collect.Lists;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
@@ -65,6 +66,7 @@ import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
@@ -449,11 +451,16 @@ public class JpaTargetManagement implements TargetManagement {
}
@Override
public long countByFilters(final Collection<TargetUpdateStatus> status, final Boolean overdueState,
final String searchText, final Long installedOrAssignedDistributionSetId,
final Boolean selectTargetWithNoTag, final String... tagNames) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(new FilterParams(status, overdueState,
searchText, installedOrAssignedDistributionSetId, selectTargetWithNoTag, tagNames));
public long countByFilters(Collection<TargetUpdateStatus> status, Boolean overdueState, String searchText,
Long installedOrAssignedDistributionSetId, Boolean selectTargetWithNoTag,
String... tagNames) {
return countByFilters(new FilterParams(status, overdueState, searchText, installedOrAssignedDistributionSetId,
selectTargetWithNoTag, tagNames));
}
@Override
public long countByFilters(final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
return countByCriteriaAPI(specList);
}
@@ -479,6 +486,13 @@ public class JpaTargetManagement implements TargetManagement {
specList.add(TargetSpecifications.hasTags(filterParams.getFilterByTagNames(),
filterParams.getSelectTargetWithNoTag()));
}
if (hasTypesFilterActive(filterParams)) {
specList.add(TargetSpecifications.hasTargetType(filterParams.getFilterByTargetType()));
} else if (hasNoTypeFilterActive(filterParams)) {
specList.add(TargetSpecifications.hasNoTargetType());
}
return specList;
}
@@ -490,6 +504,14 @@ public class JpaTargetManagement implements TargetManagement {
return isNoTagActive || isAtLeastOneTagActive;
}
private static boolean hasTypesFilterActive(final FilterParams filterParams) {
return filterParams.getFilterByTargetType() != null;
}
private static boolean hasNoTypeFilterActive(final FilterParams filterParams) {
return Boolean.TRUE.equals(filterParams.getSelectTargetWithNoTargetType());
}
private Slice<Target> findByCriteriaAPI(final Pageable pageable, final List<Specification<JpaTarget>> specList) {
if (CollectionUtils.isEmpty(specList)) {
return convertPage(targetRepository.findAllWithoutCount(pageable), pageable);
@@ -545,6 +567,59 @@ public class JpaTargetManagement implements TargetManagement {
return result;
}
@Override
@Transactional
@Retryable(include = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public TargetTypeAssignmentResult assignType(final Collection<String> controllerIds, final Long typeId) {
final TargetType type = targetTypeRepository.findById(typeId)
.orElseThrow(() -> new EntityNotFoundException(TargetType.class, typeId));
final List<JpaTarget> targetsWithSameType = findTargetsByInSpecification(controllerIds,
TargetSpecifications.hasTargetType(typeId));
final List<JpaTarget> targetsWithoutSameType = findTargetsByInSpecification(controllerIds,
TargetSpecifications.hasTargetTypeNot(typeId));
// set new target type to all targets without that type
targetsWithoutSameType.forEach(target -> target.setTargetType(type));
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(),
Collections
.unmodifiableList(targetsWithoutSameType.stream().map(targetRepository::save).collect(Collectors.toList())),
Collections.emptyList(), type);
// no reason to persist the type
entityManager.detach(type);
return result;
}
@Override
@Transactional
@Retryable(include = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public TargetTypeAssignmentResult unAssignType(final Collection<String> controllerIds) {
final List<JpaTarget> allTargets = findTargetsByInSpecification(controllerIds, null);
if (allTargets.size() < controllerIds.size()) {
throw new EntityNotFoundException(Target.class, controllerIds,
allTargets.stream().map(Target::getControllerId).collect(Collectors.toList()));
}
// set new target type to null for all targets
allTargets.forEach(target -> target.setTargetType(null));
return new TargetTypeAssignmentResult(0, Collections.emptyList(), Collections
.unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList())), null);
}
private List<JpaTarget> findTargetsByInSpecification(Collection<String> controllerIds,
Specification<JpaTarget> specification) {
return Lists.partition(new ArrayList<>(controllerIds), Constants.MAX_ENTRIES_IN_STATEMENT).stream()
.map(ids -> targetRepository.findAll(TargetSpecifications.hasControllerIdIn(ids).and(specification)))
.flatMap(List::stream).collect(Collectors.toList());
}
@Override
@Transactional
@Retryable(include = {
@@ -625,7 +700,7 @@ public class JpaTargetManagement implements TargetManagement {
/**
* Applies orderedByLinkedDistributionSet spec for order and adds additional
* specs based on filters
*
*
* @param orderByDistributionId
* distribution set used for order
* @param filterParams

View File

@@ -8,12 +8,6 @@
*/
package org.eclipse.hawkbit.repository.jpa;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.TargetTypeFields;
import org.eclipse.hawkbit.repository.TargetTypeManagement;
@@ -42,9 +36,14 @@ import org.springframework.orm.jpa.vendor.Database;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* JPA implementation of {@link TargetTypeManagement}.
*

View File

@@ -392,12 +392,16 @@ public final class TargetSpecifications {
return (targetRoot, query, cb) -> {
// Since the targetRoot is changed by joining we need to get the
// isNull predicate first
final Predicate targetTypeIsNull = targetRoot.get(JpaTarget_.targetType).isNull();
final Predicate targetTypeIsNull = getTargetTypeIsNullPredicate(targetRoot);
return cb.or(targetTypeIsNull, cb.equal(getDsTypeIdPath(targetRoot), distributionSetTypeId));
};
}
private static Predicate getTargetTypeIsNullPredicate(Root<JpaTarget> targetRoot) {
return targetRoot.get(JpaTarget_.targetType).isNull();
}
/**
* {@link Specification} for retrieving {@link Target}s that are NOT compatible
* with given {@link DistributionSetType}. Compatibility is evaluated by
@@ -532,13 +536,39 @@ public final class TargetSpecifications {
}
/**
* {@link Specification} for retrieving {@link Target}s that have a
* {@link org.eclipse.hawkbit.repository.model.TargetType} assigned
* {@link Specification} for retrieving {@link Target}s by target type id
*
* @param typeId
* the id of the target type
*
* @return the {@link Target} {@link Specification}
*/
public static Specification<JpaTarget> hasTargetType() {
return (targetRoot, query, cb) -> cb.isNotNull(targetRoot.get(JpaTarget_.targetType));
public static Specification<JpaTarget> hasTargetType(final long typeId) {
return (targetRoot, query, cb) -> cb.equal(targetRoot.get(JpaTarget_.targetType).get(JpaTargetType_.id),
typeId);
}
/**
* {@link Specification} for retrieving {@link Target}s by target type id is equal to null
*
* @return the {@link Target} {@link Specification}
*/
public static Specification<JpaTarget> hasNoTargetType() {
return (targetRoot, query, cb) -> cb.isNull(targetRoot.get(JpaTarget_.targetType));
}
/**
* {@link Specification} for retrieving {@link Target}s that don't have target
* type assigned
*
* @param typeId
* the id of the target type
*
* @return the {@link Target} {@link Specification}
*/
public static Specification<JpaTarget> hasTargetTypeNot(final Long typeId) {
return (targetRoot, query, cb) -> cb.or(getTargetTypeIsNullPredicate(targetRoot),
cb.notEqual(targetRoot.get(JpaTarget_.targetType).get(JpaTargetType_.id), typeId));
}
/**

View File

@@ -26,6 +26,8 @@ import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.test.TestConfiguration;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
@@ -133,4 +135,10 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
return distributionSetManagement.toggleTagAssignment(
sets.stream().map(DistributionSet::getId).collect(Collectors.toList()), tag.getName());
}
protected TargetTypeAssignmentResult initiateTypeAssignment(final Collection<Target> targets, final TargetType type) {
return targetManagement.assignType(
targets.stream().map(Target::getControllerId).collect(Collectors.toList()), type.getId());
}
}

View File

@@ -58,7 +58,11 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final TargetTag targTagZ = targetTagManagement.create(entityFactory.tag().create().name("TargTag-Z"));
final TargetTag targTagW = targetTagManagement.create(entityFactory.tag().create().name("TargTag-W"));
final DistributionSet setA = testdataFactory.createDistributionSet("");
final DistributionSet setA = testdataFactory.createDistributionSet("A");
final DistributionSet setB = testdataFactory.createDistributionSet("B");
final TargetType targetTypeX = testdataFactory.createTargetType("TargetTypeX",
Collections.singletonList(setB.getType()));
final DistributionSet installedSet = testdataFactory.createDistributionSet("another");
@@ -92,12 +96,17 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
final List<Target> targDs = testdataFactory.createTargets(100, targetDsDIdPref,
targetDsDIdPref.concat(" description"), lastTargetNull);
final String targetDsEIdPref = "targ-E";
final List<Target> targEs = testdataFactory.createTargetsWithType(100, targetDsEIdPref, targetTypeX);
final String assignedC = targCs.iterator().next().getControllerId();
assignDistributionSet(setA.getId(), assignedC);
final String assignedA = targAs.iterator().next().getControllerId();
assignDistributionSet(setA.getId(), assignedA);
final String assignedB = targBs.iterator().next().getControllerId();
assignDistributionSet(setA.getId(), assignedB);
final String assignedE = targEs.iterator().next().getControllerId();
assignDistributionSet(setB.getId(), assignedE);
final String installedC = targCs.iterator().next().getControllerId();
final Long actionId = getFirstAssignedActionId(assignDistributionSet(installedSet.getId(), assignedC));
@@ -136,7 +145,7 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat1TargetHasAttributeValue("%c-attribute%", targAttribute.getControllerId());
verifyThat1TargetHasAttributeValue("%" + targAttributeId.getControllerId() + "%",
targAttributeId.getControllerId());
verifyThatRepositoryContains400Targets();
verifyThatRepositoryContains500Targets();
verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs));
verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs);
verifyThat1TargetHasTagHasDescOrNameAndDs(targTagW, setA, targetManagement.getByControllerID(assignedC).get());
@@ -147,19 +156,19 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat1TargetWithDescOrNameHasDS(setA, targetManagement.getByControllerID(assignedA).get());
List<Target> expected = concat(targAs, targBs, targCs, targDs);
expected.removeAll(targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat397TargetsAreInStatusUnknown(unknown, expected);
verifyThat496TargetsAreInStatusUnknown(unknown, expected);
expected = concat(targBs, targCs);
expected.removeAll(targetManagement.getByControllerID(Arrays.asList(assignedB, assignedC)));
verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(targTagY, targTagW, unknown, expected);
verfyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(setA, unknown);
verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(setA, unknown);
expected = concat(targAs);
expected.remove(targetManagement.getByControllerID(assignedA).get());
verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(unknown, expected);
expected = concat(targBs);
expected.remove(targetManagement.getByControllerID(assignedB).get());
verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(targTagW, unknown, expected);
verifyThat3TargetsAreInStatusPending(pending,
targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat4TargetsAreInStatusPending(pending,
targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC, assignedE)));
verifyThat3TargetsWithGivenDSAreInPending(setA, pending,
targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(setA, pending,
@@ -171,8 +180,13 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
verifyThat2TargetsWithGivenTagAreInPending(targTagW, pending,
targetManagement.getByControllerID(Arrays.asList(assignedB, assignedC)));
verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(targTagW, both, concat(targBs, targCs));
verfiyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending,
verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(installedSet, pending,
targetManagement.getByControllerID(installedC).get());
verifyThat1TargetHasTypeAndDSAssigned(targetTypeX, setB, targetManagement.getByControllerID(assignedE).get());
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(setA, targetManagement.getByControllerID(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(installedSet, targetManagement.getByControllerID(Collections.singletonList(installedC)));
verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(targetTypeX, targEs);
verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(concat(targAs, targBs, targCs, targDs));
expected = concat(targBs, targCs);
expected.removeAll(targetManagement.getByControllerID(Arrays.asList(assignedB, assignedC)));
@@ -180,354 +194,314 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
}
@Step
private void verfiyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet,
private void verifyThat1TargetAIsInStatusPendingAndHasDSInstalled(final DistributionSet installedSet,
final List<TargetUpdateStatus> pending, final Target expected) {
final FilterParams filterParams = new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE);
final String query = "updatestatus==pending and installedds.name==" + installedSet.getName();
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(pending, null, null, installedSet.getId(), Boolean.FALSE))
.getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null,
installedSet.getId(), Boolean.FALSE)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat200targetsWithGivenTagAreInStatusPendingorUnknown(final TargetTag targTagW,
final List<TargetUpdateStatus> both, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName());
final String query = "(updatestatus==pending or updatestatus==unknown) and tag==" + targTagW.getName();
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(both, null, null, null, Boolean.FALSE, targTagW.getName()))
.getContent()).as("has number of elements").hasSize(200)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(both, null, null, null,
Boolean.FALSE, targTagW.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(200).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat2TargetsWithGivenTagAreInPending(final TargetTag targTagW,
final List<TargetUpdateStatus> pending, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE,
targTagW.getName());
final String query = "updatestatus==pending and tag==" + targTagW.getName();
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(pending, null, null, null, Boolean.FALSE, targTagW.getName()))
.getContent())
.as("has number of elements").hasSize(2).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, null,
Boolean.FALSE, targTagW.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(2).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat2TargetsWithGivenTagAndDSIsInPending(final TargetTag targTagW, final DistributionSet setA,
final List<TargetUpdateStatus> pending, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE,
targTagW.getName());
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ") and tag==" + targTagW.getName();
assertThat(targetManagement
.findByFilters(PAGE,
new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE, targTagW.getName()))
.getContent())
.as("has number of elements").hasSize(2).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, setA.getId(),
Boolean.FALSE, targTagW.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(2).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(final TargetTag targTagW,
final DistributionSet setA, final List<TargetUpdateStatus> pending, final Target expected) {
final FilterParams filterParams = new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE,
targTagW.getName());
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ") and (name==*targ-B* or description==*targ-B*) and tag==" + targTagW.getName();
assertThat(targetManagement
.findByFilters(PAGE,
new FilterParams(pending, null, "%targ-B%", setA.getId(), Boolean.FALSE, targTagW.getName()))
.getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, "%targ-B%",
setA.getId(), Boolean.FALSE, targTagW.getName())))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(final DistributionSet setA,
final List<TargetUpdateStatus> pending, final Target expected) {
final FilterParams filterParams = new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE);
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ") and (name==*targ-A* or description==*targ-A*)";
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(pending, null, "%targ-A%", setA.getId(), Boolean.FALSE))
.getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, "%targ-A%",
setA.getId(), Boolean.FALSE)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat3TargetsWithGivenDSAreInPending(final DistributionSet setA,
final List<TargetUpdateStatus> pending, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE);
final String query = "updatestatus==pending and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ")";
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(pending, null, null, setA.getId(), Boolean.FALSE)).getContent())
.as("has number of elements").hasSize(3).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(pending, null, null, setA.getId(), Boolean.FALSE)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(3).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat3TargetsAreInStatusPending(final List<TargetUpdateStatus> pending,
private void verifyThat4TargetsAreInStatusPending(final List<TargetUpdateStatus> pending,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams(pending, null, null, null, Boolean.FALSE);
final String query = "updatestatus==pending";
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(pending, null, null, null, Boolean.FALSE))
.getContent())
.as("has number of elements").hasSize(3).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(pending, null, null, null,
Boolean.FALSE, new String[0])))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(4).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat99TargetsWithGivenNameOrDescAndTagAreInStatusUnknown(final TargetTag targTagW,
final List<TargetUpdateStatus> unknown, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE,
targTagW.getName());
final String query = "updatestatus==unknown and (name==*targ-B* or description==*targ-B*) and tag=="
+ targTagW.getName();
assertThat(targetManagement
.findByFilters(PAGE,
new FilterParams(unknown, null, "%targ-B%", null, Boolean.FALSE, targTagW.getName()))
.getContent()).as("has number of elements").hasSize(99)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(unknown, null, "%targ-B%", null,
Boolean.FALSE, targTagW.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(99).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat99TargetsWithNameOrDescriptionAreInGivenStatus(final List<TargetUpdateStatus> unknown,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE);
final String query = "updatestatus==unknown and (name==*targ-A* or description==*targ-A*)";
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(unknown, null, "%targ-A%", null, Boolean.FALSE, new String[0]))
.getContent()).as("has number of elements").hasSize(99)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(unknown, null, "%targ-A%", null, Boolean.FALSE)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(99).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verfyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA,
private void verifyThat0TargetsAreInStatusUnknownAndHaveDSAssigned(final DistributionSet setA,
final List<TargetUpdateStatus> unknown) {
final FilterParams filterParams = new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE);
final String query = "updatestatus==unknown and (assignedds.name==" + setA.getName() + " or installedds.name=="
+ setA.getName() + ")";
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(unknown, null, null, setA.getId(), Boolean.FALSE)).getContent())
.as("has number of elements").hasSize(0).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(unknown, null, null, setA.getId(), Boolean.FALSE)))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(0).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
}
@Step
private void verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(final TargetTag targTagY,
final TargetTag targTagW, final List<TargetUpdateStatus> unknown, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(),
targTagW.getName());
final String query = "updatestatus==unknown and (tag==" + targTagY.getName() + " or tag==" + targTagW.getName()
+ ")";
assertThat(targetManagement.findByFilters(PAGE,
new FilterParams(unknown, null, null, null, Boolean.FALSE, targTagY.getName(), targTagW.getName()))
.getContent()).as("has number of elements").hasSize(198)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(unknown, null, null, null,
Boolean.FALSE, targTagY.getName(), targTagW.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(198).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat397TargetsAreInStatusUnknown(final List<TargetUpdateStatus> unknown,
private void verifyThat496TargetsAreInStatusUnknown(final List<TargetUpdateStatus> unknown,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams(unknown, null, null, null, Boolean.FALSE);
final String query = "updatestatus==unknown";
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(unknown, null, null, null, Boolean.FALSE))
.getContent()).as("has number of elements").hasSize(397)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(unknown, null, null, null, Boolean.FALSE)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(496).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat198TargetsAreInStatusUnknownAndOverdue(final List<TargetUpdateStatus> unknown,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE);
// be careful: simple filters are concatenated using AND-gating
final String query = "lastcontrollerrequestat=le=${overdue_ts};updatestatus==UNKNOWN";
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(unknown, Boolean.TRUE, null, null, Boolean.FALSE)).getContent())
.as("has number of elements").hasSize(198).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(unknown, Boolean.TRUE, null, null, Boolean.FALSE)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(198).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetWithDescOrNameHasDS(final DistributionSet setA, final Target expected) {
final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE);
final String query = "(name==*targ-A* or description==*targ-A*) and (assignedds.name==" + setA.getName()
+ " or installedds.name==" + setA.getName() + ")";
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE))
.getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(null, null, "%targ-A%", setA.getId(), Boolean.FALSE)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat3TargetsHaveDSAssigned(final DistributionSet setA, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(null, null, null, setA.getId(), Boolean.FALSE);
final String query = "assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName();
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, null, setA.getId(), Boolean.FALSE))
.getContent())
.as("has number of elements").hasSize(3).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(null, null, null, setA.getId(), Boolean.FALSE)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(3).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat0TargetsWithNameOrdescAndDSHaveTag(final TargetTag targTagX, final DistributionSet setA) {
final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE,
targTagX.getName());
final String query = "(name==*targ-C* or description==*targ-C*) and tag==" + targTagX.getName()
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
assertThat(targetManagement
.findByFilters(PAGE,
new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagX.getName()))
.getContent())
.as("has number of elements").hasSize(0).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-C%",
setA.getId(), Boolean.FALSE, targTagX.getName())))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(0).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
}
@Step
private void verifyThat0TargetsWithTagAndDescOrNameHasDS(final TargetTag targTagW, final DistributionSet setA) {
final FilterParams filterParams = new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE,
targTagW.getName());
final String query = "(name==*targ-A* or description==*targ-A*) and tag==" + targTagW.getName()
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
assertThat(targetManagement
.findByFilters(PAGE,
new FilterParams(null, null, "%targ-A%", setA.getId(), Boolean.FALSE, targTagW.getName()))
.getContent())
.as("has number of elements").hasSize(0).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-A%",
setA.getId(), Boolean.FALSE, targTagW.getName())))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(0).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(PAGE, query).getContent().size());
}
@Step
private void verifyThat1TargetHasTagHasDescOrNameAndDs(final TargetTag targTagW, final DistributionSet setA,
final Target expected) {
final FilterParams filterParams = new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE,
targTagW.getName());
final String query = "(name==*targ-c* or description==*targ-C*) and tag==" + targTagW.getName()
+ " and (assignedds.name==" + setA.getName() + " or installedds.name==" + setA.getName() + ")";
assertThat(targetManagement
.findByFilters(PAGE,
new FilterParams(null, null, "%targ-C%", setA.getId(), Boolean.FALSE, targTagW.getName()))
.getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-C%",
setA.getId(), Boolean.FALSE, targTagW.getName())))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThat1TargetHasNameAndId(final String name, final String controllerId) {
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, name, null, Boolean.FALSE))
.getContent()).as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints
.saturatedCast(targetManagement.countByFilters(null, null, name, null, Boolean.FALSE)));
final FilterParams filterParamsByName = new FilterParams(null, null, name, null, Boolean.FALSE);
assertThat(targetManagement.findByFilters(PAGE, filterParamsByName).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParamsByName)));
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, controllerId, null, Boolean.FALSE))
.getContent()).as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(null, null, controllerId, null, Boolean.FALSE)));
final FilterParams filterParamsByControllerId = new FilterParams(null, null, controllerId, null, Boolean.FALSE);
assertThat(targetManagement.findByFilters(PAGE, filterParamsByControllerId).getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParamsByControllerId)));
}
@Step
private void verifyThat1TargetHasAttributeValue(final String value, final String controllerId) {
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, value, null, Boolean.FALSE))
.getContent()).as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(
targetManagement.countByFilters(null, null, value, null, Boolean.FALSE)));
final FilterParams filterParams = new FilterParams(null, null, value, null, Boolean.FALSE);
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)));
}
@Step
private void verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(final TargetTag targTagY,
final TargetTag targTagW, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE,
targTagY.getName(), targTagW.getName());
final String query = "(name==*targ-B* or description==*targ-B*) and (tag==" + targTagY.getName() + " or tag=="
+ targTagW.getName() + ")";
assertThat(targetManagement.findByFilters(PAGE,
new FilterParams(null, null, "%targ-B%", null, Boolean.FALSE, targTagY.getName(), targTagW.getName()))
.getContent()).as("has number of elements").hasSize(100)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, "%targ-B%", null,
Boolean.FALSE, targTagY.getName(), targTagW.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(100).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@SafeVarargs
@@ -539,27 +513,66 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
@Step
private void verifyThat200TargetsHaveTagD(final TargetTag targTagD, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName());
final String query = "tag==" + targTagD.getName();
assertThat(targetManagement
.findByFilters(PAGE, new FilterParams(null, null, null, null, Boolean.FALSE, targTagD.getName()))
.getContent()).as("Expected number of results is").hasSize(200)
.as("and is expected number of results is equal to ")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(null, null, null, null,
Boolean.FALSE, targTagD.getName())))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("Expected number of results is")
.hasSize(200).as("and is expected number of results is equal to ")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(PAGE, query).getContent());
}
@Step
private void verifyThatRepositoryContains400Targets() {
assertThat(targetManagement.findByFilters(PAGE, new FilterParams(null, null, null, null, null)).getContent())
.as("Overall we expect that many targets in the repository").hasSize(400)
private void verifyThatRepositoryContains500Targets() {
final FilterParams filterParams = new FilterParams(null, null, null, null, null);
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent())
.as("Overall we expect that many targets in the repository").hasSize(500)
.as("which is also reflected by repository count").hasSize(Ints.saturatedCast(targetManagement.count()))
.as("which is also reflected by call without specification")
.containsAll(targetManagement.findAll(PAGE).getContent());
}
@Step
private void verifyThat1TargetHasTypeAndDSAssigned(final TargetType type, final DistributionSet set,
final Target expected) {
final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.FALSE, type.getId());
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsExactly(expected);
}
@Step
private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set, final List<Target> expected) {
final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null);
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(expected.size()).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected);
}
@Step
private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId());
List<Target> filteredTargets = targetManagement.findByFilters(PAGE, filterParams).getContent();
assertThat(filteredTargets).as("has number of elements").hasSize(100)
.as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)));
// Comparing the controller ids, as one of the targets was modified, so a 1:1
// comparison of the objects is not possible
assertThat(filteredTargets.stream().map(Target::getControllerId).collect(Collectors.toList()))
.containsAll(expected.stream().map(Target::getControllerId).collect(Collectors.toList()));
}
@Step
private void verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(final List<Target> expected) {
final FilterParams filterParams = new FilterParams("%targ-%", null, Boolean.TRUE, null);
assertThat(targetManagement.findByFilters(PAGE, filterParams).getContent()).as("has number of elements")
.hasSize(400).as("that number is also returned by count query")
.hasSize(Ints.saturatedCast(targetManagement.countByFilters(filterParams)))
.as("and contains the following elements").containsAll(expected);
}
@Test
@@ -770,4 +783,28 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
.type(type);
return distributionSetManagement.create(dsCreate);
}
@Test
@Description("Verifies that targets with given target type are returned from repository.")
public void findTargetByTargetType() {
TargetType testType = testdataFactory.createTargetType("testType", Collections.singletonList(standardDsType));
List<Target> unassigned = testdataFactory.createTargets(9, "unassigned");
List<Target> assigned = testdataFactory.createTargetsWithType(11, "assigned", testType);
assertThat(targetManagement.findByFilters(PAGE,
new FilterParams(null,null, false, testType.getId())))
.as("Contains the targets with set type").containsAll(assigned)
.as("and that means the following expected amount").hasSize(11);
assertThat(targetManagement.countByFilters(new FilterParams(null,null, false, testType.getId())))
.as("Count the targets with set type").isEqualTo(11);
assertThat(targetManagement.findByFilters(PAGE,
new FilterParams(null, null, true, null)))
.as("Contains the targets without a type").containsAll(unassigned)
.as("and that means the following expected amount").hasSize(9);
assertThat(targetManagement.countByFilters(new FilterParams(null, null, true, null)))
.as("Counts the targets without a type").isEqualTo(9);
}
}

View File

@@ -28,6 +28,7 @@ import javax.validation.ConstraintViolationException;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
@@ -39,6 +40,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreated
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTagCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetTypeCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
@@ -57,6 +59,7 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetTypeAssignmentResult;
import org.eclipse.hawkbit.repository.test.matcher.Expect;
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
@@ -752,7 +755,7 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
toggleTagAssignment(tagABCTargets, tagB);
toggleTagAssignment(tagABCTargets, tagC);
assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "X"))
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "X")))
.as("Target count is wrong").isEqualTo(0);
// search for targets with tag tagA
@@ -782,11 +785,11 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
checkTargetHasNotTags(tagCTargets, tagA, tagB);
// check again target lists refreshed from DB
assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "A"))
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "A")))
.as("Target count is wrong").isEqualTo(targetWithTagA.size());
assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "B"))
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "B")))
.as("Target count is wrong").isEqualTo(targetWithTagB.size());
assertThat(targetManagement.countByFilters(null, null, null, null, Boolean.FALSE, "C"))
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "C")))
.as("Target count is wrong").isEqualTo(targetWithTagC.size());
}
@@ -1107,7 +1110,57 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
assertThat(targetFound1.get().getOptLockRevision()).isEqualTo(2);
assertThat(targetFound1.get().getTargetType().getId()).isEqualTo(targetType.getId());
}
@Test
@WithUser(allSpPermissions = true)
@Description("Tests the assignment of types to multiple targets.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 20),
@Expect(type = TargetTypeCreatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 29), @Expect(type = TargetDeletedEvent.class, count = 1) })
public void targetTypeBulkAssignments() {
final List<Target> typeATargets = testdataFactory.createTargets(10, "typeATargets", "first description");
final List<Target> typeBTargets = testdataFactory.createTargets(10, "typeBTargets", "first description");
// create a target type
final TargetType typeA = testdataFactory.createTargetType("A", Collections.singletonList(standardDsType));
final TargetType typeB = testdataFactory.createTargetType("B", Collections.singletonList(standardDsType));
// assign target type to target
TargetTypeAssignmentResult resultA = initiateTypeAssignment(typeATargets, typeA);
TargetTypeAssignmentResult resultB = initiateTypeAssignment(typeBTargets, typeB);
assertThat(resultA.getAssigned()).isEqualTo(10);
assertThat(resultB.getAssigned()).isEqualTo(10);
checkTargetsHaveType(typeATargets, typeA);
checkTargetsHaveType(typeBTargets, typeB);
// double assignment does not unassign
resultA = initiateTypeAssignment(typeATargets, typeA);
resultB = initiateTypeAssignment(typeBTargets, typeB);
assertThat(resultA.getAssigned()).isZero();
assertThat(resultB.getAssigned()).isZero();
assertThat(resultA.getAlreadyAssigned()).isEqualTo(10);
assertThat(resultB.getAlreadyAssigned()).isEqualTo(10);
checkTargetsHaveType(typeATargets, typeA);
checkTargetsHaveType(typeBTargets, typeB);
// verify that type assignment does not throw an error if target list includes an unknown id
targetManagement.deleteByControllerID(typeATargets.get(0).getControllerId());
final TargetTypeAssignmentResult resultC = initiateTypeAssignment(typeATargets, typeB);
assertThat(resultC.getAssigned()).isEqualTo(9);
assertThat(resultC.getAlreadyAssigned()).isZero();
checkTargetsHaveType(typeATargets, typeB);
}
private void checkTargetsHaveType(final List<Target> targets, final TargetType type) {
List<JpaTarget> foundTargets = targetRepository
.findAllById(targets.stream().map(Identifiable::getId).collect(Collectors.toList()));
for (final Target target : foundTargets) {
if (!type.getName().equals(type.getName())) {
fail(String.format("Target %s is not of type %s.", target, type));
}
}
}
@Test
@Description("Queries and loads the metadata related to a given target.")
public void findAllTargetMetadataByControllerId() {

View File

@@ -110,7 +110,7 @@ import org.springframework.test.context.TestPropertySource;
public abstract class AbstractIntegrationTest {
private static final Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class);
protected static final Pageable PAGE = PageRequest.of(0, 400, Sort.by(Direction.ASC, "id"));
protected static final Pageable PAGE = PageRequest.of(0, 500, Sort.by(Direction.ASC, "id"));
protected static final URI LOCALHOST = URI.create("http://127.0.0.1");