Refactor DS Management (#2591)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-08-05 15:45:41 +03:00
committed by GitHub
parent 049add05ac
commit 6aa8ccaa9c
39 changed files with 365 additions and 776 deletions

View File

@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Random; import java.util.Random;
import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonFactory;
@@ -38,8 +39,12 @@ import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiProgress; import org.eclipse.hawkbit.ddi.json.model.DdiProgress;
import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration; import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -396,4 +401,8 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].name") .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].name")
.value(findFirstModuleByType(ds, appType).orElseThrow().getName())); .value(findFirstModuleByType(ds, appType).orElseThrow().getName()));
} }
protected Optional<DistributionSet> findDsByAction(final long actionId) {
return deploymentManagement.findAction(actionId).map(Action::getDistributionSet);
}
} }

View File

@@ -119,7 +119,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(actionStatusRepository.count()).isEqualTo(2); assertThat(actionStatusRepository.count()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
getAndVerifyConfirmationBasePayload( getAndVerifyConfirmationBasePayload(
DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,

View File

@@ -187,7 +187,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(), artifactSignature, action.getId(),
findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced"); findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced");
@@ -287,7 +287,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, visibleMetadataOsKey, getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, visibleMetadataOsKey,
visibleMetadataOsValue, artifact, artifactSignature, action.getId(), "attempt", "attempt", visibleMetadataOsValue, artifact, artifactSignature, action.getId(), "attempt", "attempt",
@@ -344,7 +344,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(), artifactSignature, action.getId(),
findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced"); findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced");
@@ -409,7 +409,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, "metaDataVisible", getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, "metaDataVisible",
"withValue", artifact, artifactSignature, action.getId(), "forced", "skip", "withValue", artifact, artifactSignature, action.getId(), "forced", "skip",
getOsModule(findDistributionSetByAction)); getOsModule(findDistributionSetByAction));

View File

@@ -107,10 +107,7 @@ class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRestApi {
@AuditLog(entity = "DistributionSetTag", type = AuditLog.Type.DELETE, description = "Delete Distribution Set Tag") @AuditLog(entity = "DistributionSetTag", type = AuditLog.Type.DELETE, description = "Delete Distribution Set Tag")
public ResponseEntity<Void> deleteDistributionSetTag(final Long distributionsetTagId) { public ResponseEntity<Void> deleteDistributionSetTag(final Long distributionsetTagId) {
log.debug("Delete {} distribution set tag", distributionsetTagId); log.debug("Delete {} distribution set tag", distributionsetTagId);
final DistributionSetTag tag = findDistributionTagById(distributionsetTagId); distributionSetTagManagement.delete(distributionsetTagId);
distributionSetTagManagement.delete(tag.getName());
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }

View File

@@ -198,7 +198,7 @@ public abstract class AbstractManagementApiIntegrationTest extends AbstractRestI
static void implicitLock(final DistributionSet set) { static void implicitLock(final DistributionSet set) {
if (!set.isLocked()) { if (!set.isLocked()) {
((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1); ((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1);
((JpaDistributionSet) set).lock(); ((JpaDistributionSet) set).setLocked(true);
} }
} }
} }

View File

@@ -851,7 +851,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@WithUser(principal = "uploadTester", allSpPermissions = true) @WithUser(principal = "uploadTester", allSpPermissions = true)
void getDistributionSets() throws Exception { void getDistributionSets() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
DistributionSet set = testdataFactory.createDistributionSet("one"); DistributionSet set = testdataFactory.createDistributionSet("one");
set = distributionSetManagement.update(DistributionSetManagement.Update.builder().id(set.getId()) set = distributionSetManagement.update(DistributionSetManagement.Update.builder().id(set.getId())
@@ -860,7 +860,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
// load also lazy stuff // load also lazy stuff
set = distributionSetManagement.getWithDetails(set.getId()).get(); set = distributionSetManagement.getWithDetails(set.getId()).get();
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(1); assertThat(distributionSetManagement.findAll(PAGE)).hasSize(1);
// perform request // perform request
mvc.perform(get("/rest/v1/distributionsets").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/distributionsets").accept(MediaType.APPLICATION_JSON))
@@ -930,7 +930,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
@WithUser(principal = "uploadTester", allSpPermissions = true) @WithUser(principal = "uploadTester", allSpPermissions = true)
void createDistributionSets() throws Exception { void createDistributionSets() throws Exception {
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final SoftwareModule ah = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_APP); final SoftwareModule ah = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_APP);
final SoftwareModule jvm = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_RT); final SoftwareModule jvm = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_RT);
final SoftwareModule os = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_OS); final SoftwareModule os = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_OS);
@@ -966,7 +966,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.hasToString(String.valueOf(three.getId())); .hasToString(String.valueOf(three.getId()));
// check in database // check in database
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(3); assertThat(distributionSetManagement.findAll(PAGE)).hasSize(3);
assertThat(one.isRequiredMigrationStep()).isFalse(); assertThat(one.isRequiredMigrationStep()).isFalse();
assertThat(two.isRequiredMigrationStep()).isFalse(); assertThat(two.isRequiredMigrationStep()).isFalse();
assertThat(three.isRequiredMigrationStep()).isTrue(); assertThat(three.isRequiredMigrationStep()).isTrue();
@@ -982,11 +982,11 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
void deleteUnassignedistributionSet() throws Exception { void deleteUnassignedistributionSet() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(1); assertThat(distributionSetManagement.findAll(PAGE)).hasSize(1);
// perform request // perform request
mvc.perform(delete("/rest/v1/distributionsets/{smId}", set.getId())) mvc.perform(delete("/rest/v1/distributionsets/{smId}", set.getId()))
@@ -994,7 +994,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(status().isOk()); .andExpect(status().isOk());
// check repository content // check repository content
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
assertThat(distributionSetManagement.count()).isZero(); assertThat(distributionSetManagement.count()).isZero();
} }
@@ -1014,13 +1014,13 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
void deleteAssignedDistributionSet() throws Exception { void deleteAssignedDistributionSet() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
testdataFactory.createTarget("test"); testdataFactory.createTarget("test");
assignDistributionSet(set.getId(), "test"); assignDistributionSet(set.getId(), "test");
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(1); assertThat(distributionSetManagement.findAll(PAGE)).hasSize(1);
mvc.perform(get("/rest/v1/distributionsets/{dsId}", set.getId())) mvc.perform(get("/rest/v1/distributionsets/{dsId}", set.getId()))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
@@ -1037,7 +1037,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(jsonPath("$.deleted", equalTo(true))); .andExpect(jsonPath("$.deleted", equalTo(true)));
// check repository content // check repository content
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
} }
/** /**
@@ -1046,7 +1046,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
void updateDistributionSet() throws Exception { void updateDistributionSet() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
assertThat(distributionSetManagement.count()).isEqualTo(1); assertThat(distributionSetManagement.count()).isEqualTo(1);
@@ -1081,7 +1081,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
void updateRequiredMigrationStepFailsIfDistributionSetisInUse() throws Exception { void updateRequiredMigrationStepFailsIfDistributionSetisInUse() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
assignDistributionSet(set.getId(), testdataFactory.createTarget().getControllerId()); assignDistributionSet(set.getId(), testdataFactory.createTarget().getControllerId());
@@ -1723,7 +1723,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
void lockDistributionSet() throws Exception { void lockDistributionSet() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
assertThat(distributionSetManagement.count()).isEqualTo(1); assertThat(distributionSetManagement.count()).isEqualTo(1);
@@ -1747,11 +1747,11 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
@Test @Test
void unlockDistributionSet() throws Exception { void unlockDistributionSet() throws Exception {
// prepare test data // prepare test data
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty(); assertThat(distributionSetManagement.findAll(PAGE)).isEmpty();
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
assertThat(distributionSetManagement.count()).isEqualTo(1); assertThat(distributionSetManagement.count()).isEqualTo(1);
distributionSetManagement.lock(set.getId()); distributionSetManagement.lock(set);
assertThat(distributionSetManagement.get(set.getId()) assertThat(distributionSetManagement.get(set.getId())
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, set.getId())).isLocked()) .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, set.getId())).isLocked())
.as("Distribution set should be locked") .as("Distribution set should be locked")

View File

@@ -119,7 +119,7 @@ public interface DeploymentManagement {
* target and multi-assignment is disabled * target and multi-assignment is disabled
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(Collection<Entry<String, Long>> assignments, String initiatedBy); List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(String initiatedBy, Collection<Entry<String, Long>> assignments);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY) @PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(Collection<Entry<String, Long>> assignments); List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(Collection<Entry<String, Long>> assignments);

View File

@@ -79,13 +79,36 @@ public interface DistributionSetManagement<T extends DistributionSet>
@PreAuthorize(HAS_READ_REPOSITORY) @PreAuthorize(HAS_READ_REPOSITORY)
T getOrElseThrowException(long id); T getOrElseThrowException(long id);
@PreAuthorize(HAS_READ_REPOSITORY)
boolean shouldLockImplicitly(final DistributionSet distributionSet);
/**
* Locks a distribution set. From then on its functional properties could not be changed, and it could be assigned to targets
*
* @param distributionSet the distribution set
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
T lock(final DistributionSet distributionSet);
/**
* Unlocks a distribution set.<br/>
* Use it with extreme care! In general once distribution set is locked it shall not be unlocked. Note that it could have been assigned /
* deployed to targets.
*
* @param distributionSet the distribution set
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
T unlock(final DistributionSet distributionSet);
/** /**
* Sets the specified {@link DistributionSet} as invalidated. * Sets the specified {@link DistributionSet} as invalidated.
* *
* @param distributionSet the ID of the {@link DistributionSet} to be set to invalid * @param distributionSet the ID of the {@link DistributionSet} to be set to invalid
*/ */
@PreAuthorize(HAS_UPDATE_REPOSITORY) @PreAuthorize(HAS_UPDATE_REPOSITORY)
void invalidate(T distributionSet); T invalidate(DistributionSet distributionSet);
/** /**
* Assigns {@link SoftwareModule} to existing {@link DistributionSet}. * Assigns {@link SoftwareModule} to existing {@link DistributionSet}.
@@ -137,37 +160,6 @@ public interface DistributionSetManagement<T extends DistributionSet>
@PreAuthorize(HAS_UPDATE_REPOSITORY) @PreAuthorize(HAS_UPDATE_REPOSITORY)
List<T> unassignTag(@NotEmpty Collection<Long> ids, long tagId); List<T> unassignTag(@NotEmpty Collection<Long> ids, long tagId);
/**
* Locks a distribution set. From then on its functional properties could not be changed, and it could be assigned to targets
*
* @param id the distribution set id
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
T lock(final long id);
/**
* Unlocks a distribution set.<br/>
* Use it with extreme care! In general once distribution set is locked it shall not be unlocked. Note that it could have been assigned /
* deployed to targets.
*
* @param id the distribution set id
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
T unlock(final long id);
/**
* Find distribution set by id and throw an exception if it is deleted or invalidated.
*
* @param id id of {@link DistributionSet}
* @return the found valid {@link DistributionSet}
* @throws EntityNotFoundException if distribution set with given ID does not exist
* @throws InvalidDistributionSetException if distribution set with given ID is invalidated
*/
@PreAuthorize(HAS_READ_REPOSITORY)
T getValid(long id);
/** /**
* Find distribution set by id and throw an exception if it is deleted, incomplete or invalidated. * Find distribution set by id and throw an exception if it is deleted, incomplete or invalidated.
* *
@@ -180,16 +172,6 @@ public interface DistributionSetManagement<T extends DistributionSet>
@PreAuthorize(HAS_READ_REPOSITORY) @PreAuthorize(HAS_READ_REPOSITORY)
T getValidAndComplete(long id); T getValidAndComplete(long id);
/**
* Retrieves the distribution set for a given action.
*
* @param actionId the action associated with the distribution set
* @return the distribution set which is associated with the action
* @throws EntityNotFoundException if action with given ID does not exist
*/
@PreAuthorize(HAS_READ_REPOSITORY)
Optional<T> findByAction(long actionId);
/** /**
* Find distribution set by name and version. * Find distribution set by name and version.
* *
@@ -200,27 +182,6 @@ public interface DistributionSetManagement<T extends DistributionSet>
@PreAuthorize(HAS_READ_REPOSITORY) @PreAuthorize(HAS_READ_REPOSITORY)
Optional<T> findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version); Optional<T> findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version);
/**
* Finds all {@link DistributionSet}s based on completeness.
*
* @param complete to <code>true</code> for returning only completed distribution sets or <code>false</code> for only incomplete ones nor
* <code>null</code> to return both.
* @param pageable the pagination parameter
* @return all found {@link DistributionSet}s
*/
@PreAuthorize(HAS_READ_REPOSITORY)
Slice<T> findByCompleted(Boolean complete, @NotNull Pageable pageable);
/**
* Retrieves {@link DistributionSet}s by filtering on the given parameters.
*
* @param distributionSetFilter has details of filters to be applied.
* @param pageable page parameter
* @return the page of found {@link DistributionSet}
*/
@PreAuthorize(HAS_READ_REPOSITORY)
Slice<T> findByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter, @NotNull Pageable pageable);
/** /**
* Retrieves {@link DistributionSet}s by filtering on the given parameters. * Retrieves {@link DistributionSet}s by filtering on the given parameters.
* *
@@ -247,46 +208,6 @@ public interface DistributionSetManagement<T extends DistributionSet>
@PreAuthorize(HAS_READ_REPOSITORY) @PreAuthorize(HAS_READ_REPOSITORY)
Page<T> findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable); Page<T> findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable);
/**
* Counts all {@link DistributionSet}s based on completeness.
*
* @param complete to <code>true</code> for counting only completed distribution sets or <code>false</code> for only incomplete ones
* nor <code>null</code> to count both.
* @return count of all found {@link DistributionSet}s
*/
@PreAuthorize(HAS_READ_REPOSITORY)
long countByCompleted(Boolean complete);
/**
* Counts all {@link DistributionSet}s in repository based on given filter.
*
* @param distributionSetFilter has details of filters to be applied.
* @return count of {@link DistributionSet}s
*/
@PreAuthorize(HAS_READ_REPOSITORY)
long countByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter);
/**
* Count all {@link DistributionSet}s in the repository that are not marked
* as deleted.
*
* @param typeId to look for
* @return number of {@link DistributionSet}s
* @throws EntityNotFoundException if type with given ID does not exist
*/
@PreAuthorize(HAS_READ_REPOSITORY)
long countByTypeId(long typeId);
/**
* Checks if a {@link DistributionSet} is currently in use by a target in
* the repository.
*
* @param id to check
* @return <code>true</code> if in use
*/
@PreAuthorize(HAS_READ_REPOSITORY)
boolean isInUse(long id);
/** /**
* Count all {@link org.eclipse.hawkbit.repository.model.Rollout}s by status for * Count all {@link org.eclipse.hawkbit.repository.model.Rollout}s by status for
* Distribution Set. * Distribution Set.
@@ -298,8 +219,7 @@ public interface DistributionSetManagement<T extends DistributionSet>
List<Statistic> countRolloutsByStatusForDistributionSet(@NotNull Long id); List<Statistic> countRolloutsByStatusForDistributionSet(@NotNull Long id);
/** /**
* Count all {@link org.eclipse.hawkbit.repository.model.Action}s by status for * Count all {@link org.eclipse.hawkbit.repository.model.Action}s by status for Distribution Set.
* Distribution Set.
* *
* @param id to look for * @param id to look for
* @return List of Statistics for {@link org.eclipse.hawkbit.repository.model.Action}s status counts * @return List of Statistics for {@link org.eclipse.hawkbit.repository.model.Action}s status counts
@@ -308,8 +228,7 @@ public interface DistributionSetManagement<T extends DistributionSet>
List<Statistic> countActionsByStatusForDistributionSet(@NotNull Long id); List<Statistic> countActionsByStatusForDistributionSet(@NotNull Long id);
/** /**
* Count all {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s * Count all {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s for Distribution Set.
* for Distribution Set.
* *
* @param id to look for * @param id to look for
* @return number of {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s * @return number of {@link TargetFilterQueryManagement.AutoAssignDistributionSetUpdate}s

View File

@@ -37,36 +37,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
public interface DistributionSetTagManagement<T extends DistributionSetTag> public interface DistributionSetTagManagement<T extends DistributionSetTag>
extends RepositoryManagement<T, DistributionSetTagManagement.Create, DistributionSetTagManagement.Update> { extends RepositoryManagement<T, DistributionSetTagManagement.Create, DistributionSetTagManagement.Update> {
/**
* Find {@link DistributionSet} based on given name.
*
* @param name to look for.
* @return {@link DistributionSet}
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByName(@NotEmpty String name);
/**
* Finds all {@link TargetTag} assigned to given {@link Target}.
*
* @param distributionSetId of the {@link DistributionSet}
* @param pageable information for page size, offset and sort order.
* @return page of the found {@link TargetTag}s
* @throws EntityNotFoundException if {@link DistributionSet} with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Page<T> findByDistributionSet(long distributionSetId, @NotNull Pageable pageable);
/**
* Deletes {@link DistributionSetTag} by given
* {@link DistributionSetTag#getName()}.
*
* @param tagName to be deleted
* @throws EntityNotFoundException if tag with given name does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY)
void delete(@NotEmpty String tagName);
@SuperBuilder @SuperBuilder
@Getter @Getter
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)

View File

@@ -173,7 +173,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
@Override @Override
public String toString() { public String toString() {
return getClass().getSimpleName() + " [id=" + getId() + "]"; return getClass().getSimpleName() + " [id=" + getId() + " / optLockRevision=" + getOptLockRevision() + "]";
} }
@PostPersist @PostPersist
@@ -203,9 +203,9 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
} }
protected boolean isController() { protected boolean isController() {
return SecurityContextHolder.getContext().getAuthentication() != null return SecurityContextHolder.getContext().getAuthentication() != null &&
&& SecurityContextHolder.getContext().getAuthentication() SecurityContextHolder.getContext().getAuthentication().getDetails()
.getDetails() instanceof TenantAwareAuthenticationDetails tenantAwareDetails instanceof TenantAwareAuthenticationDetails tenantAwareDetails &&
&& tenantAwareDetails.isController(); tenantAwareDetails.isController();
} }
} }

View File

@@ -75,7 +75,7 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn
@Override @Override
public String toString() { public String toString() {
return getClass().getSimpleName() + " [tenant=" + getTenant() + ", id=" + getId() + "]"; return getClass().getSimpleName() + " [tenant=" + getTenant() + ", id=" + getId() + " / optLockRevision=" + getOptLockRevision() + "]";
} }
/** /**

View File

@@ -173,7 +173,7 @@ public abstract class AbstractJpaBaseEntity implements BaseEntity {
@Override @Override
public String toString() { public String toString() {
return getClass().getSimpleName() + " [id=" + getId() + "]"; return getClass().getSimpleName() + " [id=" + getId() + " / optLockRevision=" + getOptLockRevision() + "]";
} }
@PostPersist @PostPersist

View File

@@ -71,7 +71,7 @@ public abstract class AbstractJpaTenantAwareBaseEntity extends AbstractJpaBaseEn
@Override @Override
public String toString() { public String toString() {
return getClass().getSimpleName() + " [tenant=" + getTenant() + ", id=" + getId() + "]"; return getClass().getSimpleName() + " [tenant=" + getTenant() + ", id=" + getId() + " / optLockRevision=" + getOptLockRevision() + "]";
} }
/** /**

View File

@@ -588,7 +588,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
systemSecurityContext.runAsSystem(() -> systemSecurityContext.runAsSystem(() ->
distributionSetManagement.findByNameAndVersion(distributionName, version).map( distributionSetManagement.findByNameAndVersion(distributionName, version).map(
distributionSet -> deploymentManagement.offlineAssignedDistributionSets( distributionSet -> deploymentManagement.offlineAssignedDistributionSets(
List.of(Map.entry(controllerId, distributionSet.getId())), controllerId)) controllerId, List.of(Map.entry(controllerId, distributionSet.getId()))))
.orElseThrow(() -> .orElseThrow(() ->
new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version)))); new EntityNotFoundException(DistributionSet.class, Map.entry(distributionName, version))));

View File

@@ -180,40 +180,41 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
public List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy, public List<DistributionSetAssignmentResult> assignDistributionSets(
final List<DeploymentRequest> deploymentRequests, final String actionMessage) { final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
return assignDistributionSets0(initiatedBy, deploymentRequests, actionMessage); return assignDistributionSets0(initiatedBy, deploymentRequests, actionMessage);
} }
private List<DistributionSetAssignmentResult> assignDistributionSets0(final String initiatedBy, private List<DistributionSetAssignmentResult> assignDistributionSets0(
final List<DeploymentRequest> deploymentRequests, final String actionMessage) { final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage) {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(deploymentRequests); WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(deploymentRequests);
return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy); return assignDistributionSets(initiatedBy, deploymentRequests, actionMessage, onlineDsAssignmentStrategy);
} }
@Override @Override
public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(final Collection<Entry<String, Long>> assignments, public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(
final String initiatedBy) { final String initiatedBy, final Collection<Entry<String, Long>> assignments) {
final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList(); final Collection<Entry<String, Long>> distinctAssignments = assignments.stream().distinct().toList();
enforceMaxAssignmentsPerRequest(distinctAssignments.size()); enforceMaxAssignmentsPerRequest(distinctAssignments.size());
final List<DeploymentRequest> deploymentRequests = distinctAssignments.stream() final List<DeploymentRequest> deploymentRequests = distinctAssignments.stream()
.map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build()).toList(); .map(entry -> DeploymentManagement.deploymentRequest(entry.getKey(), entry.getValue()).build()).toList();
return assignDistributionSets(auditorAware.getCurrentAuditor().orElse(tenantAware.getCurrentUsername()), deploymentRequests, null, return assignDistributionSets(
auditorAware.getCurrentAuditor().orElse(tenantAware.getCurrentUsername()), deploymentRequests, null,
offlineDsAssignmentStrategy); offlineDsAssignmentStrategy);
} }
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(final Collection<Entry<String, Long>> assignments) { public List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(final Collection<Entry<String, Long>> assignments) {
return offlineAssignedDistributionSets(assignments, tenantAware.getCurrentUsername()); return offlineAssignedDistributionSets(tenantAware.getCurrentUsername(), assignments);
} }
@Override @Override
@Transactional(isolation = Isolation.READ_COMMITTED) @Transactional(isolation = Isolation.READ_COMMITTED)
@Retryable(retryFor = { @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action cancelAction(final long actionId) { public Action cancelAction(final long actionId) {
return cancelAction0(actionId); return cancelAction0(actionId);
} }
@@ -452,7 +453,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
startScheduledActions(groupScheduledActions.getContent()); startScheduledActions(groupScheduledActions.getContent());
return groupScheduledActions.getTotalElements(); return groupScheduledActions.getTotalElements();
} }
}) > 0) ; }) > 0);
} }
@Override @Override
@@ -483,7 +484,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
@Override @Override
@Transactional(readOnly = false) @Transactional
public int deleteActionsByStatusAndLastModifiedBefore(final Set<Status> status, final long lastModified) { public int deleteActionsByStatusAndLastModifiedBefore(final Set<Status> status, final long lastModified) {
if (status.isEmpty()) { if (status.isEmpty()) {
return 0; return 0;
@@ -590,8 +591,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return template; return template;
} }
private List<DistributionSetAssignmentResult> assignDistributionSets(final String initiatedBy, private List<DistributionSetAssignmentResult> assignDistributionSets(
final List<DeploymentRequest> deploymentRequests, final String actionMessage, final AbstractDsAssignmentStrategy strategy) { final String initiatedBy, final List<DeploymentRequest> deploymentRequests, final String actionMessage,
final AbstractDsAssignmentStrategy strategy) {
final List<DeploymentRequest> validatedRequests = validateAndFilterRequestForAssignments(deploymentRequests); final List<DeploymentRequest> validatedRequests = validateAndFilterRequestForAssignments(deploymentRequests);
final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests); final Map<Long, List<TargetWithActionType>> assignmentsByDsIds = convertRequest(validatedRequests);
@@ -720,10 +722,15 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private DistributionSetAssignmentResult assignDistributionSetToTargets( private DistributionSetAssignmentResult assignDistributionSetToTargets(
final String initiatedBy, final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage, final String initiatedBy, final Long dsId, final Collection<TargetWithActionType> targetsWithActionType, final String actionMessage,
final AbstractDsAssignmentStrategy assignmentStrategy) { final AbstractDsAssignmentStrategy assignmentStrategy) {
JpaDistributionSet distributionSet = distributionSetManagement.getValidAndComplete(dsId); final JpaDistributionSet dsValidAndComplete = distributionSetManagement.getValidAndComplete(dsId);
if (distributionSetManagement.isImplicitLockApplicable(distributionSet)) { final JpaDistributionSet distributionSet;
// without new transaction DS changed event is not thrown if (distributionSetManagement.shouldLockImplicitly(dsValidAndComplete)) {
distributionSet = DeploymentHelper.runInNewTransaction(txManager, "Implicit lock", status -> distributionSetManagement.lock(dsId)); // implicitly lock, for some reason no update happen if lock in same transaction
distributionSet = DeploymentHelper.runInNewTransaction(
txManager, "lockDistributionSet-" + dsId,
status -> distributionSetManagement.lock(dsValidAndComplete));
} else {
distributionSet = dsValidAndComplete;
} }
final List<String> providedTargetIds = targetsWithActionType.stream().map(TargetWithActionType::getControllerId).distinct().toList(); final List<String> providedTargetIds = targetsWithActionType.stream().map(TargetWithActionType::getControllerId).distinct().toList();
@@ -766,8 +773,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
// not active before and the manual assignment which has been done cancels them // not active before and the manual assignment which has been done cancels them
targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets); targetEntitiesIdsChunks.forEach(this::cancelInactiveScheduledActionsForTargets);
setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity, targetEntitiesIdsChunks); setAssignedDistributionSetAndTargetUpdateStatus(assignmentStrategy, distributionSetEntity, targetEntitiesIdsChunks);
final Map<TargetWithActionType, JpaAction> assignedActions = createActions(targetsWithActionType, targetEntities, distributionSetEntity, final Map<TargetWithActionType, JpaAction> assignedActions =
assignmentStrategy, initiatedBy); createActions(targetsWithActionType, targetEntities, distributionSetEntity, assignmentStrategy, initiatedBy);
// create initial action status when action is created, so we remember // create initial action status when action is created, so we remember
// the initial running status because we will change the status // the initial running status because we will change the status
// of the action itself and with this action status we have a nicer action history. // of the action itself and with this action status we have a nicer action history.
@@ -820,7 +827,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return persistedActions; return persistedActions;
} }
private void createActionsStatus(final Map<TargetWithActionType, JpaAction> actions, final AbstractDsAssignmentStrategy assignmentStrategy, private void createActionsStatus(
final Map<TargetWithActionType, JpaAction> actions, final AbstractDsAssignmentStrategy assignmentStrategy,
final String actionMessage) { final String actionMessage) {
actionStatusRepository.saveAll(actions.entrySet().stream().map(entry -> { actionStatusRepository.saveAll(actions.entrySet().stream().map(entry -> {
final JpaAction action = entry.getValue(); final JpaAction action = entry.getValue();

View File

@@ -132,10 +132,10 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
private void invalidateDistributionSet(final long setId, final CancelationType cancelationType, final boolean cancelRollouts) { private void invalidateDistributionSet(final long setId, final CancelationType cancelationType, final boolean cancelRollouts) {
final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId); final DistributionSet distributionSet = distributionSetManagement.getOrElseThrowException(setId);
if (!distributionSet.isComplete()) { if (!distributionSet.isComplete()) {
throw new IncompleteDistributionSetException("Distribution set of type " throw new IncompleteDistributionSetException(
+ distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId()); "Distribution set of type " + distributionSet.getType().getKey() + " is incomplete: " + distributionSet.getId());
} }
((DistributionSetManagement)distributionSetManagement).invalidate(distributionSet); distributionSetManagement.invalidate(distributionSet);
log.debug("Distribution set {} marked as invalid.", setId); log.debug("Distribution set {} marked as invalid.", setId);
// rollout cancellation should only be permitted with UPDATE_ROLLOUT permission // rollout cancellation should only be permitted with UPDATE_ROLLOUT permission

View File

@@ -13,7 +13,6 @@ import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_D
import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX; import static org.eclipse.hawkbit.repository.jpa.configuration.Constants.TX_RT_MAX;
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED; import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@@ -26,12 +25,10 @@ import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import jakarta.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.DistributionSetFields; import org.eclipse.hawkbit.repository.DistributionSetFields;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement; import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.QuotaManagement; import org.eclipse.hawkbit.repository.QuotaManagement;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
@@ -39,12 +36,10 @@ import org.eclipse.hawkbit.repository.exception.DeletedException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetTag;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule; import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
@@ -52,16 +47,11 @@ import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository; import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility; import org.eclipse.hawkbit.repository.jpa.rsql.RsqlUtility;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification; import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper; import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Statistic; import org.eclipse.hawkbit.repository.model.Statistic;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
@@ -70,13 +60,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnBooleanProp
import org.springframework.dao.ConcurrencyFailureException; import org.springframework.dao.ConcurrencyFailureException;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.retry.annotation.Backoff; import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable; import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@Service @Service
@@ -86,10 +73,8 @@ public class JpaDistributionSetManagement
implements DistributionSetManagement<JpaDistributionSet> { implements DistributionSetManagement<JpaDistributionSet> {
private final DistributionSetTagManagement<JpaDistributionSetTag> distributionSetTagManagement; private final DistributionSetTagManagement<JpaDistributionSetTag> distributionSetTagManagement;
private final DistributionSetTypeManagement<JpaDistributionSetType> distributionSetTypeManagement;
private final SoftwareModuleRepository softwareModuleRepository; private final SoftwareModuleRepository softwareModuleRepository;
private final DistributionSetTagRepository distributionSetTagRepository; private final DistributionSetTagRepository distributionSetTagRepository;
private final TargetRepository targetRepository;
private final TargetFilterQueryRepository targetFilterQueryRepository; private final TargetFilterQueryRepository targetFilterQueryRepository;
private final ActionRepository actionRepository; private final ActionRepository actionRepository;
private final QuotaManagement quotaManagement; private final QuotaManagement quotaManagement;
@@ -101,10 +86,8 @@ public class JpaDistributionSetManagement
final DistributionSetRepository jpaRepository, final DistributionSetRepository jpaRepository,
final EntityManager entityManager, final EntityManager entityManager,
final DistributionSetTagManagement<JpaDistributionSetTag> distributionSetTagManagement, final DistributionSetTagManagement<JpaDistributionSetTag> distributionSetTagManagement,
final DistributionSetTypeManagement<JpaDistributionSetType> distributionSetTypeManagement,
final SoftwareModuleRepository softwareModuleRepository, final SoftwareModuleRepository softwareModuleRepository,
final DistributionSetTagRepository distributionSetTagRepository, final DistributionSetTagRepository distributionSetTagRepository,
final TargetRepository targetRepository,
final TargetFilterQueryRepository targetFilterQueryRepository, final TargetFilterQueryRepository targetFilterQueryRepository,
final ActionRepository actionRepository, final ActionRepository actionRepository,
final QuotaManagement quotaManagement, final QuotaManagement quotaManagement,
@@ -113,10 +96,8 @@ public class JpaDistributionSetManagement
final RepositoryProperties repositoryProperties) { final RepositoryProperties repositoryProperties) {
super(jpaRepository, entityManager); super(jpaRepository, entityManager);
this.distributionSetTagManagement = distributionSetTagManagement; this.distributionSetTagManagement = distributionSetTagManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.softwareModuleRepository = softwareModuleRepository; this.softwareModuleRepository = softwareModuleRepository;
this.distributionSetTagRepository = distributionSetTagRepository; this.distributionSetTagRepository = distributionSetTagRepository;
this.targetRepository = targetRepository;
this.targetFilterQueryRepository = targetFilterQueryRepository; this.targetFilterQueryRepository = targetFilterQueryRepository;
this.actionRepository = actionRepository; this.actionRepository = actionRepository;
this.quotaManagement = quotaManagement; this.quotaManagement = quotaManagement;
@@ -133,11 +114,11 @@ public class JpaDistributionSetManagement
if (Boolean.TRUE.equals(update.getLocked())) { if (Boolean.TRUE.equals(update.getLocked())) {
if (!distributionSet.isLocked()) { if (!distributionSet.isLocked()) {
lockSoftwareModules(distributionSet); lockSoftwareModules(distributionSet);
distributionSet.lock(); distributionSet.setLocked(true);
} }
} else if (Boolean.FALSE.equals(update.getLocked())) { } else if (Boolean.FALSE.equals(update.getLocked())) {
if (distributionSet.isLocked()) { if (distributionSet.isLocked()) {
distributionSet.unlock(); distributionSet.setLocked(false);
} }
} }
@@ -173,16 +154,80 @@ public class JpaDistributionSetManagement
return jpaRepository.findOne(jpaRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL); return jpaRepository.findOne(jpaRepository.byIdSpec(id), JpaDistributionSet_.GRAPH_DISTRIBUTION_SET_DETAIL);
} }
@Override
public JpaDistributionSet getOrElseThrowException(final long id) {
return getById(id);
}
// implicitly lock a distribution set if not already locked and implicit lock is enabled and not to skip
@Override @Override
@Transactional @Transactional
public void invalidate(final JpaDistributionSet distributionSet) { @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
distributionSet.invalidate(); public boolean shouldLockImplicitly(final DistributionSet distributionSet) {
jpaRepository.save(distributionSet); final JpaDistributionSet jpaDistributionSet = toJpaDistributionSet(distributionSet);
if (jpaDistributionSet.isLocked()) {
// already locked
return false;
}
if (Boolean.FALSE.equals(tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class))) {
// implicit lock disabled
return false;
}
final List<String> skipForTags = repositoryProperties.getSkipImplicitLockForTags();
if (!ObjectUtils.isEmpty(skipForTags)) {
final Set<DistributionSetTag> tags = jpaDistributionSet.getTags();
if (!ObjectUtils.isEmpty(tags)) {
for (final DistributionSetTag tag : tags) {
if (skipForTags.contains(tag.getName())) {
// has a skip tag
return false;
}
}
}
}
// finally - implicitly lock
return true;
} }
@Override @Override
public JpaDistributionSet getOrElseThrowException(final long id) { @Transactional
return getById(id); @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public JpaDistributionSet lock(final DistributionSet distributionSet) {
final JpaDistributionSet jpaDistributionSet = toJpaDistributionSet(distributionSet);
if (distributionSet.isLocked()) {
return jpaDistributionSet;
} else {
if (!jpaDistributionSet.isComplete()) {
throw new IncompleteDistributionSetException("Could not be locked while incomplete!");
}
lockSoftwareModules(jpaDistributionSet);
jpaDistributionSet.setLocked(true);
return jpaRepository.save(jpaDistributionSet);
}
}
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public JpaDistributionSet unlock(final DistributionSet distributionSet) {
final JpaDistributionSet jpaDistributionSet = toJpaDistributionSet(distributionSet);
if (jpaDistributionSet.isLocked()) {
jpaDistributionSet.setLocked(false);
return jpaRepository.save(jpaDistributionSet);
} else {
return jpaDistributionSet;
}
}
@Override
@Transactional
public JpaDistributionSet invalidate(final DistributionSet distributionSet) {
final JpaDistributionSet jpaDistributionSet = toJpaDistributionSet(distributionSet);
jpaDistributionSet.invalidate();
return jpaRepository.save(jpaDistributionSet);
} }
@Override @Override
@@ -245,51 +290,6 @@ public class JpaDistributionSetManagement
}); });
} }
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public JpaDistributionSet lock(final long id) {
final JpaDistributionSet distributionSet = getById(id);
if (distributionSet.isLocked()) {
return distributionSet;
} else {
lockSoftwareModules(distributionSet);
distributionSet.lock();
return jpaRepository.save(distributionSet);
}
}
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public JpaDistributionSet unlock(final long id) {
final JpaDistributionSet distributionSet = getById(id);
if (distributionSet.isLocked()) {
distributionSet.unlock();
return jpaRepository.save(distributionSet);
} else {
return distributionSet;
}
}
@Override
public Optional<JpaDistributionSet> findByAction(final long actionId) {
return actionRepository
.findById(actionId)
.map(action -> {
if (!targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))) {
throw new InsufficientPermissionException("Target not accessible (or not found)!");
}
return jpaRepository
.findOne(DistributionSetSpecification.byIdFetch(action.getDistributionSet().getId()))
.orElseThrow(() ->
new InsufficientPermissionException("DistributionSet not accessible (or not found)!"));
})
.or(() -> {
throw new EntityNotFoundException(Action.class, actionId);
});
}
@Override @Override
public Optional<JpaDistributionSet> findByNameAndVersion(final String distributionName, final String version) { public Optional<JpaDistributionSet> findByNameAndVersion(final String distributionName, final String version) {
return jpaRepository.findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version)); return jpaRepository.findOne(DistributionSetSpecification.equalsNameAndVersionIgnoreCase(distributionName, version));
@@ -311,35 +311,6 @@ public class JpaDistributionSetManagement
return distributionSet; return distributionSet;
} }
@Override
public JpaDistributionSet getValid(final long id) {
return getValid0(id);
}
@Override
public Slice<JpaDistributionSet> findByCompleted(final Boolean complete, final Pageable pageReq) {
final List<Specification<JpaDistributionSet>> specifications = buildSpecsByComplete(complete);
return JpaManagementHelper.findAllWithoutCountBySpec(jpaRepository, specifications, pageReq);
}
@Override
public long countByCompleted(final Boolean complete) {
return JpaManagementHelper.countBySpec(jpaRepository, buildSpecsByComplete(complete));
}
@Override
public Slice<JpaDistributionSet> findByDistributionSetFilter(final DistributionSetFilter distributionSetFilter, final Pageable pageable) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(distributionSetFilter);
return JpaManagementHelper.findAllWithoutCountBySpec(jpaRepository, specList, pageable);
}
@Override
public long countByDistributionSetFilter(@NotNull final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(distributionSetFilter);
return JpaManagementHelper.countBySpec(jpaRepository, specList);
}
@Override @Override
public Page<JpaDistributionSet> findByTag(final long tagId, final Pageable pageable) { public Page<JpaDistributionSet> findByTag(final long tagId, final Pageable pageable) {
assertDsTagExists(tagId); assertDsTagExists(tagId);
@@ -357,20 +328,6 @@ public class JpaDistributionSetManagement
pageable); pageable);
} }
@Override
public long countByTypeId(final long typeId) {
if (!distributionSetTypeManagement.exists(typeId)) {
throw new EntityNotFoundException(DistributionSetType.class, typeId);
}
return jpaRepository.count(DistributionSetSpecification.byType(typeId));
}
@Override
public boolean isInUse(final long id) {
assertDistributionSetExists(id);
return actionRepository.countByDistributionSetId(id) > 0;
}
@Override @Override
public List<Statistic> countRolloutsByStatusForDistributionSet(final Long id) { public List<Statistic> countRolloutsByStatusForDistributionSet(final Long id) {
assertDistributionSetExists(id); assertDistributionSetExists(id);
@@ -400,70 +357,6 @@ public class JpaDistributionSetManagement
QuotaHelper.assertAssignmentQuota(requested, maxMetaData, String.class, DistributionSet.class); QuotaHelper.assertAssignmentQuota(requested, maxMetaData, String.class, DistributionSet.class);
} }
// check if it shall implicitly lock a distribution set
boolean isImplicitLockApplicable(final DistributionSet distributionSet) {
final JpaDistributionSet jpaDistributionSet = (JpaDistributionSet) distributionSet;
if (jpaDistributionSet.isLocked()) {
// already locked
return false;
}
if (Boolean.FALSE.equals(tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class))) {
// implicit lock disabled
return false;
}
final List<String> skipForTags = repositoryProperties.getSkipImplicitLockForTags();
if (!ObjectUtils.isEmpty(skipForTags)) {
final Set<DistributionSetTag> tags = jpaDistributionSet.getTags();
if (!ObjectUtils.isEmpty(tags)) {
for (final DistributionSetTag tag : tags) {
if (skipForTags.contains(tag.getName())) {
// has a skip tag
return false;
}
}
}
}
// finally - implicit lock is applicable
return true;
}
private static List<Specification<JpaDistributionSet>> buildDistributionSetSpecifications(
final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>(10);
if (distributionSetFilter.getIsComplete() != null) {
specList.add(DistributionSetSpecification.isCompleted(distributionSetFilter.getIsComplete()));
}
if (distributionSetFilter.getIsDeleted() != null) {
specList.add(DistributionSetSpecification.isDeleted(distributionSetFilter.getIsDeleted()));
}
if (distributionSetFilter.getIsValid() != null) {
specList.add(DistributionSetSpecification.isValid(distributionSetFilter.getIsValid()));
}
if (distributionSetFilter.getTypeId() != null) {
specList.add(DistributionSetSpecification.byType(distributionSetFilter.getTypeId()));
}
if (!ObjectUtils.isEmpty(distributionSetFilter.getSearchText())) {
final String[] dsFilterNameAndVersionEntries = JpaManagementHelper
.getFilterNameAndVersionEntries(distributionSetFilter.getSearchText().trim());
specList.add(DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0], dsFilterNameAndVersionEntries[1]));
}
if (hasTagsFilterActive(distributionSetFilter)) {
specList.add(DistributionSetSpecification.hasTags(
distributionSetFilter.getTagNames(), distributionSetFilter.getSelectDSWithNoTag()));
}
return specList;
}
private static boolean hasTagsFilterActive(final DistributionSetFilter distributionSetFilter) {
final boolean isNoTagActive = Boolean.TRUE.equals(distributionSetFilter.getSelectDSWithNoTag());
final boolean isAtLeastOneTagActive = !CollectionUtils.isEmpty(distributionSetFilter.getTagNames());
return isNoTagActive || isAtLeastOneTagActive;
}
private static Collection<Long> notFound(final Collection<Long> distributionSetIds, final List<JpaDistributionSet> foundDistributionSets) { private static Collection<Long> notFound(final Collection<Long> distributionSetIds, final List<JpaDistributionSet> foundDistributionSets) {
final Map<Long, JpaDistributionSet> foundDistributionSetMap = foundDistributionSets.stream() final Map<Long, JpaDistributionSet> foundDistributionSetMap = foundDistributionSets.stream()
.collect(Collectors.toMap(JpaDistributionSet::getId, Function.identity())); .collect(Collectors.toMap(JpaDistributionSet::getId, Function.identity()));
@@ -507,15 +400,6 @@ public class JpaDistributionSetManagement
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId)); .orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
} }
private List<Specification<JpaDistributionSet>> buildSpecsByComplete(final Boolean complete) {
final List<Specification<JpaDistributionSet>> specifications = new ArrayList<>();
specifications.add(DistributionSetSpecification.isNotDeleted());
if (complete != null) {
specifications.add(DistributionSetSpecification.isCompleted(complete));
}
return specifications;
}
private void assertSoftwareModuleQuota(final Long id, final int requested) { private void assertSoftwareModuleQuota(final Long id, final int requested) {
QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(), QuotaHelper.assertAssignmentQuota(id, requested, quotaManagement.getMaxSoftwareModulesPerDistributionSet(),
SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId); SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId);
@@ -544,6 +428,14 @@ public class JpaDistributionSetManagement
.orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id)); .orElseThrow(() -> new EntityNotFoundException(DistributionSet.class, id));
} }
private JpaDistributionSet toJpaDistributionSet(final DistributionSet distributionSet) {
if (distributionSet instanceof JpaDistributionSet jpaDistributionSet) {
return entityManager.merge(jpaDistributionSet); // if from
} else {
return getById(distributionSet.getId());
}
}
private void assertDistributionSetExists(final long id) { private void assertDistributionSetExists(final long id) {
if (!jpaRepository.existsById(id)) { if (!jpaRepository.existsById(id)) {
throw new EntityNotFoundException(DistributionSet.class, id); throw new EntityNotFoundException(DistributionSet.class, id);

View File

@@ -43,39 +43,9 @@ public class JpaDistributionSetTagManagement
extends AbstractJpaRepositoryManagement<JpaDistributionSetTag, DistributionSetTagManagement.Create, DistributionSetTagManagement.Update, DistributionSetTagRepository, DistributionSetTagFields> extends AbstractJpaRepositoryManagement<JpaDistributionSetTag, DistributionSetTagManagement.Create, DistributionSetTagManagement.Update, DistributionSetTagRepository, DistributionSetTagFields>
implements DistributionSetTagManagement<JpaDistributionSetTag> { implements DistributionSetTagManagement<JpaDistributionSetTag> {
private final DistributionSetRepository distributionSetRepository;
protected JpaDistributionSetTagManagement( protected JpaDistributionSetTagManagement(
final DistributionSetTagRepository distributionSetTagRepository, final DistributionSetTagRepository distributionSetTagRepository,
final EntityManager entityManager, final EntityManager entityManager) {
final DistributionSetRepository distributionSetRepository) {
super(distributionSetTagRepository, entityManager); super(distributionSetTagRepository, entityManager);
this.distributionSetRepository = distributionSetRepository;
}
@Override
public Optional<JpaDistributionSetTag> findByName(final String name) {
return jpaRepository.findByNameEquals(name);
}
@Override
public Page<JpaDistributionSetTag> findByDistributionSet(final long distributionSetId, final Pageable pageable) {
if (!distributionSetRepository.existsById(distributionSetId)) {
throw new EntityNotFoundException(DistributionSet.class, distributionSetId);
}
return JpaManagementHelper.findAllWithCountBySpec(jpaRepository,
Collections.singletonList(TagSpecification.ofDistributionSet(distributionSetId)), pageable
);
}
@Override
@Transactional
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = TX_RT_MAX, backoff = @Backoff(delay = TX_RT_DELAY))
public void delete(final String tagName) {
final JpaDistributionSetTag dsTag = jpaRepository
.findOne(DistributionSetTagSpecifications.byName(tagName))
.orElseThrow(() -> new EntityNotFoundException(DistributionSetTag.class, tagName));
jpaRepository.delete(dsTag);
} }
} }

View File

@@ -564,8 +564,8 @@ public class JpaRolloutManagement implements RolloutManagement {
rollout.setTotalTargets(totalTargets); rollout.setTotalTargets(totalTargets);
} }
if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) { if (distributionSetManagement.shouldLockImplicitly(distributionSet)) {
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet);
} }
if (rollout.getWeight().isEmpty()) { if (rollout.getWeight().isEmpty()) {

View File

@@ -33,7 +33,6 @@ import org.eclipse.hawkbit.repository.exception.InvalidAutoAssignActionTypeExcep
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper; import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery; import org.eclipse.hawkbit.repository.jpa.model.JpaTargetFilterQuery;
import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetFilterQueryRepository;
@@ -164,11 +163,10 @@ class JpaTargetFilterQueryManagement
} else { } else {
WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update); WeightValidationHelper.usingContext(systemSecurityContext, tenantConfigurationManagement).validate(update);
assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.dsId()); assertMaxTargetsQuota(targetFilterQuery.getQuery(), targetFilterQuery.getName(), update.dsId());
final JpaDistributionSet distributionSet = (JpaDistributionSet) distributionSetManagement
.getValidAndComplete(update.dsId());
if (((JpaDistributionSetManagement) distributionSetManagement).isImplicitLockApplicable(distributionSet)) { DistributionSet distributionSet = distributionSetManagement.getValidAndComplete(update.dsId());
distributionSetManagement.lock(distributionSet.getId()); if (distributionSetManagement.shouldLockImplicitly(distributionSet)) {
distributionSet = distributionSetManagement.lock(distributionSet);
} }
targetFilterQuery.setAutoAssignDistributionSet(distributionSet); targetFilterQuery.setAutoAssignDistributionSet(distributionSet);

View File

@@ -20,6 +20,7 @@ import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
@@ -29,6 +30,7 @@ import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
@NoArgsConstructor(access = AccessLevel.PROTECTED) // Default constructor needed for JPA entities @NoArgsConstructor(access = AccessLevel.PROTECTED) // Default constructor needed for JPA entities
@Setter @Setter
@Getter @Getter
@ToString(callSuper = true)
@MappedSuperclass @MappedSuperclass
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@SuppressWarnings("squid:S2160") @SuppressWarnings("squid:S2160")

View File

@@ -16,12 +16,18 @@ import jakarta.persistence.MappedSuperclass;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.NamedEntity; import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity; import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
/** /**
* Extension for {@link NamedEntity} that are versioned. * Extension for {@link NamedEntity} that are versioned.
*/ */
@Setter
@Getter
@ToString(callSuper = true)
@MappedSuperclass @MappedSuperclass
// exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities
@SuppressWarnings("squid:S2160") @SuppressWarnings("squid:S2160")
@@ -50,13 +56,4 @@ public abstract class AbstractJpaNamedVersionedEntity extends AbstractJpaNamedEn
AbstractJpaNamedVersionedEntity() { AbstractJpaNamedVersionedEntity() {
// Default constructor needed for JPA entities // Default constructor needed for JPA entities
} }
@Override
public String getVersion() {
return version;
}
public void setVersion(final String version) {
this.version = version;
}
} }

View File

@@ -124,6 +124,7 @@ public class JpaDistributionSet
@Column(name = "complete") @Column(name = "complete")
private boolean complete; private boolean complete;
@Setter
@Column(name = "locked") @Column(name = "locked")
private boolean locked; private boolean locked;
@@ -213,31 +214,18 @@ public class JpaDistributionSet
return tags.remove(tag); return tags.remove(tag);
} }
public void lock() {
if (!isComplete()) {
throw new IncompleteDistributionSetException("Could not be locked while incomplete!");
}
locked = true;
}
public void unlock() {
locked = false;
}
public void invalidate() { public void invalidate() {
this.valid = false; this.valid = false;
} }
@Override @Override
public void fireCreateEvent() { public void fireCreateEvent() {
publishEventWithEventPublisher( publishEventWithEventPublisher(new DistributionSetCreatedEvent(this));
new DistributionSetCreatedEvent(this));
} }
@Override @Override
public void fireUpdateEvent() { public void fireUpdateEvent() {
publishEventWithEventPublisher( publishEventWithEventPublisher(new DistributionSetUpdatedEvent(this, complete));
new DistributionSetUpdatedEvent(this, complete));
if (deleted) { if (deleted) {
publishEventWithEventPublisher(new DistributionSetDeletedEvent(getTenant(), getId(), getClass())); publishEventWithEventPublisher(new DistributionSetDeletedEvent(getTenant(), getId(), getClass()));

View File

@@ -19,7 +19,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaStatistic;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
@@ -65,16 +64,6 @@ public interface DistributionSetRepository extends BaseEntityRepository<JpaDistr
@Query(value = "SELECT COUNT(f.autoAssignDistributionSet) FROM JpaTargetFilterQuery f WHERE f.autoAssignDistributionSet.id = :dsId GROUP BY f.autoAssignDistributionSet") @Query(value = "SELECT COUNT(f.autoAssignDistributionSet) FROM JpaTargetFilterQuery f WHERE f.autoAssignDistributionSet.id = :dsId GROUP BY f.autoAssignDistributionSet")
Long countAutoAssignmentsForDistributionSet(@Param("dsId") Long dsId); Long countAutoAssignmentsForDistributionSet(@Param("dsId") Long dsId);
/**
* Finds {@link DistributionSet}s where given {@link SoftwareModule} is assigned.
* <p/>
* No access control applied.
*
* @param moduleId to search for
* @return {@link List} of found {@link DistributionSet}s
*/
Long countByModulesId(Long moduleId);
/** /**
* Finds {@link DistributionSet}s based on given ID that are assigned yet to an {@link Action}, i.e. in use. * Finds {@link DistributionSet}s based on given ID that are assigned yet to an {@link Action}, i.e. in use.
* <p/> * <p/>

View File

@@ -30,14 +30,6 @@ import org.springframework.transaction.annotation.Transactional;
public interface DistributionSetTagRepository public interface DistributionSetTagRepository
extends BaseEntityRepository<JpaDistributionSetTag> { extends BaseEntityRepository<JpaDistributionSetTag> {
/**
* find {@link DistributionSetTag} by its name.
*
* @param tagName to filter on
* @return the {@link DistributionSetTag} if found, otherwise null
*/
Optional<JpaDistributionSetTag> findByNameEquals(String tagName);
/** /**
* Returns all instances of the type. * Returns all instances of the type.
* *
@@ -58,4 +50,4 @@ public interface DistributionSetTagRepository
@Transactional @Transactional
@Query("DELETE FROM JpaDistributionSetTag t WHERE t.tenant = :tenant") @Query("DELETE FROM JpaDistributionSetTag t WHERE t.tenant = :tenant")
void deleteByTenant(@Param("tenant") String tenant); void deleteByTenant(@Param("tenant") String tenant);
} }

View File

@@ -38,17 +38,6 @@ public interface DistributionSetTypeRepository extends BaseEntityRepository<JpaD
*/ */
long countByElementsSmType(JpaSoftwareModuleType softwareModuleType); long countByElementsSmType(JpaSoftwareModuleType softwareModuleType);
/**
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety reasons (this is a "delete everything" query after all) we add
* the tenant manually to query even if this will by done by {@link EntityManager} anyhow. The DB should take care of optimizing this away.
*
* @param tenant to delete data from
*/
@Modifying
@Transactional
@Query("DELETE FROM JpaDistributionSetType t WHERE t.tenant = :tenant")
void deleteByTenant(@Param("tenant") String tenant);
/** /**
* Counts the {@link SoftwareModuleType}s which are associated with the addressed {@link DistributionSetType}. * Counts the {@link SoftwareModuleType}s which are associated with the addressed {@link DistributionSetType}.
* <p/> * <p/>
@@ -59,4 +48,15 @@ public interface DistributionSetTypeRepository extends BaseEntityRepository<JpaD
*/ */
@Query("SELECT COUNT (e.smType) FROM DistributionSetTypeElement e WHERE e.dsType.id = :id") @Query("SELECT COUNT (e.smType) FROM DistributionSetTypeElement e WHERE e.dsType.id = :id")
long countSmTypesById(@Param("id") Long id); long countSmTypesById(@Param("id") Long id);
/**
* Deletes all {@link TenantAwareBaseEntity} of a given tenant. For safety reasons (this is a "delete everything" query after all) we add
* the tenant manually to query even if this will by done by {@link EntityManager} anyhow. The DB should take care of optimizing this away.
*
* @param tenant to delete data from
*/
@Modifying
@Transactional
@Query("DELETE FROM JpaDistributionSetType t WHERE t.tenant = :tenant")
void deleteByTenant(@Param("tenant") String tenant);
} }

View File

@@ -14,8 +14,10 @@ import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.run
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withUser; import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withUser;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
@@ -50,9 +52,13 @@ import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository; import org.eclipse.hawkbit.repository.jpa.repository.TenantMetaDataRepository;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -67,10 +73,15 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties; import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.Database;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
@Slf4j @Slf4j
@ContextConfiguration(classes = { JpaRepositoryConfiguration.class, TestConfiguration.class }) @ContextConfiguration(classes = { JpaRepositoryConfiguration.class, TestConfiguration.class })
@@ -86,9 +97,6 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
SpPermission.UPDATE_REPOSITORY, SpPermission.DELETE_REPOSITORY, SpPermission.READ_TARGET, SpPermission.CREATE_TARGET, SpPermission.UPDATE_REPOSITORY, SpPermission.DELETE_REPOSITORY, SpPermission.READ_TARGET, SpPermission.CREATE_TARGET,
SpPermission.UPDATE_TARGET, SpPermission.DELETE_TARGET); SpPermission.UPDATE_TARGET, SpPermission.DELETE_TARGET);
@PersistenceContext
protected EntityManager entityManager;
@Autowired @Autowired
protected TargetRepository targetRepository; protected TargetRepository targetRepository;
@Autowired @Autowired
@@ -307,4 +315,43 @@ public abstract class AbstractJpaIntegrationTest extends AbstractIntegrationTest
private JpaRollout refresh(final Rollout rollout) { private JpaRollout refresh(final Rollout rollout) {
return rolloutRepository.findById(rollout.getId()).get(); return rolloutRepository.findById(rollout.getId()).get();
} }
protected Slice<JpaDistributionSet> findDsByDistributionSetFilter(final DistributionSetFilter distributionSetFilter, final Pageable pageable) {
final List<Specification<JpaDistributionSet>> specList = buildDistributionSetSpecifications(distributionSetFilter);
return JpaManagementHelper.findAllWithoutCountBySpec(distributionSetRepository, specList, pageable);
}
private static List<Specification<JpaDistributionSet>> buildDistributionSetSpecifications(
final DistributionSetFilter distributionSetFilter) {
final List<Specification<JpaDistributionSet>> specList = new ArrayList<>(10);
if (distributionSetFilter.getIsComplete() != null) {
specList.add(DistributionSetSpecification.isCompleted(distributionSetFilter.getIsComplete()));
}
if (distributionSetFilter.getIsDeleted() != null) {
specList.add(DistributionSetSpecification.isDeleted(distributionSetFilter.getIsDeleted()));
}
if (distributionSetFilter.getIsValid() != null) {
specList.add(DistributionSetSpecification.isValid(distributionSetFilter.getIsValid()));
}
if (distributionSetFilter.getTypeId() != null) {
specList.add(DistributionSetSpecification.byType(distributionSetFilter.getTypeId()));
}
if (!ObjectUtils.isEmpty(distributionSetFilter.getSearchText())) {
final String[] dsFilterNameAndVersionEntries = JpaManagementHelper
.getFilterNameAndVersionEntries(distributionSetFilter.getSearchText().trim());
specList.add(DistributionSetSpecification.likeNameAndVersion(dsFilterNameAndVersionEntries[0], dsFilterNameAndVersionEntries[1]));
}
if (hasTagsFilterActive(distributionSetFilter)) {
specList.add(DistributionSetSpecification.hasTags(
distributionSetFilter.getTagNames(), distributionSetFilter.getSelectDSWithNoTag()));
}
return specList;
}
private static boolean hasTagsFilterActive(final DistributionSetFilter distributionSetFilter) {
final boolean isNoTagActive = Boolean.TRUE.equals(distributionSetFilter.getSelectDSWithNoTag());
final boolean isAtLeastOneTagActive = !CollectionUtils.isEmpty(distributionSetFilter.getTagNames());
return isNoTagActive || isAtLeastOneTagActive;
}
} }

View File

@@ -58,7 +58,6 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
final DistributionSet hidden = testdataFactory.createDistributionSet(); final DistributionSet hidden = testdataFactory.createDistributionSet();
final Action permittedAction = testdataFactory.performAssignment(permitted); final Action permittedAction = testdataFactory.performAssignment(permitted);
final Action hiddenAction = testdataFactory.performAssignment(hidden);
runAs(withUser("user", runAs(withUser("user",
READ_REPOSITORY, READ_REPOSITORY,
@@ -74,15 +73,6 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
assertThat(distributionSetManagement.findByRsql("name==*", Pageable.unpaged()).get().map(Identifiable::getId) assertThat(distributionSetManagement.findByRsql("name==*", Pageable.unpaged()).get().map(Identifiable::getId)
.toList()).containsOnly(permittedActionId); .toList()).containsOnly(permittedActionId);
// verify distributionSetManagement#findByCompleted
assertThat(distributionSetManagement.findByCompleted(true, Pageable.unpaged()).get().map(Identifiable::getId)
.toList()).containsOnly(permittedActionId);
// verify distributionSetManagement#findByDistributionSetFilter
assertThat(distributionSetManagement
.findByDistributionSetFilter(DistributionSetFilter.builder().isDeleted(false).build(), Pageable.unpaged())
.get().map(Identifiable::getId).toList()).containsOnly(permittedActionId);
// verify distributionSetManagement#get // verify distributionSetManagement#get
assertThat(distributionSetManagement.get(permittedActionId)).isPresent(); assertThat(distributionSetManagement.get(permittedActionId)).isPresent();
final Long hiddenId = hidden.getId(); final Long hiddenId = hidden.getId();
@@ -92,11 +82,6 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
assertThat(distributionSetManagement.getWithDetails(permittedActionId)).isPresent(); assertThat(distributionSetManagement.getWithDetails(permittedActionId)).isPresent();
assertThat(distributionSetManagement.getWithDetails(hiddenId)).isEmpty(); assertThat(distributionSetManagement.getWithDetails(hiddenId)).isEmpty();
// verify distributionSetManagement#get
assertThat(distributionSetManagement.getValid(permittedActionId).getId()).isEqualTo(permittedActionId);
assertThatThrownBy(() -> distributionSetManagement.getValid(hiddenId))
.as("Distribution set should not be found.").isInstanceOf(EntityNotFoundException.class);
// verify distributionSetManagement#get // verify distributionSetManagement#get
final List<Long> allActionIds = Arrays.asList(permittedActionId, hiddenId); final List<Long> allActionIds = Arrays.asList(permittedActionId, hiddenId);
assertThatThrownBy(() -> distributionSetManagement.get(allActionIds)) assertThatThrownBy(() -> distributionSetManagement.get(allActionIds))
@@ -105,12 +90,6 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
// verify distributionSetManagement#getByNameAndVersion // verify distributionSetManagement#getByNameAndVersion
assertThat(distributionSetManagement.findByNameAndVersion(permitted.getName(), permitted.getVersion())).isPresent(); assertThat(distributionSetManagement.findByNameAndVersion(permitted.getName(), permitted.getVersion())).isPresent();
assertThat(distributionSetManagement.findByNameAndVersion(hidden.getName(), hidden.getVersion())).isEmpty(); assertThat(distributionSetManagement.findByNameAndVersion(hidden.getName(), hidden.getVersion())).isEmpty();
// verify distributionSetManagement#getByAction
assertThat(distributionSetManagement.findByAction(permittedAction.getId())).isPresent();
final Long hiddenActionId = hiddenAction.getId();
assertThatThrownBy(() -> distributionSetManagement.findByAction(hiddenActionId))
.as("Action is hidden.").isInstanceOf(InsufficientPermissionException.class);
}); });
} }
@@ -254,9 +233,9 @@ class DistributionSetAccessControllerTest extends AbstractJpaIntegrationTest {
final DistributionSet readOnly = testdataFactory.createDistributionSet(); final DistributionSet readOnly = testdataFactory.createDistributionSet();
final DistributionSet hidden = testdataFactory.createDistributionSet(); final DistributionSet hidden = testdataFactory.createDistributionSet();
// has to lock them, otherwise implicit lock shall be made which require DistributionSet update permissions // has to lock them, otherwise implicit lock shall be made which require DistributionSet update permissions
distributionSetManagement.lock(permitted.getId()); distributionSetManagement.lock(permitted);
distributionSetManagement.lock(readOnly.getId()); distributionSetManagement.lock(readOnly);
distributionSetManagement.lock(hidden.getId()); distributionSetManagement.lock(hidden);
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build()); .create(TargetFilterQueryManagement.Create.builder().name("test").query("id==*").build());

View File

@@ -196,8 +196,8 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void verifyTargetAssignment() { void verifyTargetAssignment() {
final Long dsId = testdataFactory.createDistributionSet("myDs").getId(); final DistributionSet ds = testdataFactory.createDistributionSet("myDs");
distributionSetManagement.lock(dsId); distributionSetManagement.lock(ds);
final Target permittedTarget = targetManagement final Target permittedTarget = targetManagement
.create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED)); .create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED));
@@ -214,6 +214,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
READ_TARGET + "/controllerId==" + permittedTarget.getControllerId(), READ_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
UPDATE_TARGET + "/controllerId==" + permittedTarget.getControllerId(), UPDATE_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
READ_REPOSITORY), () -> { READ_REPOSITORY), () -> {
final Long dsId = ds.getId();
assertThat(assignDistributionSet(dsId, permittedTarget.getControllerId()).getAssigned()).isEqualTo(1); assertThat(assignDistributionSet(dsId, permittedTarget.getControllerId()).getAssigned()).isEqualTo(1);
// assigning of not allowed target behaves as not found // assigning of not allowed target behaves as not found
assertThatThrownBy(() -> assignDistributionSet(dsId, hiddenTargetControllerId)).isInstanceOf(AssertionError.class); assertThatThrownBy(() -> assignDistributionSet(dsId, hiddenTargetControllerId)).isInstanceOf(AssertionError.class);
@@ -233,10 +234,10 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void verifyTargetAssignmentOnNonUpdatableTarget() { void verifyTargetAssignmentOnNonUpdatableTarget() {
final Long firstDsId = testdataFactory.createDistributionSet("myDs").getId(); final DistributionSet firstDs = testdataFactory.createDistributionSet("myDs");
distributionSetManagement.lock(firstDsId); distributionSetManagement.lock(firstDs);
final DistributionSet secondDs = testdataFactory.createDistributionSet("anotherDs"); final DistributionSet secondDs = testdataFactory.createDistributionSet("anotherDs");
distributionSetManagement.lock(secondDs.getId()); distributionSetManagement.lock(secondDs);
final Target manageableTarget = targetManagement final Target manageableTarget = targetManagement
.create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED)); .create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED));
@@ -247,6 +248,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
READ_TARGET + "/controllerId==" + manageableTarget.getControllerId() + " or controllerId==" + readOnlyTarget.getControllerId(), READ_TARGET + "/controllerId==" + manageableTarget.getControllerId() + " or controllerId==" + readOnlyTarget.getControllerId(),
UPDATE_TARGET + "/controllerId==" + manageableTarget.getControllerId(), UPDATE_TARGET + "/controllerId==" + manageableTarget.getControllerId(),
READ_REPOSITORY), () -> { READ_REPOSITORY), () -> {
final Long firstDsId = firstDs.getId();
// assignment is permitted for manageableTarget // assignment is permitted for manageableTarget
assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned()).isEqualTo(1); assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned()).isEqualTo(1);
@@ -267,7 +269,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
@Test @Test
void verifyRolloutTargetScope() { void verifyRolloutTargetScope() {
final DistributionSet ds = testdataFactory.createDistributionSet("myDs"); final DistributionSet ds = testdataFactory.createDistributionSet("myDs");
distributionSetManagement.lock(ds.getId()); distributionSetManagement.lock(ds);
final String[] updateTargetControllerIds = { "update1", "update2", "update3" }; final String[] updateTargetControllerIds = { "update1", "update2", "update3" };
final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds); final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds);
@@ -307,7 +309,7 @@ class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
@Test @Test
void verifyAutoAssignmentTargetScope() { void verifyAutoAssignmentTargetScope() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet(); final DistributionSet distributionSet = testdataFactory.createDistributionSet();
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet);
final String[] updateTargetControllerIds = { "update1", "update2", "update3" }; final String[] updateTargetControllerIds = { "update1", "update2", "update3" };
final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds); final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds);

View File

@@ -63,7 +63,7 @@ class DeploymentManagementSecurityTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void offlineAssignedDistributionSetsWithInitiatedByPermissionsCheck() { void offlineAssignedDistributionSetsWithInitiatedByPermissionsCheck() {
assertPermissions(() -> deploymentManagement.offlineAssignedDistributionSets(List.of(), "initiator"), assertPermissions(() -> deploymentManagement.offlineAssignedDistributionSets("initiator", List.of()),
List.of(SpPermission.READ_REPOSITORY, SpPermission.UPDATE_TARGET)); List.of(SpPermission.READ_REPOSITORY, SpPermission.UPDATE_TARGET));
} }

View File

@@ -1356,7 +1356,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
} }
// verify that deleted attribute is used correctly // verify that deleted attribute is used correctly
List<? extends DistributionSet> allFoundDS = distributionSetManagement.findByCompleted(true, PAGE).getContent(); List<? extends DistributionSet> allFoundDS = distributionSetManagement.findAll(PAGE).getContent();
assertThat(allFoundDS).as("no ds should be founded").isEmpty(); assertThat(allFoundDS).as("no ds should be founded").isEmpty();
assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays
@@ -1368,16 +1368,13 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
// try to delete again // try to delete again
distributionSetManagement.delete(deploymentResult.getDistributionSetIDs()); distributionSetManagement.delete(deploymentResult.getDistributionSetIDs());
// verify that the result is the same, even though distributionSet dsA // verify that the result is the same, even though distributionSet dsA has been installed
// has been installed // successfully and no activeAction is referring to created distribution sets
// successfully and no activeAction is referring to created distribution allFoundDS = distributionSetManagement.findAll(pageRequest).getContent();
// sets
allFoundDS = distributionSetManagement.findByCompleted(true, pageRequest).getContent();
assertThat(allFoundDS).as("no ds should be founded").isEmpty(); assertThat(allFoundDS).as("no ds should be founded").isEmpty();
assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays assertThat(distributionSetRepository.findAll(SpecificationsBuilder.combineWithAnd(Arrays
.asList(DistributionSetSpecification.isDeleted(true), DistributionSetSpecification.isCompleted(true))), .asList(DistributionSetSpecification.isDeleted(true), DistributionSetSpecification.isCompleted(true))),
PAGE).getContent()).as("wrong size of founded ds").hasSize(noOfDistributionSets); PAGE).getContent()).as("wrong size of founded ds").hasSize(noOfDistributionSets);
} }
/** /**

View File

@@ -14,11 +14,8 @@ import java.util.Map;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest; import org.eclipse.hawkbit.repository.jpa.AbstractRepositoryManagementSecurityTest;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
@@ -119,10 +116,8 @@ class DistributionSetManagementSecurityTest
*/ */
@Test @Test
void lockPermissionsCheck() { void lockPermissionsCheck() {
assertPermissions(() -> { final DistributionSet ds = testdataFactory.createDistributionSet();
distributionSetManagement.lock(1L); assertPermissions(() -> distributionSetManagement.lock(ds), List.of(SpPermission.UPDATE_REPOSITORY));
return null;
}, List.of(SpPermission.UPDATE_REPOSITORY));
} }
/** /**
@@ -130,18 +125,8 @@ class DistributionSetManagementSecurityTest
*/ */
@Test @Test
void unlockPermissionsCheck() { void unlockPermissionsCheck() {
assertPermissions(() -> { final DistributionSet ds = testdataFactory.createDistributionSet();
distributionSetManagement.unlock(1L); assertPermissions(() -> distributionSetManagement.unlock(ds), List.of(SpPermission.UPDATE_REPOSITORY));
return null;
}, List.of(SpPermission.UPDATE_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void getByActionPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.findByAction(1L), List.of(SpPermission.READ_REPOSITORY));
} }
/** /**
@@ -168,14 +153,6 @@ class DistributionSetManagementSecurityTest
assertPermissions(() -> distributionSetManagement.getValidAndComplete(1L), List.of(SpPermission.READ_REPOSITORY)); assertPermissions(() -> distributionSetManagement.getValidAndComplete(1L), List.of(SpPermission.READ_REPOSITORY));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void getValidPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.getValid(1L), List.of(SpPermission.READ_REPOSITORY));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */
@@ -184,40 +161,6 @@ class DistributionSetManagementSecurityTest
assertPermissions(() -> distributionSetManagement.getOrElseThrowException(1L), List.of(SpPermission.READ_REPOSITORY)); assertPermissions(() -> distributionSetManagement.getOrElseThrowException(1L), List.of(SpPermission.READ_REPOSITORY));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByCompletedPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.findByCompleted(true, PAGE), List.of(SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByCompletedPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.countByCompleted(true), List.of(SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByDistributionSetFilterPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.findByDistributionSetFilter(DistributionSetFilter.builder().build(), PAGE),
List.of(SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByDistributionSetFilterPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.countByDistributionSetFilter(DistributionSetFilter.builder().build()),
List.of(SpPermission.READ_REPOSITORY));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */
@@ -234,14 +177,6 @@ class DistributionSetManagementSecurityTest
assertPermissions(() -> distributionSetManagement.findByRsqlAndTag("rsql", 1L, PAGE), List.of(SpPermission.READ_REPOSITORY)); assertPermissions(() -> distributionSetManagement.findByRsqlAndTag("rsql", 1L, PAGE), List.of(SpPermission.READ_REPOSITORY));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void isInUsePermissionsCheck() {
assertPermissions(() -> distributionSetManagement.isInUse(1L), List.of(SpPermission.READ_REPOSITORY));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */
@@ -250,14 +185,6 @@ class DistributionSetManagementSecurityTest
assertPermissions(() -> distributionSetManagement.unassignSoftwareModule(1L, 1L), List.of(SpPermission.UPDATE_REPOSITORY)); assertPermissions(() -> distributionSetManagement.unassignSoftwareModule(1L, 1L), List.of(SpPermission.UPDATE_REPOSITORY));
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void countByTypeIdPermissionsCheck() {
assertPermissions(() -> distributionSetManagement.countByTypeId(1L), List.of(SpPermission.READ_REPOSITORY));
}
/** /**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions. * Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/ */
@@ -287,13 +214,8 @@ class DistributionSetManagementSecurityTest
*/ */
@Test @Test
void invalidatePermissionsCheck() { void invalidatePermissionsCheck() {
final DistributionSetType dsType = distributionSetTypeManagement.create(DistributionSetTypeManagement.Create.builder() final DistributionSet ds = testdataFactory.createDistributionSet();
.key("type").name("name").build()); assertPermissions(() -> distributionSetManagement.invalidate(ds),
final DistributionSet ds = distributionSetManagement.create(DistributionSetManagement.Create.builder() List.of(SpPermission.UPDATE_REPOSITORY, SpPermission.READ_REPOSITORY));
.type(dsType).name("test").version("1.0.0").build());
assertPermissions(() -> {
((DistributionSetManagement) distributionSetManagement).invalidate(ds);
return null;
}, List.of(SpPermission.UPDATE_REPOSITORY, SpPermission.READ_REPOSITORY));
} }
} }

View File

@@ -42,7 +42,6 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdated
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent; import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException; import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException; import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException; import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException; import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
@@ -117,8 +116,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> distributionSetManagement.assignSoftwareModules(set.getId(), singletonList(NOT_EXIST_IDL)), "SoftwareModule"); () -> distributionSetManagement.assignSoftwareModules(set.getId(), singletonList(NOT_EXIST_IDL)), "SoftwareModule");
verifyThrownExceptionBy(() -> distributionSetManagement.countByTypeId(NOT_EXIST_IDL), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.unassignSoftwareModule(NOT_EXIST_IDL, module.getId()), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.unassignSoftwareModule(NOT_EXIST_IDL, module.getId()), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.unassignSoftwareModule(set.getId(), NOT_EXIST_IDL), "SoftwareModule"); verifyThrownExceptionBy(() -> distributionSetManagement.unassignSoftwareModule(set.getId(), NOT_EXIST_IDL), "SoftwareModule");
@@ -143,27 +140,17 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(NOT_EXIST_IDL, "xxx"), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(NOT_EXIST_IDL, "xxx"), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(set.getId(), NOT_EXIST_ID), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(set.getId(), NOT_EXIST_ID), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.findByAction(NOT_EXIST_IDL), "Action");
verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get("xxx"), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get("xxx"), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get(PAGE), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL), "DistributionSet");
assertThatThrownBy(() -> distributionSetManagement.isInUse(NOT_EXIST_IDL))
.isInstanceOf(EntityNotFoundException.class).hasMessageContaining(NOT_EXIST_ID)
.hasMessageContaining("DistributionSet");
verifyThrownExceptionBy( verifyThrownExceptionBy(
() -> distributionSetManagement.update(DistributionSetManagement.Update.builder().id(NOT_EXIST_IDL).build()), () -> distributionSetManagement.update(DistributionSetManagement.Update.builder().id(NOT_EXIST_IDL).build()),
"DistributionSet"); "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.createMetadata(NOT_EXIST_IDL, "xxx", "xxx"), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.createMetadata(NOT_EXIST_IDL, "xxx", "xxx"), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.getValidAndComplete(NOT_EXIST_IDL), "DistributionSet"); verifyThrownExceptionBy(() -> distributionSetManagement.getValidAndComplete(NOT_EXIST_IDL), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetManagement.getValid(NOT_EXIST_IDL), "DistributionSet");
} }
/** /**
@@ -305,7 +292,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
.as("ds has wrong tag size") .as("ds has wrong tag size")
.hasSize(1)); .hasSize(1));
final DistributionSetTag findDistributionSetTag = getOrThrow(distributionSetTagManagement.findByName(TAG1_NAME)); final DistributionSetTag findDistributionSetTag = getOrThrow(distributionSetTagManagement.get(tag.getId()));
assertThat(assignedDS) assertThat(assignedDS)
.as("assigned ds has wrong size") .as("assigned ds has wrong size")
@@ -315,7 +302,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
.unassignTag(List.of(assignDS.get(0)), findDistributionSetTag.getId()).get(0); .unassignTag(List.of(assignDS.get(0)), findDistributionSetTag.getId()).get(0);
assertThat(unAssignDS.getId()).as("unassigned ds is wrong").isEqualTo(assignDS.get(0)); assertThat(unAssignDS.getId()).as("unassigned ds is wrong").isEqualTo(assignDS.get(0));
assertThat(unAssignDS.getTags()).as("unassigned ds has wrong tag size").isEmpty(); assertThat(unAssignDS.getTags()).as("unassigned ds has wrong tag size").isEmpty();
assertThat(distributionSetTagManagement.findByName(TAG1_NAME)).isPresent(); assertThat(distributionSetTagManagement.get(tag.getId())).isPresent();
assertThat(distributionSetManagement.findByTag(tag.getId(), PAGE).getNumberOfElements()) assertThat(distributionSetManagement.findByTag(tag.getId(), PAGE).getNumberOfElements())
.as("ds tag ds has wrong ds size").isEqualTo(3); .as("ds tag ds has wrong ds size").isEqualTo(3);
@@ -534,7 +521,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
assertThat(reloadedDS.getLastModifiedAt()).isPositive(); assertThat(reloadedDS.getLastModifiedAt()).isPositive();
// verify updated meta data is the updated value // verify updated meta data is the updated value
assertThat(distributionSetManagement.getMetadata(ds.getId()).get(knownKey)).isEqualTo(knownUpdateValue); assertThat(distributionSetManagement.getMetadata(ds.getId())).containsEntry(knownKey, knownUpdateValue);
} }
/** /**
@@ -578,11 +565,11 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
dsDeleted = getOrThrow(distributionSetManagement.get(dsDeleted.getId())); dsDeleted = getOrThrow(distributionSetManagement.get(dsDeleted.getId()));
dsGroup1 = assignTag(dsGroup1, dsTagA); dsGroup1 = assignTag(dsGroup1, dsTagA);
dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName())); dsTagA = getOrThrow(distributionSetTagRepository.findById(dsTagA.getId()));
dsGroup1 = assignTag(dsGroup1, dsTagB); dsGroup1 = assignTag(dsGroup1, dsTagB);
dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName())); dsTagA = getOrThrow(distributionSetTagRepository.findById(dsTagA.getId()));
dsGroup2 = assignTag(dsGroup2, dsTagA); dsGroup2 = assignTag(dsGroup2, dsTagA);
dsTagA = getOrThrow(distributionSetTagRepository.findByNameEquals(dsTagA.getName())); dsTagA = getOrThrow(distributionSetTagRepository.findById(dsTagA.getId()));
final List<? extends DistributionSet> allDistributionSets = Stream final List<? extends DistributionSet> allDistributionSets = Stream
.of(dsGroup1, dsGroup2, Arrays.asList(dsDeleted, dsInComplete, dsNewType)).flatMap(Collection::stream) .of(dsGroup1, dsGroup2, Arrays.asList(dsDeleted, dsInComplete, dsNewType)).flatMap(Collection::stream)
@@ -607,33 +594,19 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, dsGroup2Prefix); validateDeletedAndCompletedAndTypeAndSearchTextAndTag(dsGroup2, dsTagA, dsGroup2Prefix);
} }
/**
* Simple DS load without the related data that should be loaded lazy.
*/
@Test
void findDistributionSetsWithoutLazy() {
testdataFactory.createDistributionSets(20);
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(20);
}
/** /**
* Locks a DS. * Locks a DS.
*/ */
@Test @Test
void lockDistributionSet() { void lockDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1");
assertThat( assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(true)).isFalse();
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(true)) distributionSetManagement.lock(distributionSet);
.isFalse(); assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)).isTrue();
distributionSetManagement.lock(distributionSet.getId());
assertThat(
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false))
.isTrue();
// assert software modules are locked // assert software modules are locked
assertThat(distributionSet.getModules().size()).isNotZero(); assertThat(distributionSet.getModules().size()).isNotZero();
distributionSetManagement.getWithDetails(distributionSet.getId()).map(DistributionSet::getModules) distributionSetManagement.getWithDetails(distributionSet.getId()).map(DistributionSet::getModules).orElseThrow()
.orElseThrow().forEach(module -> assertThat(module.isLocked()).isTrue()); .forEach(module -> assertThat(module.isLocked()).isTrue());
} }
/** /**
@@ -642,11 +615,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void deleteUnassignedLockedDistributionSet() { void deleteUnassignedLockedDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1");
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet);
assertThat( assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)).isTrue();
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked)
.orElse(false))
.isTrue();
distributionSetManagement.delete(distributionSet.getId()); distributionSetManagement.delete(distributionSet.getId());
assertThat(distributionSetManagement.get(distributionSet.getId())).isEmpty(); assertThat(distributionSetManagement.get(distributionSet.getId())).isEmpty();
@@ -658,11 +628,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void deleteAssignedLockedDistributionSet() { void deleteAssignedLockedDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1");
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet);
assertThat( assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)).isTrue();
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked)
.orElse(false))
.isTrue();
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
assignDistributionSet(distributionSet.getId(), target.getControllerId()); assignDistributionSet(distributionSet.getId(), target.getControllerId());
@@ -676,21 +643,15 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void unlockDistributionSet() { void unlockDistributionSet() {
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1");
distributionSetManagement.lock(distributionSet.getId()); distributionSet = distributionSetManagement.lock(distributionSet);
assertThat( assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)).isTrue();
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked) distributionSet = distributionSetManagement.unlock(distributionSet);
.orElse(false)) assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(true)).isFalse();
.isTrue();
distributionSetManagement.unlock(distributionSet.getId());
assertThat(
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked)
.orElse(true))
.isFalse();
// assert software modules are not unlocked // assert software modules are not unlocked
assertThat(distributionSet.getModules().size()).isNotZero(); assertThat(distributionSet.getModules().size()).isNotZero();
distributionSetManagement.getWithDetails(distributionSet.getId()).map(DistributionSet::getModules) distributionSetManagement.getWithDetails(distributionSet.getId()).map(DistributionSet::getModules).orElseThrow()
.orElseThrow().forEach(module -> assertThat(module.isLocked()).isTrue()); .forEach(module -> assertThat(module.isLocked()).isTrue());
} }
/** /**
@@ -701,8 +662,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1"); final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1");
final int softwareModuleCount = distributionSet.getModules().size(); final int softwareModuleCount = distributionSet.getModules().size();
assertThat(softwareModuleCount).isNotZero(); assertThat(softwareModuleCount).isNotZero();
distributionSetManagement.lock(distributionSet);
final Long distributionSetId = distributionSet.getId(); final Long distributionSetId = distributionSet.getId();
distributionSetManagement.lock(distributionSetId);
assertThat(distributionSetManagement.get(distributionSetId).map(DistributionSet::isLocked).orElse(false)).isTrue(); assertThat(distributionSetManagement.get(distributionSetId).map(DistributionSet::isLocked).orElse(false)).isTrue();
// try add // try add
@@ -710,16 +671,16 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
assertThatExceptionOfType(LockedException.class) assertThatExceptionOfType(LockedException.class)
.as("Attempt to modify a locked DS software modules should throw an exception") .as("Attempt to modify a locked DS software modules should throw an exception")
.isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSetId, moduleIds)); .isThrownBy(() -> distributionSetManagement.assignSoftwareModules(distributionSetId, moduleIds));
assertThat(distributionSetManagement.getWithDetails(distributionSetId).get().getModules()) assertThat(distributionSetManagement.getWithDetails(distributionSetId).orElseThrow().getModules())
.as("Software module shall not be added to a locked DS.") .as("Software module shall not be added to a locked DS.")
.hasSize(softwareModuleCount); .hasSize(softwareModuleCount);
// try remove // try remove
final Long fisrtModuleId = distributionSet.getModules().stream().findFirst().get().getId(); final Long firstModuleId = distributionSet.getModules().stream().findFirst().orElseThrow().getId();
assertThatExceptionOfType(LockedException.class) assertThatExceptionOfType(LockedException.class)
.as("Attempt to modify a locked DS software modules should throw an exception") .as("Attempt to modify a locked DS software modules should throw an exception")
.isThrownBy(() -> distributionSetManagement.unassignSoftwareModule(distributionSetId, fisrtModuleId)); .isThrownBy(() -> distributionSetManagement.unassignSoftwareModule(distributionSetId, firstModuleId));
assertThat(distributionSetManagement.getWithDetails(distributionSetId).get().getModules()) assertThat(distributionSetManagement.getWithDetails(distributionSetId).orElseThrow().getModules())
.as("Software module shall not be removed from a locked DS.") .as("Software module shall not be removed from a locked DS.")
.hasSize(softwareModuleCount); .hasSize(softwareModuleCount);
} }
@@ -729,11 +690,11 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@Test @Test
void isImplicitLockApplicableForDistributionSet() { void shouldLockImplicitlyForDistributionSet() {
final JpaDistributionSetManagement distributionSetManagement = (JpaDistributionSetManagement) (DistributionSetManagement) this.distributionSetManagement; final JpaDistributionSetManagement distributionSetManagement = (JpaDistributionSetManagement) (DistributionSetManagement) this.distributionSetManagement;
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-non-skip"); final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-non-skip");
// assert that implicit lock is applicable for non skip tags // assert that implicit lock is applicable for non skip tags
assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSet)).isTrue(); assertThat(distributionSetManagement.shouldLockImplicitly(distributionSet)).isTrue();
assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotZero(); assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotZero();
final List<? extends DistributionSetTag> skipTags = distributionSetTagManagement.create( final List<? extends DistributionSetTag> skipTags = distributionSetTagManagement.create(
@@ -750,7 +711,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
distributionSetManagement.assignTag(List.of(distributionSetWithSkipTag.getId()), skipTag.getId()); distributionSetManagement.assignTag(List.of(distributionSetWithSkipTag.getId()), skipTag.getId());
distributionSetWithSkipTag = distributionSetManagement.get(distributionSetWithSkipTag.getId()).orElseThrow(); distributionSetWithSkipTag = distributionSetManagement.get(distributionSetWithSkipTag.getId()).orElseThrow();
// assert that implicit lock isn't applicable for skip tags // assert that implicit lock isn't applicable for skip tags
assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSetWithSkipTag)).isFalse(); assertThat(distributionSetManagement.shouldLockImplicitly(distributionSetWithSkipTag)).isFalse();
}); });
} }
@@ -759,12 +720,12 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
*/ */
@Test @Test
void lockIncompleteDistributionSetFails() { void lockIncompleteDistributionSetFails() {
final long incompleteDistributionSetId = testdataFactory.createIncompleteDistributionSet().getId(); final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
assertThatExceptionOfType(IncompleteDistributionSetException.class) assertThatExceptionOfType(IncompleteDistributionSetException.class)
.as("Locking an incomplete distribution set should throw an exception") .as("Locking an incomplete distribution set should throw an exception")
.isThrownBy(() -> distributionSetManagement.lock(incompleteDistributionSetId)); .isThrownBy(() -> distributionSetManagement.lock(incompleteDistributionSet));
assertThat( assertThat(
distributionSetManagement.get(incompleteDistributionSetId).map(DistributionSet::isLocked).orElse(true)) distributionSetManagement.get(incompleteDistributionSet.getId()).map(DistributionSet::isLocked).orElse(true))
.isFalse(); .isFalse();
} }
@@ -781,7 +742,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
distributionSetManagement.delete(ds1.getId()); distributionSetManagement.delete(ds1.getId());
// not assigned so not marked as deleted but fully deleted // not assigned so not marked as deleted but fully deleted
assertThat(distributionSetRepository.findAll()).hasSize(1); assertThat(distributionSetRepository.findAll()).hasSize(1);
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(1);
} }
/** /**
@@ -851,7 +811,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
// not assigned so not marked as deleted // not assigned so not marked as deleted
assertThat(distributionSetRepository.findAll()).hasSize(4); assertThat(distributionSetRepository.findAll()).hasSize(4);
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).hasSize(2);
assertThat(distributionSetManagement.findAll(PAGE)).hasSize(2); assertThat(distributionSetManagement.findAll(PAGE)).hasSize(2);
assertThat(distributionSetManagement.findByRsql("name==*", PAGE)).hasSize(2); assertThat(distributionSetManagement.findByRsql("name==*", PAGE)).hasSize(2);
assertThat(distributionSetManagement.count()).isEqualTo(2); assertThat(distributionSetManagement.count()).isEqualTo(2);
@@ -887,10 +846,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
void verifyGetValid() { void verifyGetValid() {
final Long distributionSetId = testdataFactory.createAndInvalidateDistributionSet().getId(); final Long distributionSetId = testdataFactory.createAndInvalidateDistributionSet().getId();
assertThatExceptionOfType(InvalidDistributionSetException.class)
.as("Invalid distributionSet should throw an exception")
.isThrownBy(() -> distributionSetManagement.getValid(distributionSetId));
assertThatExceptionOfType(InvalidDistributionSetException.class) assertThatExceptionOfType(InvalidDistributionSetException.class)
.as("Invalid distributionSet should throw an exception") .as("Invalid distributionSet should throw an exception")
.isThrownBy(() -> distributionSetManagement.getValidAndComplete(distributionSetId)); .isThrownBy(() -> distributionSetManagement.getValidAndComplete(distributionSetId));
@@ -1098,7 +1053,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
} }
private void validateDeleted(final DistributionSet deletedDistributionSet, final int notDeletedSize) { private void validateDeleted(final DistributionSet deletedDistributionSet, final int notDeletedSize) {
assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.TRUE), assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().isDeleted(Boolean.TRUE),
singletonList(deletedDistributionSet)); singletonList(deletedDistributionSet));
@@ -1107,7 +1061,6 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
} }
private void validateCompleted(final DistributionSet dsIncomplete, final int completedSize) { private void validateCompleted(final DistributionSet dsIncomplete, final int completedSize) {
assertThatFilterHasSizeAndDoesNotContainDistributionSet( assertThatFilterHasSizeAndDoesNotContainDistributionSet(
DistributionSetFilter.builder().isComplete(Boolean.TRUE), completedSize, dsIncomplete); DistributionSetFilter.builder().isComplete(Boolean.TRUE), completedSize, dsIncomplete);
@@ -1115,8 +1068,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
DistributionSetFilter.builder().isComplete(Boolean.FALSE), singletonList(dsIncomplete)); DistributionSetFilter.builder().isComplete(Boolean.FALSE), singletonList(dsIncomplete));
} }
private void validateType(final DistributionSetType newType, final DistributionSet dsNewType, private void validateType(final DistributionSetType newType, final DistributionSet dsNewType, final int standardDsTypeSize) {
final int standardDsTypeSize) {
assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().typeId(newType.getId()), assertThatFilterContainsOnlyGivenDistributionSets(DistributionSetFilter.builder().typeId(newType.getId()),
singletonList(dsNewType)); singletonList(dsNewType));
assertThatFilterHasSizeAndDoesNotContainDistributionSet( assertThatFilterHasSizeAndDoesNotContainDistributionSet(
@@ -1277,19 +1229,17 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder, private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder,
final List<? extends DistributionSet> distributionSets) { final List<? extends DistributionSet> distributionSets) {
final int expectedDsSize = distributionSets.size(); final int expectedDsSize = distributionSets.size();
assertThat(((DistributionSetManagement)distributionSetManagement).findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) assertThat(findDsByDistributionSetFilter(filterBuilder.build(), PAGE).getContent())
.hasSize(expectedDsSize).containsOnly(distributionSets.toArray(new DistributionSet[expectedDsSize])); .hasSize(expectedDsSize).containsOnly(distributionSets.toArray(new JpaDistributionSet[expectedDsSize]));
} }
private void assertThatFilterDoesNotContainAnyDistributionSet(final DistributionSetFilterBuilder filterBuilder) { private void assertThatFilterDoesNotContainAnyDistributionSet(final DistributionSetFilterBuilder filterBuilder) {
assertThat(distributionSetManagement.findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) assertThat(findDsByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()).isEmpty();
.isEmpty();
} }
private void assertThatFilterHasSizeAndDoesNotContainDistributionSet( private void assertThatFilterHasSizeAndDoesNotContainDistributionSet(
final DistributionSetFilterBuilder filterBuilder, final int size, final DistributionSet ds) { final DistributionSetFilterBuilder filterBuilder, final int size, final DistributionSet ds) {
assertThat(((DistributionSetManagement)distributionSetManagement).findByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()) assertThat((List)findDsByDistributionSetFilter(filterBuilder.build(), PAGE).getContent()).hasSize(size).doesNotContain(ds);
.hasSize(size).doesNotContain(ds);
} }
// can be removed with java-11 // can be removed with java-11

View File

@@ -41,32 +41,4 @@ class DistributionSetTagManagementSecurityTest
protected DistributionSetTagManagement.Update getUpdateObject() { protected DistributionSetTagManagement.Update getUpdateObject() {
return DistributionSetTagManagement.Update.builder().id(1L).name("tag").build(); return DistributionSetTagManagement.Update.builder().id(1L).name("tag").build();
} }
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void getByNameWitPermissionWorks() {
assertPermissions(() -> distributionSetTagManagement.findByName("tagName"), List.of(SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void findByDistributionSetPermissionsCheck() {
assertPermissions(() -> distributionSetTagManagement.findByDistributionSet(1L, Pageable.unpaged()),
List.of(SpPermission.READ_REPOSITORY));
}
/**
* Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.
*/
@Test
void deleteDistributionSetTagPermissionsCheck() {
assertPermissions(() -> {
distributionSetTagManagement.delete("tagName");
return null;
}, List.of(SpPermission.DELETE_REPOSITORY));
}
} }

View File

@@ -45,15 +45,12 @@ import org.springframework.data.domain.Pageable;
*/ */
class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest { class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
private static final Random RND = new Random();
/** /**
* Verifies that management get access reacts as specified on calls for non existing entities by means of Optional not present. * Verifies that management get access reacts as specified on calls for non existing entities by means of Optional not present.
*/ */
@Test @Test
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) }) @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(distributionSetTagManagement.findByName(NOT_EXIST_ID)).isNotPresent();
assertThat(distributionSetTagManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(distributionSetTagManagement.get(NOT_EXIST_IDL)).isNotPresent();
} }
@@ -66,8 +63,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
@Expect(type = DistributionSetTagUpdatedEvent.class, count = 0), @Expect(type = DistributionSetTagUpdatedEvent.class, count = 0),
@Expect(type = TargetTagUpdatedEvent.class, count = 0) }) @Expect(type = TargetTagUpdatedEvent.class, count = 0) })
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
verifyThrownExceptionBy(() -> distributionSetTagManagement.delete(NOT_EXIST_ID), "DistributionSetTag"); verifyThrownExceptionBy(() -> distributionSetTagManagement.delete(NOT_EXIST_IDL), "DistributionSetTag");
verifyThrownExceptionBy(() -> distributionSetTagManagement.findByDistributionSet(NOT_EXIST_IDL, PAGE), "DistributionSet");
verifyThrownExceptionBy(() -> distributionSetTagManagement.update( verifyThrownExceptionBy(() -> distributionSetTagManagement.update(
DistributionSetTagManagement.Update.builder().id(NOT_EXIST_IDL).build()), "DistributionSetTag"); DistributionSetTagManagement.Update.builder().id(NOT_EXIST_IDL).build()), "DistributionSetTag");
} }
@@ -95,18 +91,18 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
assignTag(dsBs, tagB); assignTag(dsBs, tagB);
assignTag(dsCs, tagC); assignTag(dsCs, tagC);
assignTag(dsABs, distributionSetTagManagement.findByName(tagA.getName()).get()); assignTag(dsABs, distributionSetTagManagement.get(tagA.getId()).orElseThrow());
assignTag(dsABs, distributionSetTagManagement.findByName(tagB.getName()).get()); assignTag(dsABs, distributionSetTagManagement.get(tagB.getId()).orElseThrow());
assignTag(dsACs, distributionSetTagManagement.findByName(tagA.getName()).get()); assignTag(dsACs, distributionSetTagManagement.get(tagA.getId()).orElseThrow());
assignTag(dsACs, distributionSetTagManagement.findByName(tagC.getName()).get()); assignTag(dsACs, distributionSetTagManagement.get(tagC.getId()).orElseThrow());
assignTag(dsBCs, distributionSetTagManagement.findByName(tagB.getName()).get()); assignTag(dsBCs, distributionSetTagManagement.get(tagB.getId()).orElseThrow());
assignTag(dsBCs, distributionSetTagManagement.findByName(tagC.getName()).get()); assignTag(dsBCs, distributionSetTagManagement.get(tagC.getId()).orElseThrow());
assignTag(dsABCs, distributionSetTagManagement.findByName(tagA.getName()).get()); assignTag(dsABCs, distributionSetTagManagement.get(tagA.getId()).orElseThrow());
assignTag(dsABCs, distributionSetTagManagement.findByName(tagB.getName()).get()); assignTag(dsABCs, distributionSetTagManagement.get(tagB.getId()).orElseThrow());
assignTag(dsABCs, distributionSetTagManagement.findByName(tagC.getName()).get()); assignTag(dsABCs, distributionSetTagManagement.get(tagC.getId()).orElseThrow());
// search for not deleted // search for not deleted
final DistributionSetFilter.DistributionSetFilterBuilder distributionSetFilterBuilder = getDistributionSetFilterBuilder() final DistributionSetFilter.DistributionSetFilterBuilder distributionSetFilterBuilder = getDistributionSetFilterBuilder()
@@ -121,11 +117,11 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
Stream.empty()); Stream.empty());
assertThat(distributionSetTagRepository.findAll()).hasSize(5); assertThat(distributionSetTagRepository.findAll()).hasSize(5);
distributionSetTagManagement.delete(tagY.getName()); distributionSetTagManagement.delete(tagY.getId());
assertThat(distributionSetTagRepository.findAll()).hasSize(4); assertThat(distributionSetTagRepository.findAll()).hasSize(4);
distributionSetTagManagement.delete(tagX.getName()); distributionSetTagManagement.delete(tagX.getId());
assertThat(distributionSetTagRepository.findAll()).hasSize(3); assertThat(distributionSetTagRepository.findAll()).hasSize(3);
distributionSetTagManagement.delete(tagB.getName()); distributionSetTagManagement.delete(tagB.getId());
assertThat(distributionSetTagRepository.findAll()).hasSize(2); assertThat(distributionSetTagRepository.findAll()).hasSize(2);
verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.tagNames(Arrays.asList(tagA.getName())), verifyExpectedFilteredDistributionSets(distributionSetFilterBuilder.tagNames(Arrays.asList(tagA.getName())),
@@ -217,11 +213,11 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
final Tag tag = distributionSetTagManagement final Tag tag = distributionSetTagManagement
.create(DistributionSetTagManagement.Create.builder().name("kai1").description("kai2").colour("colour").build()); .create(DistributionSetTagManagement.Create.builder().name("kai1").description("kai2").colour("colour").build());
assertThat(distributionSetTagRepository.findByNameEquals("kai1").get().getDescription()).as("wrong tag found") assertThat(distributionSetTagRepository.findById(tag.getId()).orElseThrow().getDescription()).as("wrong tag found")
.isEqualTo("kai2"); .isEqualTo("kai2");
assertThat(distributionSetTagManagement.findByName("kai1").get().getColour()).as("wrong tag found") assertThat(distributionSetTagManagement.get(tag.getId()).orElseThrow().getColour()).as("wrong tag found")
.isEqualTo("colour"); .isEqualTo("colour");
assertThat(distributionSetTagManagement.get(tag.getId()).get().getColour()).as("wrong tag found") assertThat(distributionSetTagManagement.get(tag.getId()).orElseThrow().getColour()).as("wrong tag found")
.isEqualTo("colour"); .isEqualTo("colour");
} }
@@ -240,7 +236,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
} }
// delete // delete
distributionSetTagManagement.delete(tags.iterator().next().getName()); distributionSetTagManagement.delete(tags.iterator().next().getId());
// check // check
assertThat(distributionSetTagRepository.findById(toDelete.getId())).as("Deleted tag should be null") assertThat(distributionSetTagRepository.findById(toDelete.getId())).as("Deleted tag should be null")
@@ -321,8 +317,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
private void verifyExpectedFilteredDistributionSets(final DistributionSetFilter.DistributionSetFilterBuilder distributionSetFilterBuilder, private void verifyExpectedFilteredDistributionSets(final DistributionSetFilter.DistributionSetFilterBuilder distributionSetFilterBuilder,
final Stream<Collection<DistributionSet>> expectedFilteredDistributionSets) { final Stream<Collection<DistributionSet>> expectedFilteredDistributionSets) {
final Collection<Long> retrievedFilteredDsIds = distributionSetManagement final Collection<Long> retrievedFilteredDsIds = findDsByDistributionSetFilter(distributionSetFilterBuilder.build(), PAGE).stream()
.findByDistributionSetFilter(distributionSetFilterBuilder.build(), PAGE).stream()
.map(DistributionSet::getId).toList(); .map(DistributionSet::getId).toList();
final Collection<Long> expectedFilteredDsIds = expectedFilteredDistributionSets.flatMap(Collection::stream) final Collection<Long> expectedFilteredDsIds = expectedFilteredDistributionSets.flatMap(Collection::stream)
.map(DistributionSet::getId).toList(); .map(DistributionSet::getId).toList();

View File

@@ -1424,11 +1424,11 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
* Verify the creation and the start of a rollout. * Verify the creation and the start of a rollout.
*/ */
@Test @Test
void createScheduledRollout() throws Exception { void createScheduledRollout() {
final String rolloutName = "scheduledRolloutTest"; final String rolloutName = "scheduledRolloutTest";
testdataFactory.createTargets(50, rolloutName + "-", rolloutName); testdataFactory.createTargets(50, rolloutName + "-", rolloutName);
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName); final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet);
final WithUser userWithoutHandleRollout = SecurityContextSwitch.withUser( final WithUser userWithoutHandleRollout = SecurityContextSwitch.withUser(
"user_without_handle_rollout", "user_without_handle_rollout",

View File

@@ -194,18 +194,16 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
assertThat(softwareModuleManagement.findByTextAndType("oracle", runtimeType.getId(), PAGE).getContent()) assertThat(softwareModuleManagement.findByTextAndType("oracle", runtimeType.getId(), PAGE).getContent())
.hasSize(1); .hasSize(1);
assertThat( assertThat(
softwareModuleManagement.findByTextAndType("oracle", runtimeType.getId(), PAGE).getContent().get(0)) softwareModuleManagement.findByTextAndType("oracle", runtimeType.getId(), PAGE).getContent().get(0)).isEqualTo(jvm);
.isEqualTo(jvm);
assertThat(softwareModuleManagement.findByTextAndType(":1.0.1", appType.getId(), PAGE).getContent()).hasSize(1) assertThat(softwareModuleManagement.findByTextAndType(":1.0.1", appType.getId(), PAGE).getContent()).hasSize(1)
.first().isEqualTo(ah); .first().isEqualTo(ah);
assertThat(softwareModuleManagement.findByTextAndType(":1.0", appType.getId(), PAGE).getContent()).hasSize(2); assertThat(softwareModuleManagement.findByTextAndType(":1.0", appType.getId(), PAGE).getContent()).hasSize(2);
distributionSetManagement.unlock(ds.getId()); // otherwise delete will be rejected as a part of a locked DS distributionSetManagement.unlock(ds); // otherwise delete will be rejected as a part of a locked DS
softwareModuleManagement.delete(ah2.getId()); softwareModuleManagement.delete(ah2.getId());
assertThat(softwareModuleManagement.findByTextAndType(":1.0", appType.getId(), PAGE).getContent()).hasSize(1); assertThat(softwareModuleManagement.findByTextAndType(":1.0", appType.getId(), PAGE).getContent()).hasSize(1);
assertThat(softwareModuleManagement.findByTextAndType(":1.0", appType.getId(), PAGE).getContent().get(0)) assertThat(softwareModuleManagement.findByTextAndType(":1.0", appType.getId(), PAGE).getContent().get(0)).isEqualTo(ah);
.isEqualTo(ah);
} }
/** /**
@@ -429,16 +427,16 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
final Artifact artifactY = moduleY.getArtifacts().iterator().next(); final Artifact artifactY = moduleY.getArtifacts().iterator().next();
// [STEP3]: Assign SoftwareModuleX to DistributionSetX and to target // [STEP3]: Assign SoftwareModuleX to DistributionSetX and to target
final DistributionSet disSetX = testdataFactory.createDistributionSet(Set.of(moduleX), "X"); final DistributionSet disSetX = assignDistributionSet(testdataFactory.createDistributionSet(Set.of(moduleX), "X"), List.of(target))
assignDistributionSet(disSetX, Collections.singletonList(target)); .getDistributionSet();
// [STEP4]: Assign SoftwareModuleY to DistributionSet and to target // [STEP4]: Assign SoftwareModuleY to DistributionSet and to target
final DistributionSet disSetY = testdataFactory.createDistributionSet(Set.of(moduleY), "Y"); final DistributionSet disSetY = assignDistributionSet(testdataFactory.createDistributionSet(Set.of(moduleY), "Y"), List.of(target))
assignDistributionSet(disSetY, Collections.singletonList(target)); .getDistributionSet();
// [STEP5]: Delete SoftwareModuleX // [STEP5]: Delete SoftwareModuleX
distributionSetManagement.unlock(disSetX.getId()); // otherwise delete will be rejected as a part of a locked DS distributionSetManagement.unlock(disSetX); // otherwise delete will be rejected as a part of a locked DS
distributionSetManagement.unlock(disSetY.getId()); // otherwise delete will be rejected as a part of a locked DS distributionSetManagement.unlock(disSetY); // otherwise delete will be rejected as a part of a locked DS
softwareModuleManagement.delete(moduleX.getId()); softwareModuleManagement.delete(moduleX.getId());
// [STEP6]: Delete SoftwareModuleY // [STEP6]: Delete SoftwareModuleY
@@ -757,10 +755,8 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
// try to delete while DS is not locked // try to delete while DS is not locked
softwareModuleManagement.delete(modules.get(0).getId()); softwareModuleManagement.delete(modules.get(0).getId());
distributionSetManagement.lock(distributionSet.getId()); distributionSetManagement.lock(distributionSet);
assertThat( assertThat(distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false)).isTrue();
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked).orElse(false))
.isTrue();
// try to delete SM of a locked DS // try to delete SM of a locked DS
final Long moduleId = modules.get(1).getId(); final Long moduleId = modules.get(1).getId();
@@ -772,7 +768,7 @@ class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
private Action assignSet(final JpaTarget target, final JpaDistributionSet ds) { private Action assignSet(final JpaTarget target, final JpaDistributionSet ds) {
assignDistributionSet(ds.getId(), target.getControllerId()); assignDistributionSet(ds.getId(), target.getControllerId());
implicitLock(ds); implicitLock(ds);
assertThat(targetManagement.getByControllerID(target.getControllerId()).get().getUpdateStatus()) assertThat(targetManagement.getByControllerID(target.getControllerId()).orElseThrow().getUpdateStatus())
.isEqualTo(TargetUpdateStatus.PENDING); .isEqualTo(TargetUpdateStatus.PENDING);
final Optional<DistributionSet> assignedDistributionSet = deploymentManagement final Optional<DistributionSet> assignedDistributionSet = deploymentManagement
.getAssignedDistributionSet(target.getControllerId()); .getAssignedDistributionSet(target.getControllerId());

View File

@@ -28,9 +28,8 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.data.domain.Slice; import org.springframework.data.domain.Slice;
/** /**
* Multi-Tenancy tests which testing the CRUD operations of entities that all * Multi-Tenancy tests which testing the CRUD operations of entities that all CRUD-Operations are tenant aware and cannot access
* CRUD-Operations are tenant aware and cannot access or delete entities not * or delete entities not belonging to the current tenant.
* belonging to the current tenant.
* <p/> * <p/>
* Feature: Component Tests - Repository<br/> * Feature: Component Tests - Repository<br/>
* Story: Multi Tenancy * Story: Multi Tenancy
@@ -201,6 +200,6 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
} }
private Slice<? extends DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception { private Slice<? extends DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
return runAsTenant(tenant, () -> distributionSetManagement.findByCompleted(true, PAGE)); return runAsTenant(tenant, () -> distributionSetManagement.findAll(PAGE));
} }
} }

View File

@@ -25,6 +25,7 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Optional; import java.util.Optional;
import java.util.Random;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
@@ -117,6 +118,7 @@ public abstract class AbstractIntegrationTest {
protected static final Pageable PAGE = PageRequest.of(0, 500, 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"); protected static final URI LOCALHOST = URI.create("http://127.0.0.1");
protected static final int DEFAULT_TEST_WEIGHT = 500; protected static final int DEFAULT_TEST_WEIGHT = 500;
protected static final Random RND = new Random();
/** /**
* Number of {@link DistributionSetType}s that exist in every test case. One * Number of {@link DistributionSetType}s that exist in every test case. One
@@ -286,14 +288,12 @@ public abstract class AbstractIntegrationTest {
return defaultDsType().getMandatoryModuleTypes().stream().findAny().orElseThrow(); return defaultDsType().getMandatoryModuleTypes().stream().findAny().orElseThrow();
} }
protected static Action getFirstAssignedAction( protected static Action getFirstAssignedAction(final DistributionSetAssignmentResult distributionSetAssignmentResult) {
final DistributionSetAssignmentResult distributionSetAssignmentResult) {
return distributionSetAssignmentResult.getAssignedEntity().stream().findFirst() return distributionSetAssignmentResult.getAssignedEntity().stream().findFirst()
.orElseThrow(() -> new IllegalStateException("expected one assigned action, found none")); .orElseThrow(() -> new IllegalStateException("expected one assigned action, found none"));
} }
protected static Long getFirstAssignedActionId( protected static Long getFirstAssignedActionId(final DistributionSetAssignmentResult distributionSetAssignmentResult) {
final DistributionSetAssignmentResult distributionSetAssignmentResult) {
return getFirstAssignedAction(distributionSetAssignmentResult).getId(); return getFirstAssignedAction(distributionSetAssignmentResult).getId();
} }
@@ -313,13 +313,12 @@ public abstract class AbstractIntegrationTest {
return TestdataFactory.randomBytes(len); return TestdataFactory.randomBytes(len);
} }
protected DistributionSetAssignmentResult assignDistributionSet(final long dsID, final String controllerId) { protected DistributionSetAssignmentResult assignDistributionSet(final long dsId, final String controllerId) {
return assignDistributionSet(dsID, controllerId, ActionType.FORCED); return assignDistributionSet(dsId, controllerId, ActionType.FORCED);
} }
protected DistributionSetAssignmentResult assignDistributionSet( protected DistributionSetAssignmentResult assignDistributionSet(final long dsId, final String controllerId, final ActionType actionType) {
final long dsID, final String controllerId, final ActionType actionType) { return assignDistributionSet(dsId, Collections.singletonList(controllerId), actionType);
return assignDistributionSet(dsID, Collections.singletonList(controllerId), actionType);
} }
protected DistributionSetAssignmentResult assignDistributionSet( protected DistributionSetAssignmentResult assignDistributionSet(
@@ -333,8 +332,8 @@ public abstract class AbstractIntegrationTest {
} }
protected DistributionSetAssignmentResult assignDistributionSet( protected DistributionSetAssignmentResult assignDistributionSet(
final long dsID, final List<String> controllerIds, final ActionType actionType, final long forcedTime) { final long dsId, final List<String> controllerIds, final ActionType actionType, final long forcedTime) {
return assignDistributionSet(dsID, controllerIds, actionType, forcedTime, null); return assignDistributionSet(dsId, controllerIds, actionType, forcedTime, null);
} }
protected DistributionSetAssignmentResult assignDistributionSet( protected DistributionSetAssignmentResult assignDistributionSet(