forbid software modules / artifacts modification for locked distribution sets / software modules respectively Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -205,6 +205,10 @@ public enum SpServerError {
|
||||
*/
|
||||
SP_DS_INCOMPLETE("hawkbit.server.error.distributionset.incomplete",
|
||||
"Distribution set is assigned/locked to a target that is incomplete (i.e. mandatory modules are missing)"),
|
||||
/**
|
||||
*
|
||||
*/
|
||||
SP_LOCKED("hawkbit.server.error.locked", "Entry is locked. Could not be modified"),
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -23,7 +24,9 @@ import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
*/
|
||||
public class EntityNotFoundException extends AbstractServerRtException {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (c) 2024 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.repository.model.BaseEntity;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* Thrown if assignment quota is exceeded
|
||||
*/
|
||||
public class LockedException extends AbstractServerRtException {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final String ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE = "Quota exceeded: Cannot assign %s more %s entities to %s '%s'. The maximum is %s.";
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_LOCKED;
|
||||
|
||||
public LockedException(
|
||||
final Class<? extends BaseEntity> type, final Object entityId, final String operation) {
|
||||
super(
|
||||
type.getSimpleName() + " with given identifier {" + entityId + "} is locked and " + operation +
|
||||
" is forbidden!",
|
||||
THIS_ERROR);
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreated
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.DistributionSetTypeUndefinedException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -185,6 +186,10 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
}
|
||||
|
||||
public boolean addModule(final SoftwareModule softwareModule) {
|
||||
if (isLocked()) {
|
||||
throw new LockedException(JpaDistributionSet.class, getId(), "ADD_SOFTWARE_MODULE");
|
||||
}
|
||||
|
||||
if (modules == null) {
|
||||
modules = new HashSet<>();
|
||||
}
|
||||
@@ -215,6 +220,10 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
}
|
||||
|
||||
public void removeModule(final SoftwareModule softwareModule) {
|
||||
if (isLocked()) {
|
||||
throw new LockedException(JpaDistributionSet.class, getId(), "REMOVE_SOFTWARE_MODULE");
|
||||
}
|
||||
|
||||
if (modules != null && modules.removeIf(m -> m.getId().equals(softwareModule.getId()))) {
|
||||
complete = type.checkComplete(this);
|
||||
}
|
||||
@@ -253,7 +262,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
if (!complete) {
|
||||
if (!isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Could not be locked while incomplete!");
|
||||
}
|
||||
locked = true;
|
||||
|
||||
@@ -39,6 +39,7 @@ import lombok.ToString;
|
||||
import org.eclipse.hawkbit.repository.event.remote.SoftwareModuleDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -140,6 +141,10 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement
|
||||
}
|
||||
|
||||
public void addArtifact(final Artifact artifact) {
|
||||
if (isLocked()) {
|
||||
throw new LockedException(JpaSoftwareModule.class, getId(), "ADD_ARTIFACT");
|
||||
}
|
||||
|
||||
if (artifacts == null) {
|
||||
artifacts = new ArrayList<>(4);
|
||||
artifacts.add((JpaArtifact) artifact);
|
||||
@@ -155,6 +160,10 @@ public class JpaSoftwareModule extends AbstractJpaNamedVersionedEntity implement
|
||||
* @param artifact is removed from the assigned {@link Artifact}s.
|
||||
*/
|
||||
public void removeArtifact(final Artifact artifact) {
|
||||
if (isLocked()) {
|
||||
throw new LockedException(JpaSoftwareModule.class, getId(), "REMOVE_ARTIFACT");
|
||||
}
|
||||
|
||||
if (artifacts != null) {
|
||||
artifacts.remove(artifact);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
@@ -1010,7 +1011,39 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Locks an incomplete DS. Expected behaviour is to throw exception and to do not lock it.")
|
||||
@Description("Software modules of a locked DS can't be modified. Expected behaviour is to throw an exception and to do not modify them.")
|
||||
void lockDistributionSetApplied() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-1");
|
||||
final int softwareModuleCount = distributionSet.getModules().size();
|
||||
assertThat(softwareModuleCount).isNotEqualTo(0);
|
||||
distributionSetManagement.lock(distributionSet.getId());
|
||||
assertThat(
|
||||
distributionSetManagement.get(distributionSet.getId()).map(DistributionSet::isLocked)
|
||||
.orElse(false))
|
||||
.isTrue();
|
||||
|
||||
|
||||
// try add
|
||||
assertThatExceptionOfType(LockedException.class)
|
||||
.as("Attempt to modify a locked DS software modules should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.assignSoftwareModules(
|
||||
distributionSet.getId(), List.of(testdataFactory.createSoftwareModule("sm-1").getId())));
|
||||
assertThat(distributionSetManagement.get(distributionSet.getId()).get().getModules().size())
|
||||
.as("Software module shall not be added to a locked DS.")
|
||||
.isEqualTo(softwareModuleCount);
|
||||
|
||||
// try remove
|
||||
assertThatExceptionOfType(LockedException.class)
|
||||
.as("Attempt to modify a locked DS software modules should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.unassignSoftwareModule(
|
||||
distributionSet.getId(), distributionSet.getModules().stream().findFirst().get().getId()));
|
||||
assertThat(distributionSetManagement.get(distributionSet.getId()).get().getModules().size())
|
||||
.as("Software module shall not be removed from a locked DS.")
|
||||
.isEqualTo(softwareModuleCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Locks an incomplete DS. Expected behaviour is to throw an exception and to do not lock it.")
|
||||
void lockIncompleteDistributionSetFails() {
|
||||
final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet();
|
||||
assertThatExceptionOfType(IncompleteDistributionSetException.class)
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.RandomGeneratedInputStream;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction_;
|
||||
@@ -824,7 +825,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@Description("Locks a SM.")
|
||||
void lockSoftwareModule() {
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("ds-1");
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1");
|
||||
assertThat(
|
||||
softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(true))
|
||||
.isFalse();
|
||||
@@ -834,6 +835,43 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Artifacts of a locked SM can't be modified. Expected behaviour is to throw an exception and to do not modify them.")
|
||||
void lockSoftwareModuleApplied() {
|
||||
final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("sm-1");
|
||||
artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(new byte[] {1}), softwareModule.getId(),
|
||||
"artifact1", false, 1));
|
||||
final int artifactCount = softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size();
|
||||
assertThat(artifactCount).isNotEqualTo(0);
|
||||
softwareModuleManagement.lock(softwareModule.getId());
|
||||
assertThat(
|
||||
softwareModuleManagement.get(softwareModule.getId()).map(SoftwareModule::isLocked).orElse(false))
|
||||
.isTrue();
|
||||
|
||||
|
||||
// try add
|
||||
assertThatExceptionOfType(LockedException.class)
|
||||
.as("Attempt to modify a locked SM artifacts should throw an exception")
|
||||
.isThrownBy(() -> artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(new byte[] {2}), softwareModule.getId(),
|
||||
"artifact2", false, 1)));
|
||||
assertThat(softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size())
|
||||
.as("Artifacts shall not be added to a locked SM.")
|
||||
.isEqualTo(artifactCount);
|
||||
|
||||
// try remove
|
||||
final long artifactId = softwareModuleManagement.get(softwareModule.getId()).get()
|
||||
.getArtifacts().stream().findFirst().get().getId();
|
||||
assertThatExceptionOfType(LockedException.class)
|
||||
.as("Attempt to modify a locked DS software modules should throw an exception")
|
||||
.isThrownBy(() -> artifactManagement.delete(artifactId));
|
||||
assertThat(softwareModuleManagement.get(softwareModule.getId()).get().getArtifacts().size())
|
||||
.as("Software module shall not be removed from a locked DS.")
|
||||
.isEqualTo(artifactCount);
|
||||
assertThat(artifactManagement.get(artifactId)).isPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that non existing metadata find results in exception.")
|
||||
public void findSoftwareModuleMetadataFailsIfEntryDoesNotExist() {
|
||||
|
||||
Reference in New Issue
Block a user