Cleanup TargetManagement (#2601)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-08-08 13:13:28 +03:00
committed by GitHub
parent 5217297c24
commit bff77ac224
35 changed files with 433 additions and 2032 deletions

View File

@@ -32,7 +32,9 @@ import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
@@ -58,14 +60,12 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
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.TestConfiguration;
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
@@ -191,9 +191,8 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
return distributionSetManagement.unassignTag(sets.stream().map(DistributionSet::getId).toList(), tag.getId());
}
protected TargetTypeAssignmentResult initiateTypeAssignment(final Collection<Target> targets, final TargetType type) {
return targetManagement.assignType(
targets.stream().map(Target::getControllerId).toList(), type.getId());
protected void initiateTypeAssignment(final Collection<Target> targets, final TargetType type) {
targets.stream().map(Target::getControllerId).forEach(id -> targetManagement.assignType(id, type.getId()));
}
protected void assertRollout(final Rollout rollout, final boolean dynamic, final Rollout.RolloutStatus status, final int groupCreated,
@@ -312,6 +311,10 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
return rolloutGroupRepository.findById(group.getId()).get();
}
protected static Specification<JpaAction> byDistributionSetId(final Long distributionSetId) {
return (root, query, cb) -> cb.equal(root.get(JpaAction_.distributionSet).get(AbstractJpaBaseEntity_.id), distributionSetId);
}
private JpaRollout refresh(final Rollout rollout) {
return rolloutRepository.findById(rollout.getId()).get();
}

View File

@@ -24,7 +24,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
@@ -76,10 +75,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
assertThat(targetManagement.findByRsql("id==*", Pageable.unpaged()).get().map(Identifiable::getId).toList())
.containsOnly(permittedTarget.getId());
// verify targetManagement#findByUpdateStatus
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.REGISTERED, Pageable.unpaged()).get()
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
// verify targetManagement#getByControllerID
assertThat(targetManagement.getByControllerId(permittedTarget.getControllerId())).isPresent();
final String hiddenTargetControllerId = hiddenTarget.getControllerId();
@@ -106,19 +101,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
.as("Target should not be found.")
.isInstanceOf(InsufficientPermissionException.class);
});
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> {
// verify targetManagement#findByTargetFilterQuery
assertThat(targetManagement.findByTargetFilterQuery(targetFilterQuery.getId(), Pageable.unpaged()).get()
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
// verify targetManagement#findByTargetFilterQuery (used by UI)
assertThat(targetManagement.findByFilters(new FilterParams(null, null, null, null), Pageable.unpaged()).get()
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
});
}
@Test
@@ -208,11 +190,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
.create(Create.builder().controllerId("device02").updateStatus(TargetUpdateStatus.REGISTERED).build())
.getControllerId();
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () ->
// verify targetManagement#findByUpdateStatus before assignment
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.REGISTERED, Pageable.unpaged()).get()
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId()));
runAs(withUser("user",
READ_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
UPDATE_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
@@ -221,14 +198,6 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
assertThat(assignDistributionSet(dsId, permittedTarget.getControllerId()).getAssigned()).isEqualTo(1);
// assigning of not allowed target behaves as not found
assertThatThrownBy(() -> assignDistributionSet(dsId, hiddenTargetControllerId)).isInstanceOf(AssertionError.class);
// verify targetManagement#findByUpdateStatus(REGISTERED) after assignment
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.REGISTERED, Pageable.unpaged())
.getTotalElements()).isZero();
// verify targetManagement#findByUpdateStatus(PENDING) after assignment
assertThat(targetManagement.findByUpdateStatus(TargetUpdateStatus.PENDING, Pageable.unpaged()).get()
.map(Identifiable::getId).toList()).containsOnly(permittedTarget.getId());
});
}

View File

@@ -145,7 +145,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
verifyThatTargetsHaveDistributionSetAssignment(setB, targets.subList(10, 20), targetsCount);
// Count the number of targets that will be assigned with setA
assertThat(targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(setA.getId(), targetFilterQuery.getQuery()))
assertThat(targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(setA.getId(), targetFilterQuery.getQuery()))
.isEqualTo(15);
// Run the check
@@ -405,7 +405,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
final List<Long> compatibleTargets = Stream
.of(compatibleTargetsSingleType, compatibleTargetsMultiType, compatibleTargetsWithoutType)
.flatMap(Collection::stream).map(Target::getId).toList();
final long compatibleCount = targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(testDs.getId(),
final long compatibleCount = targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(testDs.getId(),
testFilter.getQuery());
assertThat(compatibleCount).isEqualTo(compatibleTargets.size());
@@ -498,7 +498,7 @@ class AutoAssignCheckerIntTest extends AbstractJpaIntegrationTest {
private Slice<Action> findActionsByDistributionSet(final Pageable pageable, final long distributionSetId) {
return actionRepository
.findAll(ActionSpecifications.byDistributionSetId(distributionSetId), pageable)
.findAll(byDistributionSetId(distributionSetId), pageable)
.map(Action.class::cast);
}
}

View File

@@ -95,7 +95,7 @@ class RepositoryEntityEventTest extends AbstractJpaIntegrationTest {
void targetDeletedEventIsPublished() throws InterruptedException {
final Target createdTarget = testdataFactory.createTarget("12345");
targetManagement.deleteByControllerID("12345");
targetManagement.deleteByControllerId("12345");
final TargetDeletedEvent targetDeletedEvent = eventListener.waitForEvent(TargetDeletedEvent.class);
assertThat(targetDeletedEvent).isNotNull();

View File

@@ -1788,7 +1788,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
distributionSetManagement.get(distributionSetId).orElseThrow(() ->
new EntityNotFoundException(DistributionSet.class, distributionSetId));
return actionRepository
.findAll(ActionSpecifications.byDistributionSetId(distributionSetId), pageable)
.findAll(byDistributionSetId(distributionSetId), pageable)
.map(Action.class::cast);
}

View File

@@ -958,11 +958,12 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
expectedTargetCountStatus.put(TotalTargetCountStatus.Status.FINISHED, 9L);
validateRolloutActionStatus(rolloutTwo.getId(), expectedTargetCountStatus);
changeStatusForAllRunningActions(rolloutTwo, Status.FINISHED);
final Page<Target> targetPage = targetManagement.findByUpdateStatus(TargetUpdateStatus.IN_SYNC, PAGE);
final List<Target> targetList = targetPage.getContent();
final List<? extends Target> targetList = findByUpdateStatus(TargetUpdateStatus.IN_SYNC, PAGE);
// 15 targets in finished/IN_SYNC status and same DS assigned
assertThat(targetList).hasSize(amountTargetsForRollout);
targetList.stream().map(Target::getControllerId).map(deploymentManagement::getAssignedDistributionSet)
targetList.stream()
.map(Target::getControllerId)
.map(deploymentManagement::getAssignedDistributionSet)
.forEach(d -> assertThat(d).contains(distributionSet));
}

View File

@@ -12,25 +12,18 @@ package org.eclipse.hawkbit.repository.jpa.management;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.junit.jupiter.api.Test;
/**
@@ -39,157 +32,6 @@ import org.junit.jupiter.api.Test;
*/
class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
private static final String SPACE_AND_DESCRIPTION = " description";
/**
* Verifies that targets with given target type are returned from repository.
*/
@Test
void findTargetByTargetType() {
final TargetType testType = testdataFactory.createTargetType("testType", Set.of(standardDsType));
final List<Target> unassigned = testdataFactory.createTargets(9, "unassigned");
final List<Target> assigned = testdataFactory.createTargetsWithType(11, "assigned", testType);
assertThat(targetManagement.findByFilters(new FilterParams(null, null, false, testType.getId()), PAGE))
.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(new FilterParams(null, null, true, null), PAGE))
.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);
}
/**
* Tests different parameter combinations for target search operations.
* and query definitions by RSQL (named and un-named).
*/
@Test
void targetSearchWithVariousFilterCombinations() {
final TargetTag targTagX = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-X").build());
final TargetTag targTagY = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-Y").build());
final TargetTag targTagZ = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-Z").build());
final TargetTag targTagW = targetTagManagement.create(TargetTagManagement.Create.builder().name("TargTag-W").build());
final DistributionSet setA = testdataFactory.createDistributionSet("A");
final DistributionSet setB = testdataFactory.createDistributionSet("B");
final TargetType targetTypeX = testdataFactory.createTargetType("TargetTypeX", Set.of(setB.getType()));
final DistributionSet installedSet = testdataFactory.createDistributionSet("another");
final Long lastTargetQueryNotOverdue = System.currentTimeMillis();
final Long lastTargetQueryAlwaysOverdue = 0L;
final String targetDsAIdPref = "targ-A";
List<Target> targAs = testdataFactory.createTargets(100, targetDsAIdPref,
targetDsAIdPref.concat(SPACE_AND_DESCRIPTION), lastTargetQueryNotOverdue);
targAs = assignTag(targAs, targTagX);
final Target targSpecialName = targetManagement
.update(TargetManagement.Update.builder().id(targAs.get(0).getId()).name("targ-A-special").build());
final String targetDsBIdPref = "targ-B";
List<Target> targBs = testdataFactory.createTargets(100, targetDsBIdPref,
targetDsBIdPref.concat(SPACE_AND_DESCRIPTION), lastTargetQueryAlwaysOverdue);
targBs = assignTag(targBs, targTagY);
targBs = assignTag(targBs, targTagW);
final String targetDsCIdPref = "targ-C";
List<Target> targCs = testdataFactory.createTargets(100, targetDsCIdPref,
targetDsCIdPref.concat(SPACE_AND_DESCRIPTION), lastTargetQueryAlwaysOverdue);
targCs = assignTag(targCs, targTagZ);
targCs = assignTag(targCs, targTagW);
final String targetDsDIdPref = "targ-D";
final List<Target> targDs = testdataFactory.createTargets(100, targetDsDIdPref,
targetDsDIdPref.concat(SPACE_AND_DESCRIPTION), null);
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));
// set one installed DS also
controllerManagement.addUpdateActionStatus(
entityFactory.actionStatus().create(actionId).status(Status.FINISHED).message("message"));
assignDistributionSet(setA.getId(), installedC);
final List<TargetUpdateStatus> unknown = List.of(TargetUpdateStatus.UNKNOWN);
final List<TargetUpdateStatus> pending = List.of(TargetUpdateStatus.PENDING);
final List<TargetUpdateStatus> both = List.of(TargetUpdateStatus.UNKNOWN, TargetUpdateStatus.PENDING);
// get final updated version of targets
targAs = targetManagement.getByControllerId(targAs.stream().map(Target::getControllerId).toList());
targBs = targetManagement.getByControllerId(targBs.stream().map(Target::getControllerId).toList());
targCs = targetManagement.getByControllerId(targCs.stream().map(Target::getControllerId).toList());
// try to find several targets with different filter settings
verifyThat1TargetHasNameAndId("targ-A-special", targSpecialName.getControllerId());
verifyThatRepositoryContains500Targets();
verifyThat200TargetsHaveTagD(targTagW, concat(targBs, targCs));
verifyThat100TargetsContainsGivenTextAndHaveTagAssigned(targTagY, targTagW, targBs);
verifyThat1TargetHasTagHasDescOrNameAndDs(targTagW, setA, targetManagement.getByControllerId(assignedC).get());
verifyThat0TargetsWithTagAndDescOrNameHasDS(targTagW, setA);
verifyThat0TargetsWithNameOrdescAndDSHaveTag(targTagX, setA);
verifyThat3TargetsHaveDSAssigned(setA, targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat1TargetWithDescOrNameHasDS(setA, targetManagement.getByControllerId(assignedA).get());
List<Target> expected = concat(targAs, targBs, targCs, targDs);
expected.removeAll(targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat496TargetsAreInStatusUnknown(unknown, expected);
expected = concat(targBs, targCs);
expected.removeAll(targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
verifyThat198TargetsAreInStatusUnknownAndHaveGivenTags(targTagY, targTagW, unknown, expected);
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);
verifyThat4TargetsAreInStatusPending(pending,
targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC, assignedE)));
verifyThat3TargetsWithGivenDSAreInPending(setA, pending,
targetManagement.getByControllerId(Arrays.asList(assignedA, assignedB, assignedC)));
verifyThat1TargetWithGivenNameOrDescAndDSIsInPending(setA, pending,
targetManagement.getByControllerId(assignedA).get());
verifyThat1TargetWithGivenNameOrDescAndTagAndDSIsInPending(targTagW, setA, pending,
targetManagement.getByControllerId(assignedB).get());
verifyThat2TargetsWithGivenTagAndDSIsInPending(targTagW, setA, pending,
targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
verifyThat2TargetsWithGivenTagAreInPending(targTagW, pending,
targetManagement.getByControllerId(Arrays.asList(assignedB, assignedC)));
verifyThat200targetsWithGivenTagAreInStatusPendingOrUnknown(targTagW, both, concat(targBs, targCs));
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)));
verifyThat198TargetsAreInStatusUnknownAndOverdue(unknown, expected);
}
/**
* Verifies that targets with given assigned DS are returned from repository.
*/
@@ -305,358 +147,4 @@ class TargetManagementSearchTest extends AbstractJpaIntegrationTest {
.containsExactlyInAnyOrderElementsOf(testTargets).as("does not contain incompatible targets")
.doesNotContainAnyElementsOf(targetsWithIncompatibleType);
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(200).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(2).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(2).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(3).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(4).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(99).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(99).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent())
.as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(query, PAGE).getContent().size())
.as("has number of elements")
.isEmpty();
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(198).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(496).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(198).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(3).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
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(filterParams, PAGE).getContent())
.as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(query, PAGE).getContent().size())
.as("has number of elements")
.isEmpty();
}
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(filterParams, PAGE).getContent())
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and filter query returns the same result")
.hasSize(targetManagement.findByRsql(query, PAGE).getContent().size())
.as("has number of elements")
.isEmpty();
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsExactly(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
private void verifyThat1TargetHasNameAndId(final String name, final String controllerId) {
final FilterParams filterParamsByName = new FilterParams(null, null, name, null, Boolean.FALSE);
assertThat(targetManagement.findByFilters(filterParamsByName, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParamsByName));
final FilterParams filterParamsByControllerId = new FilterParams(null, null, controllerId, null, Boolean.FALSE);
assertThat(targetManagement.findByFilters(filterParamsByControllerId, PAGE).getContent())
.as("has number of elements").hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParamsByControllerId));
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(100).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
@SafeVarargs
private List<Target> concat(final List<Target>... targets) {
final List<Target> result = new ArrayList<>();
Arrays.asList(targets).forEach(result::addAll);
return result;
}
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(filterParams, PAGE).getContent()).as("Expected number of results is")
.hasSize(200).as("and is expected number of results is equal to ")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected)
.as("and filter query returns the same result")
.containsAll(targetManagement.findByRsql(query, PAGE).getContent());
}
private void verifyThatRepositoryContains500Targets() {
final FilterParams filterParams = new FilterParams(null, null, null, null, null);
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent())
.as("Overall we expect that many targets in the repository").hasSize(500)
.as("which is also reflected by repository count").hasSize((int) targetManagement.count())
.as("which is also reflected by call without specification")
.containsAll(targetManagement.findAll(PAGE).getContent());
}
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(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(1).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsExactly(expected);
}
private void verifyThatTargetsHasNoTypeAndDSAssignedOrInstalled(final DistributionSet set,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams(null, set.getId(), Boolean.TRUE, null);
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(expected.size()).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected);
}
private void verifyThat100TargetsContainsGivenTextAndHaveTypeAssigned(final TargetType targetType,
final List<Target> expected) {
final FilterParams filterParams = new FilterParams("%targ-E%", null, Boolean.FALSE, targetType.getId());
final List<Target> filteredTargets = targetManagement.findByFilters(filterParams, PAGE).getContent();
assertThat(filteredTargets).as("has number of elements").hasSize(100)
.as("that number is also returned by count query")
.hasSize((int) 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).toList())
.containsAll(expected.stream().map(Target::getControllerId).toList());
}
private void verifyThat400TargetsContainsGivenTextAndHaveNoTypeAssigned(final List<Target> expected) {
final FilterParams filterParams = new FilterParams("%targ-%", null, Boolean.TRUE, null);
assertThat(targetManagement.findByFilters(filterParams, PAGE).getContent()).as("has number of elements")
.hasSize(400).as("that number is also returned by count query")
.hasSize((int) targetManagement.countByFilters(filterParams))
.as("and contains the following elements").containsAll(expected);
}
}

View File

@@ -14,11 +14,9 @@ import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.TargetManagement.Create;
import org.eclipse.hawkbit.repository.TargetManagement.Update;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.junit.jupiter.api.Test;
@@ -29,42 +27,6 @@ import org.junit.jupiter.api.Test;
@Slf4j
class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByAssignedDistributionSetPermissionsCheck() {
assertPermissions(() -> targetManagement.countByAssignedDistributionSet(1L),
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByFiltersPermissionsCheck() {
assertPermissions(() -> targetManagement.countByFilters(new FilterParams(null, null, null, null, null, null)),
List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByInstalledDistributionSetPermissionsCheck() {
assertPermissions(() -> targetManagement.countByInstalledDistributionSet(1L),
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void existsByInstalledOrAssignedDistributionSetPermissionsCheck() {
assertPermissions(() -> targetManagement.existsByInstalledOrAssignedDistributionSet(1L),
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -73,14 +35,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
assertPermissions(() -> targetManagement.countByRsql("controllerId==id"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByRsqlAndUpdatablePermissionsCheck() {
assertPermissions(() -> targetManagement.countByRsqlAndUpdatable("controllerId==id"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -138,21 +92,13 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void deleteByControllerIDPermissionsCheck() {
void deleteByControllerIdPermissionsCheck() {
assertPermissions(() -> {
targetManagement.deleteByControllerID("controllerId");
targetManagement.deleteByControllerId("controllerId");
return null;
}, List.of(SpPermission.DELETE_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByTargetFilterQueryPermissionsCheck() {
assertPermissions(() -> targetManagement.countByTargetFilterQuery(1L), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -166,8 +112,8 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByRsqlAndNonDSAndCompatibleAndUpdatablePermissionsCheck() {
assertPermissions(() -> targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(1L, "controllerId==id"),
void countByRsqlAndNonDsAndCompatibleAndUpdatablePermissionsCheck() {
assertPermissions(() -> targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(1L, "controllerId==id"),
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
@@ -262,15 +208,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
assertPermissions(() -> targetManagement.getByControllerId("controllerId"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByFiltersPermissionsCheck() {
assertPermissions(() -> targetManagement.findByFilters(new FilterParams(null, null, null, null, null, null), PAGE),
List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -289,14 +226,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
List.of(SpPermission.READ_TARGET, SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByUpdateStatusPermissionsCheck() {
assertPermissions(() -> targetManagement.findByUpdateStatus(TargetUpdateStatus.IN_SYNC, PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -313,14 +242,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
assertPermissions(() -> targetManagement.findByRsql("controllerId==id", PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByTargetFilterQueryPermissionsCheck() {
assertPermissions(() -> targetManagement.findByTargetFilterQuery(1L, PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -337,14 +258,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
assertPermissions(() -> targetManagement.findByRsqlAndTag("controllerId==id", 1L, PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void assignTypePermissionsCheck() {
assertPermissions(() -> targetManagement.assignType(List.of("controllerId"), 1L), List.of(SpPermission.UPDATE_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -388,14 +301,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
List.of(SpPermission.UPDATE_TARGET, SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void unassignTypePermissionsCheck() {
assertPermissions(() -> targetManagement.unassignType(List.of("controllerId")), List.of(SpPermission.UPDATE_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -428,14 +333,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
assertPermissions(() -> targetManagement.get(List.of(1L)), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void existsByControllerIdPermissionsCheck() {
assertPermissions(() -> targetManagement.existsByControllerId("controllerId"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@@ -462,33 +359,6 @@ class TargetManagementSecurityTest extends AbstractJpaIntegrationTest {
assertPermissions(() -> targetManagement.getControllerAttributes("controllerId"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void requestControllerAttributesPermissionsCheck() {
assertPermissions(() -> {
targetManagement.requestControllerAttributes("controllerId");
return null;
}, List.of(SpPermission.UPDATE_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void isControllerAttributesRequestedPermissionsCheck() {
assertPermissions(() -> targetManagement.isControllerAttributesRequested("controllerId"), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByControllerAttributesRequestedPermissionsCheck() {
assertPermissions(() -> targetManagement.findByControllerAttributesRequested(PAGE), List.of(SpPermission.READ_TARGET));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/

View File

@@ -26,13 +26,18 @@ import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.JoinType;
import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.SetJoin;
import jakarta.validation.ConstraintViolationException;
import org.assertj.core.api.Assertions;
import org.awaitility.Awaitility;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.im.authentication.SpRole;
import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.TargetManagement.Create;
import org.eclipse.hawkbit.repository.TargetManagement.Update;
@@ -54,12 +59,16 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidTargetAddressException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -70,9 +79,7 @@ import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target;
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.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
import org.eclipse.hawkbit.repository.test.matcher.Expect;
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
@@ -81,6 +88,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
/**
* Feature: Component Tests - Repository<br/>
@@ -91,7 +99,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
private static final String WHITESPACE_ERROR = "target with whitespaces in controller id should not be created";
/**
* Verifies that management get access react as specified on calls for non existing entities by means
* Verifies that management get access react as specified on calls for non existing entities by means
* of Optional not present.
*/
@Test
@@ -104,8 +112,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
}
/**
* Verifies that management queries react as specified on calls for non existing entities
* by means of throwing EntityNotFoundException.
* Verifies that management queries react as specified on calls for non existing entities
* by means of throwing EntityNotFoundException.
*/
@Test
@ExpectEvents({
@@ -122,15 +130,10 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
verifyThrownExceptionBy(() -> targetManagement.findByTag(NOT_EXIST_IDL, PAGE), "TargetTag");
verifyThrownExceptionBy(() -> targetManagement.findByRsqlAndTag("name==*", NOT_EXIST_IDL, PAGE), "TargetTag");
verifyThrownExceptionBy(() -> targetManagement.countByAssignedDistributionSet(NOT_EXIST_IDL), "DistributionSet");
verifyThrownExceptionBy(() -> targetManagement.countByInstalledDistributionSet(NOT_EXIST_IDL), "DistributionSet");
verifyThrownExceptionBy(() -> targetManagement.existsByInstalledOrAssignedDistributionSet(NOT_EXIST_IDL), "DistributionSet");
verifyThrownExceptionBy(() -> targetManagement.countByTargetFilterQuery(NOT_EXIST_IDL), "TargetFilterQuery");
verifyThrownExceptionBy(() -> targetManagement.countByRsqlAndNonDSAndCompatibleAndUpdatable(NOT_EXIST_IDL, "name==*"),
verifyThrownExceptionBy(() -> targetManagement.countByRsqlAndNonDsAndCompatibleAndUpdatable(NOT_EXIST_IDL, "name==*"),
"DistributionSet");
verifyThrownExceptionBy(() -> targetManagement.deleteByControllerID(NOT_EXIST_ID), "Target");
verifyThrownExceptionBy(() -> targetManagement.deleteByControllerId(NOT_EXIST_ID), "Target");
verifyThrownExceptionBy(() -> targetManagement.delete(Collections.singletonList(NOT_EXIST_IDL)), "Target");
verifyThrownExceptionBy(
@@ -166,7 +169,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
*/
@Test
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception {
void getTargetSecurityTokenOnlyWithCorrectPermission() {
final Target createdTarget = targetManagement
.create(Create.builder().controllerId("targetWithSecurityToken").securityToken("token").build());
@@ -280,10 +283,8 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
target = createTargetWithAttributes("4711");
assertThat(targetManagement.count()).as("target count is wrong").isEqualTo(1);
assertThat(targetManagement.existsByControllerId("4711")).isTrue();
targetManagement.delete(Collections.singletonList(target.getId()));
assertThat(targetManagement.count()).as("target count is wrong").isZero();
assertThat(targetManagement.existsByControllerId("4711")).isFalse();
final List<Long> targets = new ArrayList<>();
for (int i = 0; i < 5; i++) {
@@ -316,19 +317,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet testDs1 = testdataFactory.createDistributionSet("test");
final DistributionSet testDs2 = testdataFactory.createDistributionSet("test2");
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId()))
.as("For newly created distributions sets the assigned target count should be zero").isZero();
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId()))
.as("For newly created distributions sets the installed target count should be zero").isZero();
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
.as("Exists assigned or installed query should return false for new distribution sets").isFalse();
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId()))
.as("For newly created distributions sets the assigned target count should be zero").isZero();
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId()))
.as("For newly created distributions sets the installed target count should be zero").isZero();
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
.as("For newly created distributions sets the assigned target count should be zero").isFalse();
createTargetWithAttributes("4711");
final long current = System.currentTimeMillis();
@@ -344,19 +332,6 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
Target target = targetManagement.getByControllerId("4711").orElseThrow(IllegalStateException::new);
// read data
assertThat(targetManagement.countByAssignedDistributionSet(testDs1.getId())).as("Target count is wrong")
.isZero();
assertThat(targetManagement.countByInstalledDistributionSet(testDs1.getId())).as("Target count is wrong")
.isEqualTo(1);
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs1.getId()))
.as("Target count is wrong").isTrue();
assertThat(targetManagement.countByAssignedDistributionSet(testDs2.getId())).as("Target count is wrong")
.isEqualTo(1);
assertThat(targetManagement.countByInstalledDistributionSet(testDs2.getId())).as("Target count is wrong")
.isZero();
assertThat(targetManagement.existsByInstalledOrAssignedDistributionSet(testDs2.getId()))
.as("Target count is wrong").isTrue();
assertThat(target.getLastTargetQuery()).as("Target query is not work").isGreaterThanOrEqualTo(current);
final DistributionSet assignedDs = deploymentManagement.getAssignedDistributionSet("4711")
@@ -401,8 +376,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1) })
void singleTargetIsInsertedIntoRepo() throws Exception {
void singleTargetIsInsertedIntoRepo() {
final String myCtrlID = "myCtrlID";
Target savedTarget = testdataFactory.createTarget(myCtrlID);
@@ -482,7 +456,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
}
}
targetManagement.deleteByControllerID(extra.getControllerId());
targetManagement.deleteByControllerId(extra.getControllerId());
final int numberToDelete = 50;
final Collection<? extends Target> targetsToDelete = firstList.subList(0, numberToDelete);
@@ -495,7 +469,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
assertThat(firstList.spliterator().getExactSizeIfKnown() - numberToDelete).as("Size of split list")
.isEqualTo(targetsLeft.spliterator().getExactSizeIfKnown());
Assertions.<Target>assertThat(targetsLeft).as("Not all undeleted found").doesNotContain(deletedTargets);
Assertions.<Target> assertThat(targetsLeft).as("Not all undeleted found").doesNotContain(deletedTargets);
}
/**
@@ -567,7 +541,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
assignTag(tagABCTargets, tagB);
assignTag(tagABCTargets, tagC);
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "X")))
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "X")))
.as("Target count is wrong").isZero();
// search for targets with tag tagA
@@ -597,11 +571,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
checkTargetHasNotTags(tagCTargets, tagA, tagB);
// check again target lists refreshed from DB
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "A")))
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "A")))
.as("Target count is wrong").isEqualTo(targetWithTagA.size());
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "B")))
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "B")))
.as("Target count is wrong").isEqualTo(targetWithTagB.size());
assertThat(targetManagement.countByFilters(new FilterParams(null, null, null, null, Boolean.FALSE, "C")))
assertThat(countByFilters(new FilterParams(Boolean.FALSE, "C")))
.as("Target count is wrong").isEqualTo(targetWithTagC.size());
}
@@ -682,12 +656,10 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
testdataFactory.createTargets(25, "target-id-B", "first description");
final String[] tagNames = null;
final List<Target> targetsListWithNoTag = targetManagement
.findByFilters(new FilterParams(null, null, null, null, Boolean.TRUE, tagNames), PAGE).getContent();
final long targetsListWithNoTag = countByFilters(new FilterParams(Boolean.TRUE, tagNames));
assertThat(targetManagement.count()).as("Total targets").isEqualTo(50L);
assertThat(targetsListWithNoTag).as("Targets with no tag").hasSize(25);
assertThat(targetsListWithNoTag).as("Targets with no tag").isEqualTo(25);
}
/**
@@ -758,16 +730,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
void verifyRequestControllerAttributes() {
final String knownControllerId = "KnownControllerId";
final Target target = createTargetWithAttributes(knownControllerId);
assertThat(targetManagement.findByControllerAttributesRequested(PAGE)).isEmpty();
assertThat(targetManagement.isControllerAttributesRequested(knownControllerId)).isFalse();
targetManagement.requestControllerAttributes(knownControllerId);
final Target updated = targetManagement.getByControllerId(knownControllerId).get();
assertThat(target.isRequestControllerAttributes()).isFalse();
assertThat(targetManagement.findByControllerAttributesRequested(PAGE).getContent()).contains(updated);
assertThat(targetManagement.isControllerAttributesRequested(knownControllerId)).isTrue();
targetManagement.update(Update.builder().id(target.getId()).requestControllerAttributes(true).build());
final Target updated = targetManagement.getByControllerId(knownControllerId).orElseThrow();
assertThat(updated.isRequestControllerAttributes()).isTrue();
}
/**
@@ -949,8 +916,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@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) })
@Expect(type = TargetUpdatedEvent.class, count = 20) })
void targetTypeBulkAssignments() {
final List<Target> typeATargets = testdataFactory.createTargets(10, "typeATargets", "first description");
final List<Target> typeBTargets = testdataFactory.createTargets(10, "typeBTargets", "first description");
@@ -960,30 +926,16 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final TargetType typeB = testdataFactory.createTargetType("B", Set.of(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);
initiateTypeAssignment(typeATargets, typeA);
initiateTypeAssignment(typeBTargets, typeB);
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);
initiateTypeAssignment(typeATargets, typeA);
initiateTypeAssignment(typeBTargets, typeB);
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);
}
/**
@@ -1170,13 +1122,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet();
assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
"notExisting", ds.getId(),"name==*")).isFalse();
"notExisting", ds.getId(), "name==*")).isFalse();
}
/**
* Tests action based aspects of the dynamic group assignment filters.
*/
/**
* Target matches filter no active action with ge weight.
*/
@Test
@@ -1344,6 +1294,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
.as("target with too long address should not be updated")
.isThrownBy(() -> targetManagement.update(targetUpdate));
}
private void createTargetWithInvalidControllerId() {
final Create targetCreateEmpty = Create.builder().controllerId("").build();
assertThatExceptionOfType(ConstraintViolationException.class)
@@ -1424,8 +1375,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
private void checkTargetHasNotTags(final Iterable<Target> targets, final TargetTag... tags) {
for (final Target tl : targets) {
targetManagement.getByControllerId(tl.getControllerId()).get();
targetManagement.getByControllerId(tl.getControllerId()).orElseThrow();
for (final Tag tag : tags) {
for (final Tag tt : getTargetTags(tl.getControllerId())) {
if (tag.getName().equals(tt.getName())) {
@@ -1438,7 +1388,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
private void insertMetadata(final String knownKey, final String knownValue, final Target target) {
targetManagement.createMetadata(target.getControllerId(), Map.of(knownKey, knownValue));
assertThat(targetManagement.getMetadata(target.getControllerId()).get(knownKey)).isEqualTo(knownValue);
assertThat(targetManagement.getMetadata(target.getControllerId())).containsEntry(knownKey, knownValue);
}
private void checkTargetsHaveType(final List<Target> targets, final TargetType type) {
@@ -1461,14 +1411,11 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
return target;
}
private Target createTargetWithTargetTypeAndMetadata(final String controllerId, final TargetType targetType, final int count) {
private void createTargetWithTargetTypeAndMetadata(final String controllerId, final TargetType targetType, final int count) {
final Target target = testdataFactory.createTarget(controllerId, controllerId, targetType);
for (int index = 1; index <= count; index++) {
insertMetadata("key" + index, controllerId + "-value" + index, target);
}
return target;
}
private void createAction(final Target target, final Rollout rollout, final Integer weight, final Action.Status status,
@@ -1499,4 +1446,65 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
assertThat(foundTargetsByMetadataAndControllerId.getContent().stream().map(Target::getControllerId))
.as("Targets found by RSQL filter have wrong controller ids").containsExactlyInAnyOrder(controllerIds);
}
}
private long countByFilters(final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = buildSpecificationList(filterParams);
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
private List<Specification<JpaTarget>> buildSpecificationList(final FilterParams filterParams) {
final List<Specification<JpaTarget>> specList = new ArrayList<>();
if (hasTagsFilterActive(filterParams)) {
specList.add(hasTags(filterParams.filterByTagNames(), filterParams.selectTargetWithNoTag()));
}
return specList;
}
private static boolean hasTagsFilterActive(final FilterParams filterParams) {
final boolean isNoTagActive = Boolean.TRUE.equals(filterParams.selectTargetWithNoTag());
final boolean isAtLeastOneTagActive = filterParams.filterByTagNames() != null && filterParams.filterByTagNames().length > 0;
return isNoTagActive || isAtLeastOneTagActive;
}
/**
* {@link Specification} for retrieving {@link Target}s by "has no tag names"or "has at least on of the given tag names".
*
* @param tagNames to be filtered on
* @param selectTargetWithNoTag flag to get targets with no tag assigned
* @return the {@link Target} {@link Specification}
*/
private static Specification<JpaTarget> hasTags(final String[] tagNames, final Boolean selectTargetWithNoTag) {
return (targetRoot, query, cb) -> {
final Predicate predicate = getHasTagsPredicate(targetRoot, cb, selectTargetWithNoTag, tagNames);
query.distinct(true);
return predicate;
};
}
private static Predicate getHasTagsPredicate(
final Root<JpaTarget> targetRoot, final CriteriaBuilder cb, final Boolean selectTargetWithNoTag, final String[] tagNames) {
final SetJoin<JpaTarget, JpaTargetTag> tags = targetRoot.join(JpaTarget_.tags, JoinType.LEFT);
final Path<String> exp = tags.get(AbstractJpaNamedEntity_.name);
final List<Predicate> hasTagsPredicates = new ArrayList<>();
if (isNoTagActive(selectTargetWithNoTag)) {
hasTagsPredicates.add(exp.isNull());
}
if (isAtLeastOneTagActive(tagNames)) {
hasTagsPredicates.add(exp.in((Object[]) tagNames));
}
return hasTagsPredicates.stream().reduce(cb::or)
.orElseThrow(() -> new RuntimeException("Neither NO_TAG, nor TAG target tag filter was provided!"));
}
private static boolean isNoTagActive(final Boolean selectTargetWithNoTag) {
return Boolean.TRUE.equals(selectTargetWithNoTag);
}
private static boolean isAtLeastOneTagActive(final String[] tagNames) {
return tagNames != null && tagNames.length > 0;
}
private record FilterParams(Boolean selectTargetWithNoTag, String... filterByTagNames) {}
}