Multi-Asssignments feature removal (#2893)

* Multi-Asssignments feature removal

Signed-off-by: strailov <Stanislav.Trailov@bosch.io>

* fix some sonar findings

Signed-off-by: strailov <Stanislav.Trailov@bosch.io>

* fixes after review

Signed-off-by: strailov <Stanislav.Trailov@bosch.io>

---------

Signed-off-by: strailov <Stanislav.Trailov@bosch.io>
This commit is contained in:
Stanislav Trailov
2026-02-04 16:59:09 +02:00
committed by GitHub
parent 2bf443661d
commit c33156b134
43 changed files with 123 additions and 1610 deletions

View File

@@ -30,44 +30,6 @@ class RemoteTenantEventTest extends AbstractRemoteEventTest {
private static final String TENANT_DEFAULT = "DEFAULT";
/**
* Verifies that a testMultiActionAssignEvent can be properly serialized and deserialized
*/
@Test
void testMultiActionAssignEvent() {
final List<String> controllerIds = List.of("id0", "id1", "id2", "id3", "id4loooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnng");
final List<Action> actions = controllerIds.stream().map(this::createAction).toList();
final MultiActionAssignEvent assignEvent = new MultiActionAssignEvent(TENANT_DEFAULT, actions);
final MultiActionAssignEvent remoteAssignEventProtoStuff = createProtoStuffEvent(assignEvent);
assertThat(assignEvent).isEqualTo(remoteAssignEventProtoStuff);
assertThat(remoteAssignEventProtoStuff.getControllerIds()).containsExactlyElementsOf(controllerIds);
final MultiActionAssignEvent remoteAssignEventJackson = createJacksonEvent(assignEvent);
assertThat(assignEvent).isEqualTo(remoteAssignEventJackson);
assertThat(remoteAssignEventJackson.getControllerIds()).containsExactlyElementsOf(controllerIds);
}
/**
* Verifies that a MultiActionCancelEvent can be properly serialized and deserialized
*/
@Test
void testMultiActionCancelEvent() {
final List<String> controllerIds = List.of("id0", "id1", "id2", "id3", "id4loooooooooooooooooooooooooooooooooooonnnnnnnnnnnnnnnnnng");
final List<Action> actions = controllerIds.stream().map(this::createAction).toList();
final MultiActionCancelEvent cancelEvent = new MultiActionCancelEvent(TENANT_DEFAULT, actions);
final MultiActionCancelEvent remoteCancelEventProtoStuff = createProtoStuffEvent(cancelEvent);
assertThat(cancelEvent).isEqualTo(remoteCancelEventProtoStuff);
assertThat(remoteCancelEventProtoStuff.getControllerIds()).containsExactlyElementsOf(controllerIds);
final MultiActionCancelEvent remoteCancelEventJackson = createJacksonEvent(cancelEvent);
assertThat(cancelEvent).isEqualTo(remoteCancelEventJackson);
assertThat(remoteCancelEventJackson.getControllerIds()).containsExactlyElementsOf(controllerIds);
}
/**
* Verifies that a DownloadProgressEvent can be properly serialized and deserialized
*/
@@ -135,15 +97,6 @@ class RemoteTenantEventTest extends AbstractRemoteEventTest {
assertCancelTargetAssignmentEvent(action, remoteEventJackson);
}
private Action createAction(final String controllerId) {
final JpaAction generateAction = new JpaAction();
generateAction.setId(1L);
generateAction.setActionType(ActionType.FORCED);
generateAction.setTarget(testdataFactory.createTarget(controllerId));
generateAction.setStatus(Status.RUNNING);
return generateAction;
}
private void assertTargetAssignDistributionSetEvent(final Action action, final TargetAssignDistributionSetEvent underTest) {
assertThat(underTest.getActions()).hasSize(1);
final ActionProperties actionProperties = underTest.getActions().get(action.getTarget().getControllerId());

View File

@@ -16,7 +16,6 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.List;
import java.util.Set;
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
@@ -25,7 +24,6 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.service.CancelTargetAssignmentServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.MultiActionAssignServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetAssignDistributionSetServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetAttributesRequestedServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetCreatedServiceEvent;
@@ -79,8 +77,6 @@ class ServiceEventsTest {
TargetAssignDistributionSetEvent.class,
CancelTargetAssignmentEvent.class,
TargetAttributesRequestedEvent.class,
MultiActionAssignEvent.class,
MultiActionCancelEvent.class,
ActionCreatedEvent.class,
ActionUpdatedEvent.class
);
@@ -124,16 +120,6 @@ class ServiceEventsTest {
verify(streamBridge).send(eq("group"), any(TargetAttributesRequestedServiceEvent.class));
}
@Test
void testProcessingMultiActionAssignmentEventIsSent() {
MultiActionAssignEvent event = new MultiActionAssignEvent("testtenant", List.of(mockAction()));
publisher.publishEvent(event);
verify(streamBridge).send("fanout", event);
verify(streamBridge).send(eq("group"), any(MultiActionAssignServiceEvent.class));
}
@Test
void testCancelTargetAssignmentEventIsSent() {
CancelTargetAssignmentEvent event = new CancelTargetAssignmentEvent(mockAction());

View File

@@ -64,37 +64,6 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest {
.allMatch(action -> action.getStatus() == Status.WAIT_FOR_CONFIRMATION);
}
/**
* Verify 'findActiveActionsWaitingConfirmation' method is filtering like expected with multi assignment active
*/
@Test
void retrieveActionsWithConfirmationStateInMultiAssignment() {
enableMultiAssignments();
enableConfirmationFlow();
final String controllerId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final List<Action> actions = assignDistributionSet(dsId, controllerId).getAssignedEntity();
assertThat(actions).hasSize(1);
assertThat(confirmationManagement.findActiveActionsWaitingConfirmation(controllerId)).hasSize(1)
.allMatch(action -> action.getStatus() == Status.WAIT_FOR_CONFIRMATION);
final Long dsId2 = testdataFactory.createDistributionSet().getId();
assignDistributionSet(dsId2, controllerId);
assertThat(confirmationManagement.findActiveActionsWaitingConfirmation(controllerId)).hasSize(2)
.allMatch(action -> action.getStatus() == Status.WAIT_FOR_CONFIRMATION);
confirmationManagement.confirmAction(actions.get(0).getId(), null, null);
assertThat(confirmationManagement.findActiveActionsWaitingConfirmation(controllerId)).hasSize(1)
.allMatch(action -> action.getStatus() == Status.WAIT_FOR_CONFIRMATION
&& Objects.equals(action.getDistributionSet().getId(), dsId2));
}
/**
* Verify confirming an action will put it to the running state
*/
@@ -191,34 +160,6 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest {
.noneMatch(status -> status.getStatus() == Status.RUNNING);
}
/**
* Verify multiple actions in WFC state will be transferred in RUNNING state in case auto-confirmation is activated.
*/
@Test
void activateAutoConfirmationInMultiAssignment() {
enableMultiAssignments();
enableConfirmationFlow();
final String controllerId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final Long dsId2 = testdataFactory.createDistributionSet().getId();
final List<Action> actions = assignDistributionSets(
Arrays.asList(toDeploymentRequest(controllerId, dsId), toDeploymentRequest(controllerId, dsId2)))
.stream().flatMap(s -> s.getAssignedEntity().stream()).toList();
assertThat(actions).hasSize(2);
assertThat(confirmationManagement.findActiveActionsWaitingConfirmation(controllerId)).hasSize(2)
.allMatch(action -> action.getStatus() == Status.WAIT_FOR_CONFIRMATION);
confirmationManagement.activateAutoConfirmation(controllerId, null, null);
assertThat(confirmationManagement.findActiveActionsWaitingConfirmation(controllerId)).isEmpty();
assertThat(deploymentManagement.findActionsByTarget(controllerId, PAGE).getContent()).hasSize(2)
.allMatch(action -> action.getStatus() == Status.RUNNING);
}
/**
* Verify action in WFC state will be transferred in RUNNING state in case auto-confirmation is activated.
*/
@@ -324,10 +265,6 @@ class ConfirmationManagementTest extends AbstractJpaIntegrationTest {
Arguments.of(null, null));
}
private static DeploymentRequest toDeploymentRequest(final String controllerId, final Long distributionSetId) {
return DeploymentRequest.builder(controllerId, distributionSetId).confirmationRequired(true).build();
}
private void verifyAutoConfirmationIsDisabled(final String controllerId) {
assertThat(targetManagement.getWithAutoConfigurationStatus(controllerId).getAutoConfirmationStatus()).isNull();
}

View File

@@ -1582,41 +1582,6 @@ class ControllerManagementTest extends AbstractJpaIntegrationTest {
assertNoActiveActionsExistsForControllerId(DEFAULT_CONTROLLER_ID);
}
/**
* Actions are exposed according to thier weight in multi assignment mode.
*/
@Test
void actionsAreExposedAccordingToTheirWeight() {
final String targetId = testdataFactory.createTarget().getControllerId();
final DistributionSet ds = testdataFactory.createDistributionSet();
final Long actionWeightNull = assignDistributionSet(ds.getId(), targetId).getAssignedEntity().get(0).getId();
enableMultiAssignments();
final Long actionWeight500old = assignDistributionSet(ds.getId(), targetId, 500).getAssignedEntity().get(0)
.getId();
final Long actionWeight500new = assignDistributionSet(ds.getId(), targetId, 500).getAssignedEntity().get(0)
.getId();
final Long actionWeight1000 = assignDistributionSet(ds.getId(), targetId, 1000).getAssignedEntity().get(0)
.getId();
assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId())
.isEqualTo(actionWeightNull);
controllerManagement
.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeightNull).status(Status.FINISHED).build());
assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId())
.isEqualTo(actionWeight1000);
controllerManagement
.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeight1000).status(Status.FINISHED).build());
assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId())
.isEqualTo(actionWeight500old);
controllerManagement
.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeight500old).status(Status.FINISHED).build());
assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId).get().getId())
.isEqualTo(actionWeight500new);
controllerManagement
.addUpdateActionStatus(ActionStatusCreate.builder().actionId(actionWeight500new).status(Status.FINISHED).build());
assertThat(controllerManagement.findActiveActionWithHighestWeight(targetId)).isEmpty();
}
/**
* Delete a target on requested target deletion from client side
*/

View File

@@ -37,8 +37,6 @@ import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.event.remote.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent;
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
@@ -50,13 +48,18 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TenantConfigurationUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.service.ActionCreatedServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.ActionUpdatedServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.CancelTargetAssignmentServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetAssignDistributionSetServiceEvent;
import org.eclipse.hawkbit.repository.event.remote.service.TargetUpdatedServiceEvent;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.ForceQuitActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.IncompatibleTargetTypeException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
import org.eclipse.hawkbit.repository.exception.InvalidDistributionSetException;
import org.eclipse.hawkbit.repository.exception.MultiAssignmentIsNotEnabledException;
import org.eclipse.hawkbit.repository.exception.MultiAssignmentException;
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
@@ -208,19 +211,22 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
*/
@Test
void assertMaxActionsPerTargetQuotaIsEnforced() {
enableMultiAssignments();
final int maxActions = quotaManagement.getMaxActionsPerTarget();
final Target testTarget = testdataFactory.createTarget();
final Long ds1Id = testdataFactory.createDistributionSet("ds1").getId();
final List<Long> dsIds = new ArrayList<>();
for (int i = 0; i < maxActions; i++) {
dsIds.add(testdataFactory.createDistributionSet("ds" + i).getId());
}
final String controllerId = testTarget.getControllerId();
for (int i = 0; i < maxActions; i++) {
deploymentManagement.offlineAssignedDistributionSets(List.of(new SimpleEntry<>(controllerId, ds1Id)));
deploymentManagement.offlineAssignedDistributionSets(List.of(new SimpleEntry<>(controllerId, dsIds.get(i))));
}
final long dsIdThatShouldNotBeAssigned = testdataFactory.createDistributionSet("shouldNotBeAssigned").getId();
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> assignDistributionSet(ds1Id, controllerId, 77));
.isThrownBy(() -> assignDistributionSet(dsIdThatShouldNotBeAssigned, controllerId, 77));
}
/**
@@ -539,44 +545,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
.allMatch(target -> target.getLastModifiedAt() == target.getInstallationDate());
}
/**
* Offline assign multiple DSs to a single Target in multiassignment mode.
*/
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 4),
@Expect(type = ActionCreatedEvent.class, count = 4),
@Expect(type = DistributionSetCreatedEvent.class, count = 4),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 12),
@Expect(type = DistributionSetUpdatedEvent.class, count = 4), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 12), // implicit lock
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void multiOfflineAssignment() {
final List<String> targetIds = testdataFactory.createTargets(1).stream().map(Target::getControllerId).toList();
final List<Long> dsIds = testdataFactory.createDistributionSets(4).stream().map(DistributionSet::getId).toList();
enableMultiAssignments();
final List<Entry<String, Long>> offlineAssignments = new ArrayList<>();
targetIds.forEach(targetId -> dsIds.forEach(dsId -> offlineAssignments.add(new SimpleEntry<>(targetId, dsId))));
final List<DistributionSetAssignmentResult> assignmentResults = deploymentManagement
.offlineAssignedDistributionSets(offlineAssignments);
assertThat(getResultingActionCount(assignmentResults)).isEqualTo(4);
targetIds.forEach(controllerId -> {
final List<Long> assignedDsIds = deploymentManagement.findActionsByTarget(controllerId, PAGE).stream()
.map(a -> {
// don't use peek since it is by documentation mainly for debugging and could be skipped in some cases
assertThat(a.getInitiatedBy())
.as("Actions should be initiated by current user")
.isEqualTo(AccessContext.actor());
return a;
})
.map(action -> action.getDistributionSet().getId()).toList();
assertThat(assignedDsIds).containsExactlyInAnyOrderElementsOf(dsIds);
});
}
/**
* Verifies that if an account is set to action autoclose running actions in case of a new assigned set get closed and set to CANCELED.
*/
@@ -620,118 +588,11 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
}
}
/**
* If multi-assignment is enabled, verify that the previous Distribution Set assignment is not canceled when a new one is assigned.
*/
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 10),
@Expect(type = TargetUpdatedEvent.class, count = 20),
@Expect(type = ActionCreatedEvent.class, count = 20),
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
@Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), // implicit lock
@Expect(type = MultiActionAssignEvent.class, count = 2),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void previousAssignmentsAreNotCanceledInMultiAssignMode() {
enableMultiAssignments();
final List<Target> targets = testdataFactory.createTargets(10);
final List<String> targetIds = targets.stream().map(Target::getControllerId).toList();
// First assignment
final DistributionSet ds1 = testdataFactory.createDistributionSet("Multi-assign-1");
assignDistributionSet(ds1.getId(), targetIds, 77);
assertDsExclusivelyAssignedToTargets(targets, ds1.getId(), STATE_ACTIVE, RUNNING);
// Second assignment
final DistributionSet ds2 = testdataFactory.createDistributionSet("Multi-assign-2");
assignDistributionSet(ds2.getId(), targetIds, 45);
assertDsExclusivelyAssignedToTargets(targets, ds2.getId(), STATE_ACTIVE, RUNNING);
assertDsExclusivelyAssignedToTargets(targets, ds1.getId(), STATE_ACTIVE, RUNNING);
}
/**
* Assign multiple DSs to a single Target in one request in multiassignment mode.
*/
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 4),
@Expect(type = ActionCreatedEvent.class, count = 4),
@Expect(type = DistributionSetCreatedEvent.class, count = 4),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 12),
@Expect(type = DistributionSetUpdatedEvent.class, count = 4), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 12), // implicit lock
@Expect(type = MultiActionAssignEvent.class, count = 1),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void multiAssignmentInOneRequest() {
final List<Target> targets = testdataFactory.createTargets(1);
final List<DistributionSet> distributionSets = testdataFactory.createDistributionSets(4);
final List<DeploymentRequest> deploymentRequests = createAssignmentRequests(distributionSets, targets, 34);
enableMultiAssignments();
final List<DistributionSetAssignmentResult> results = deploymentManagement.assignDistributionSets(deploymentRequests, null);
assertThat(getResultingActionCount(results)).isEqualTo(deploymentRequests.size());
final List<Long> dsIds = distributionSets.stream().map(DistributionSet::getId).toList();
targets.forEach(target -> {
final List<Long> assignedDsIds = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE)
.stream()
.map(a -> {
// don't use peek since it is by documentation mainly for debugging and could be skipped in some cases
assertThat(a.getInitiatedBy()).as("Initiated by current user")
.isEqualTo(AccessContext.actor());
return a;
})
.map(action -> action.getDistributionSet().getId()).toList();
assertThat(assignedDsIds).containsExactlyInAnyOrderElementsOf(dsIds);
});
}
/**
* Assign multiple DSs to single Target in one request in multiAssignment mode and cancel each created action afterwards.
*/
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 4),
@Expect(type = ActionCreatedEvent.class, count = 4),
@Expect(type = DistributionSetCreatedEvent.class, count = 4),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 12),
@Expect(type = DistributionSetUpdatedEvent.class, count = 4), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 12), // implicit lock
@Expect(type = MultiActionAssignEvent.class, count = 1),
@Expect(type = MultiActionCancelEvent.class, count = 4),
@Expect(type = ActionUpdatedEvent.class, count = 4),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void cancelMultiAssignmentActions() {
final List<Target> targets = testdataFactory.createTargets(1);
final List<DistributionSet> distributionSets = testdataFactory.createDistributionSets(4);
final List<DeploymentRequest> deploymentRequests = createAssignmentRequests(distributionSets, targets, 34, false);
enableMultiAssignments();
final List<DistributionSetAssignmentResult> results = deploymentManagement.assignDistributionSets(deploymentRequests, null);
assertThat(getResultingActionCount(results)).isEqualTo(deploymentRequests.size());
final List<Long> dsIds = distributionSets.stream().map(DistributionSet::getId).toList();
targets.forEach(target ->
deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).forEach(action -> {
assertThat(action.getDistributionSet().getId()).isIn(dsIds);
assertThat(action.getInitiatedBy())
.as("Should be Initiated by current user").isEqualTo(AccessContext.actor());
deploymentManagement.cancelAction(action.getId());
}));
}
/**
* A Request resulting in multiple assignments to a single target is only allowed when multiassignment is enabled.
*/
@Test
void multipleAssignmentsToTargetOnlyAllowedInMultiAssignMode() {
void multipleAssignmentsToTargetNotAllowed() {
final Target target = testdataFactory.createTarget();
final List<DistributionSet> distributionSets = testdataFactory.createDistributionSets(2);
@@ -742,11 +603,9 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
.builder(target.getControllerId(), distributionSets.get(1).getId()).weight(565).build();
final List<DeploymentRequest> deploymentRequests = List.of(targetToDS0, targetToDS1);
Assertions.assertThatExceptionOfType(MultiAssignmentIsNotEnabledException.class)
Assertions.assertThatExceptionOfType(MultiAssignmentException.class)
.isThrownBy(() -> deploymentManagement.assignDistributionSets(deploymentRequests, null));
enableMultiAssignments();
assertThat(getResultingActionCount(deploymentManagement.assignDistributionSets(List.of(targetToDS0, targetToDS1), null))).isEqualTo(2);
}
/**
@@ -912,77 +771,46 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
}));
}
/**
* Duplicate Assignments are removed from a request when multi-assignment is disabled, otherwise not
*/
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = MultiActionAssignEvent.class, count = 1),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void duplicateAssignmentsInRequestAreRemovedIfMultiassignmentEnabled() {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final List<DeploymentRequest> twoEqualAssignments = Collections.nCopies(2, DeploymentRequest.builder(targetId, dsId).build());
assertThat(getResultingActionCount(deploymentManagement.assignDistributionSets(twoEqualAssignments, null))).isEqualTo(1);
enableMultiAssignments();
final List<DeploymentRequest> twoEqualAssignmentsWithWeight = Collections.nCopies(
2, DeploymentRequest.builder(targetId, dsId).weight(555).build());
assertThat(getResultingActionCount(deploymentManagement.assignDistributionSets(twoEqualAssignmentsWithWeight, null))).isEqualTo(1);
}
/**
* An assignment request is not accepted if it would lead to a target exceeding the max actions per target quota.
*/
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 20),
@Expect(type = TargetUpdatedServiceEvent.class, count = 20),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 20),
@Expect(type = CancelTargetAssignmentEvent.class, count = 19),
@Expect(type = CancelTargetAssignmentServiceEvent.class, count = 19),
@Expect(type = DistributionSetCreatedEvent.class, count = 21), // max actions per target are 20 for test
@Expect(type = DistributionSetUpdatedEvent.class, count = 20),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3 * 21),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3 * 20),
@Expect(type = ActionUpdatedEvent.class, count = 19),
@Expect(type = ActionCreatedEvent.class, count = 20),
@Expect(type = ActionCreatedServiceEvent.class, count = 20),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 20),
})
void maxActionsPerTargetIsCheckedBeforeAssignmentExecution() {
final int maxActions = quotaManagement.getMaxActionsPerTarget();
assertThat(maxActions)
.as("Expect 20 as maxActionPerTarget. If not the case change @Expect counts for " +
"DistributionSetCreatedEvent and SoftwareModuleCreatedEvent accordingly!")
.isEqualTo(20);
final int size = maxActions + 1;
final String controllerId = testdataFactory.createTarget().getControllerId();
final List<DeploymentRequest> deploymentRequests = new ArrayList<>();
for (int i = 0; i < size; i++) {
for (int i = 0; i < maxActions; i++) {
final Long dsId = testdataFactory.createDistributionSet().getId();
deploymentRequests.add(DeploymentRequest.builder(controllerId, dsId).weight(24).build());
deploymentManagement.assignDistributionSets(
List.of(DeploymentRequest.builder(controllerId, dsId).weight(24).build()), null);
}
enableMultiAssignments();
final Long dsId = testdataFactory.createDistributionSet().getId();
final List<DeploymentRequest> deploymentRequests = List.of(DeploymentRequest.builder(controllerId, dsId).weight(24).build());
Assertions.assertThatExceptionOfType(AssignmentQuotaExceededException.class)
.isThrownBy(() -> deploymentManagement.assignDistributionSets(deploymentRequests, null));
assertThat(actionRepository.countByTargetControllerId(controllerId)).isZero();
}
/**
* An assignment request without a weight is ok when multi assignment in enabled.
*/
@Test
void weightNotRequiredInMultiAssignmentMode() {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final DeploymentRequest assignWithoutWeight = DeploymentRequest.builder(targetId, dsId).build();
final DeploymentRequest assignWithWeight = DeploymentRequest.builder(targetId, dsId).weight(567).build();
enableMultiAssignments();
assertThat(deploymentManagement.assignDistributionSets(List.of(assignWithoutWeight, assignWithWeight), null)).isNotNull();
assertThat(actionRepository.countByTargetControllerId(controllerId)).isEqualTo(20L);
}
/**
@@ -1003,22 +831,28 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
@Test
@ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
@Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6), // implicit lock
@Expect(type = ActionCreatedEvent.class, count = 2),
@Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = ActionUpdatedServiceEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = MultiActionAssignEvent.class, count = 2),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetServiceEvent.class, count = 2),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = CancelTargetAssignmentServiceEvent.class, count = 1)
})
void weightValidatedAndSaved() {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final DeploymentRequest validRequest1 = DeploymentRequest.builder(targetId, dsId).weight(Action.WEIGHT_MAX).build();
final DeploymentRequest validRequest2 = DeploymentRequest.builder(targetId, dsId).weight(Action.WEIGHT_MIN).build();
final DeploymentRequest weightTooLow = DeploymentRequest.builder(targetId, dsId).weight(Action.WEIGHT_MIN - 1).build();
final DeploymentRequest weightTooHigh = DeploymentRequest.builder(targetId, dsId).weight(Action.WEIGHT_MAX + 1).build();
enableMultiAssignments();
final Long dsId1 = testdataFactory.createDistributionSet().getId();
final Long dsId2 = testdataFactory.createDistributionSet().getId();
final DeploymentRequest validRequest1 = DeploymentRequest.builder(targetId, dsId1).weight(Action.WEIGHT_MAX).build();
final DeploymentRequest validRequest2 = DeploymentRequest.builder(targetId, dsId2).weight(Action.WEIGHT_MIN).build();
final DeploymentRequest weightTooLow = DeploymentRequest.builder(targetId, dsId1).weight(Action.WEIGHT_MIN - 1).build();
final DeploymentRequest weightTooHigh = DeploymentRequest.builder(targetId, dsId1).weight(Action.WEIGHT_MAX + 1).build();
final List<DeploymentRequest> deploymentRequestsTooLow = Collections.singletonList(weightTooLow);
Assertions.assertThatExceptionOfType(ConstraintViolationException.class)
.isThrownBy(() -> deploymentManagement.assignDistributionSets(deploymentRequestsTooLow, null));
@@ -1027,9 +861,11 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
() -> deploymentManagement.assignDistributionSets(deploymentRequestsTooHigh, null));
final Long validActionId1 = getFirstAssignedAction(
deploymentManagement.assignDistributionSets(Collections.singletonList(validRequest1), null).get(0)).getId();
final Long validActionId2 = getFirstAssignedAction(
deploymentManagement.assignDistributionSets(Collections.singletonList(validRequest2), null).get(0)).getId();
assertThat(actionRepository.findById(validActionId1).get().getWeight()).get().isEqualTo(Action.WEIGHT_MAX);
DistributionSetAssignmentResult assignmentResult = deploymentManagement.assignDistributionSets(Collections.singletonList(validRequest2), null).get(0);
System.out.println(assignmentResult.getAssignedEntity().toString());
final Long validActionId2 = getFirstAssignedAction(assignmentResult).getId();
assertThat(actionRepository.findById(validActionId2).get().getWeight()).get().isEqualTo(Action.WEIGHT_MIN);
}
@@ -1720,20 +1556,6 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
}
private List<DeploymentRequest> createAssignmentRequests(
final Collection<DistributionSet> distributionSets, final Collection<Target> targets, final int weight) {
return createAssignmentRequests(distributionSets, targets, weight, false);
}
private List<DeploymentRequest> createAssignmentRequests(final Collection<DistributionSet> distributionSets,
final Collection<Target> targets, final int weight, final boolean confirmationRequired) {
final List<DeploymentRequest> deploymentRequests = new ArrayList<>();
distributionSets.forEach(ds -> targets.forEach(target -> deploymentRequests.add(
DeploymentRequest.builder(target.getControllerId(), ds.getId())
.weight(weight).confirmationRequired(confirmationRequired).build())));
return deploymentRequests;
}
private JpaAction assignSet(final Target target, final DistributionSet ds) {
assignDistributionSet(ds.getId(), target.getControllerId());
implicitLock(ds);

View File

@@ -25,6 +25,7 @@ import java.util.stream.Stream;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.ValidationException;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.api.Assertions;
import org.assertj.core.api.Condition;
import org.eclipse.hawkbit.auth.SpPermission;
@@ -1994,18 +1995,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
assertThat(rolloutsOrderedByName).containsSubsequence(List.of(rolloutRunning, rolloutReady));
}
/**
* Creating a rollout without weight value when multi assignment in enabled.
*/
@Test
void weightNotRequiredInMultiAssignmentMode() {
enableMultiAssignments();
final Rollout rollout = testdataFactory.createSimpleTestRolloutWithTargetsAndDistributionSet(10, 10, 2, "50",
"80",
ActionType.FORCED, null);
assertThat(rollout).isNotNull();
}
/**
* Creating a rollout with a weight causes an error when multi assignment in disabled.
*/
@@ -2024,7 +2013,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
void weightValidatedAndSaved() {
final String targetPrefix = UUID.randomUUID().toString();
testdataFactory.createTargets(4, targetPrefix);
enableMultiAssignments();
final String rolloutName = UUID.randomUUID().toString();
final String targetPrefixName = UUID.randomUUID().toString();
@@ -2054,7 +2042,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
void actionsWithWeightAreCreated() {
final int amountOfTargets = 5;
final int weight = 99;
enableMultiAssignments();
final Long rolloutId = testdataFactory
.createSimpleTestRolloutWithTargetsAndDistributionSet(amountOfTargets, 2, amountOfTargets,
"80", "50", null, weight).getId();
@@ -2066,24 +2053,6 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
.allMatch(action -> action.getWeight().get() == weight);
}
/**
* Rollout can be created without weight in single assignment and be started in multi assignment
*/
@Test
void createInSingleStartInMultiassignMode() {
final int amountOfTargets = 5;
final Long rolloutId = testdataFactory.createSimpleTestRolloutWithTargetsAndDistributionSet(amountOfTargets, 2,
amountOfTargets,
"80", "50", null, null).getId();
enableMultiAssignments();
rolloutManagement.start(rolloutId);
rolloutHandler.handleAll();
final List<Action> actions = deploymentManagement.findActionsAll(PAGE).getContent();
// wight replaced with default
assertThat(actions).hasSize(5).allMatch(action -> action.getWeight().isPresent());
}
/**
* Verifies that an exception is thrown when trying to create a rollout with an invalidated distribution set.
*/

View File

@@ -244,23 +244,6 @@ class TargetFilterQueryManagementTest extends AbstractRepositoryManagementTest<T
verifyFindForAllWithAutoAssignDs(tfq, tfq2);
}
/**
* Creating or updating a target filter query with autoassignment and no-value weight when multi assignment in enabled.
*/
@Test
void weightNotRequiredInMultiAssignmentMode() {
enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").build()).getId();
assertThat(
targetFilterQueryManagement.create(Create.builder().name("b").query("name==*").autoAssignDistributionSet(ds).build()))
.isNotNull();
assertThat(
targetFilterQueryManagement.updateAutoAssignDS(new AutoAssignDistributionSetUpdate(filterId).ds(ds.getId())))
.isNotNull();
}
/**
* Creating or updating a target filter query with autoassignment with a weight causes an error when multi assignment in disabled.
*/
@@ -279,23 +262,8 @@ class TargetFilterQueryManagementTest extends AbstractRepositoryManagementTest<T
.isNotNull();
}
/**
* Auto assignment can be removed from filter when multi assignment in enabled.
*/
@Test
void removeDsFromFilterWhenMultiAssignmentModeNotEnabled() {
enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet();
final Long filterId = targetFilterQueryManagement.create(
Create.builder().name("a").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(23).build()).getId();
assertThat(targetFilterQueryManagement.updateAutoAssignDS(
new AutoAssignDistributionSetUpdate(filterId).ds(null).weight(null)))
.isNotNull();
}
@Test
void weightValidatedAndSaved() {
enableMultiAssignments();
final DistributionSet ds = testdataFactory.createDistributionSet();
final Create targetFilterQueryCreate = Create.builder().name("a")

View File

@@ -328,7 +328,6 @@ class AutoAssignHandlerIntTest extends AbstractJpaIntegrationTest {
final int amountOfTargets = 5;
final DistributionSet ds = testdataFactory.createDistributionSet();
final int weight = 32;
enableMultiAssignments();
targetFilterQueryManagement.create(Create.builder()
.name("a").query("name==*").autoAssignDistributionSet(ds).autoAssignWeight(weight)
@@ -342,25 +341,6 @@ class AutoAssignHandlerIntTest extends AbstractJpaIntegrationTest {
.allMatch(action -> action.getWeight().get() == weight);
}
/**
* An auto assignment target filter without weight still works after multi assignment is enabled
*/
@Test
void filterWithoutWeightWorksInMultiAssignmentMode() {
final int amountOfTargets = 5;
final DistributionSet ds = testdataFactory.createDistributionSet();
targetFilterQueryManagement.create(Create.builder().name("a").query("name==*").autoAssignDistributionSet(ds).build());
enableMultiAssignments();
testdataFactory.createTargets(amountOfTargets);
autoAssignChecker.handleAll();
final List<Action> actions = deploymentManagement.findActionsAll(PAGE).getContent();
assertThat(actions)
.hasSize(amountOfTargets)
.allMatch(action -> action.getWeight().isPresent());
}
/**
* Verifies an auto assignment only creates actions for compatible targets
*/