Dmf batch support changes. (#1273)
* Dmf batch support changes. Implement single batch message instead of multiple messages for assigment on multiple targets. Added system property to switch on/off. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> * Dmf batch support changes. Implement single batch message instead of multiple messages for assigment on multiple targets. Added system property to switch on/off. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> * Dmf batch support changes. Implement single batch message instead of multiple messages for assigment on multiple targets. Added system property to switch on/off. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> * Dmf batch support changes. Implement single batch message instead of multiple messages for assigment on multiple targets. Added system property to switch on/off. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> * Update hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AmqpMessageDispatcherServiceIntegrationTest.java Co-authored-by: Bondar Bogdan <36962546+bogdan-bondar@users.noreply.github.com> * Dmf batch support changes. Implement single batch message instead of multiple messages for assigment on multiple targets. Added system property to switch on/off. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> * Dmf batch support changes. Implement single batch message instead of multiple messages for assigment on multiple targets. Added system property to switch on/off. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> * Dmf batch support changes. Implement code review comments. Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io> Co-authored-by: Bondar Bogdan <36962546+bogdan-bondar@users.noreply.github.com>
This commit is contained in:
@@ -111,7 +111,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
|
||||
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher,
|
||||
distributionSetManagement, softwareModuleManagement, deploymentManagement);
|
||||
distributionSetManagement, softwareModuleManagement, deploymentManagement, tenantConfigurationManagement);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -32,6 +34,7 @@ import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfCreateThing;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule;
|
||||
import org.eclipse.hawkbit.integration.listener.DeadletterListener;
|
||||
import org.eclipse.hawkbit.integration.listener.ReplyToListener;
|
||||
import org.eclipse.hawkbit.matcher.SoftwareModuleJsonMatcher;
|
||||
@@ -95,7 +98,7 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
getDmfClient().setExchange(AmqpSettings.DMF_EXCHANGE);
|
||||
}
|
||||
|
||||
private <T> T waitUntilIsPresent(final Callable<Optional<T>> callable) {
|
||||
protected <T> T waitUntilIsPresent(final Callable<Optional<T>> callable) {
|
||||
|
||||
createConditionFactory()
|
||||
.until(() -> WithSpringAuthorityRule.runAsPrivileged(() -> callable.call().isPresent()));
|
||||
@@ -194,10 +197,7 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
|
||||
protected void assertDmfDownloadAndUpdateRequest(final DmfDownloadAndUpdateRequest request,
|
||||
final Set<SoftwareModule> softwareModules, final String controllerId) {
|
||||
assertThat(softwareModules)
|
||||
.is(new HamcrestCondition<>(SoftwareModuleJsonMatcher.containsExactly(request.getSoftwareModules())));
|
||||
request.getSoftwareModules().forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly(
|
||||
new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE)));
|
||||
assertSoftwareModules(softwareModules, request.getSoftwareModules());
|
||||
final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.getByControllerID(controllerId));
|
||||
assertThat(updatedTarget).isNotNull();
|
||||
assertThat(updatedTarget.getSecurityToken()).isEqualTo(request.getTargetSecurityToken());
|
||||
@@ -445,4 +445,11 @@ public abstract class AbstractAmqpServiceIntegrationTest extends AbstractAmqpInt
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
protected void assertSoftwareModules(final Set<SoftwareModule> expectedSoftwareModules,
|
||||
final List<DmfSoftwareModule> softwareModules) {
|
||||
assertThat(expectedSoftwareModules)
|
||||
.is(new HamcrestCondition<>(SoftwareModuleJsonMatcher.containsExactly(softwareModules)));
|
||||
softwareModules.forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly(
|
||||
new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,9 +9,13 @@
|
||||
package org.eclipse.hawkbit.integration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.eclipse.hawkbit.dmf.amqp.api.EventTopic.BATCH_DOWNLOAD;
|
||||
import static org.eclipse.hawkbit.dmf.amqp.api.EventTopic.BATCH_DOWNLOAD_AND_INSTALL;
|
||||
import static org.eclipse.hawkbit.dmf.amqp.api.EventTopic.DOWNLOAD;
|
||||
import static org.eclipse.hawkbit.dmf.amqp.api.MessageType.EVENT;
|
||||
import static org.eclipse.hawkbit.repository.model.Action.ActionType.DOWNLOAD_ONLY;
|
||||
import static org.eclipse.hawkbit.repository.model.Action.ActionType.FORCED;
|
||||
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Arrays;
|
||||
@@ -29,10 +33,12 @@ import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfActionRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfActionStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfBatchDownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfMultiActionRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfMultiActionRequest.DmfMultiActionElement;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfTarget;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
|
||||
@@ -53,6 +59,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedE
|
||||
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.exception.TenantConfigurationValueChangeNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -66,6 +73,8 @@ import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.amqp.core.Message;
|
||||
|
||||
@@ -603,4 +612,87 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AbstractAmqpSer
|
||||
|| multiActionElement.getTopic().equals(EventTopic.DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify payload of batch assignment download and install message.")
|
||||
public void assertBatchAssignmentsDownloadAndInstall() {
|
||||
assertBatchAssignmentsMessagePayload(BATCH_DOWNLOAD_AND_INSTALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify payload of batch assignments download only message.")
|
||||
public void assertBatchAssignmentsDownloadOnly() {
|
||||
assertBatchAssignmentsMessagePayload(BATCH_DOWNLOAD);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that batch and multi-assignments can't be activated at the same time.")
|
||||
void assertBatchAndMultiAssignmentsNotCompatible() {
|
||||
enableBatchAssignments();
|
||||
assertThatExceptionOfType(TenantConfigurationValueChangeNotAllowedException.class)
|
||||
.isThrownBy(() -> enableMultiAssignments());
|
||||
disableBatchAssignments();
|
||||
|
||||
enableMultiAssignments();
|
||||
assertThatExceptionOfType(TenantConfigurationValueChangeNotAllowedException.class)
|
||||
.isThrownBy(() -> enableBatchAssignments());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(names = { "BATCH_DOWNLOAD_AND_INSTALL", "BATCH_DOWNLOAD" })
|
||||
@Description("Verify payload of batch assignments.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 3), @Expect(type = ActionUpdatedEvent.class, count = 0),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = TargetPollEvent.class, count = 3),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void assertBatchAssignmentsMessagePayload(final EventTopic topic) {
|
||||
enableBatchAssignments();
|
||||
|
||||
final List<String> targets = Arrays.asList("batchCtrlID1", "batchCtrlID2", "batchCtrlID3");
|
||||
for (int i = 0; i < targets.size(); i++) {
|
||||
registerAndAssertTargetWithExistingTenant(targets.get(i), i+1);
|
||||
}
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
testdataFactory.addSoftwareModuleMetadata(ds);
|
||||
|
||||
assignDistributionSet(ds.getId(), targets, topic == BATCH_DOWNLOAD?DOWNLOAD_ONLY:FORCED);
|
||||
|
||||
waitUntilEventMessagesAreDispatchedToTarget(topic);
|
||||
|
||||
final Message message = replyToListener.getLatestEventMessage(topic);
|
||||
final Map<String, Object> headers = message.getMessageProperties().getHeaders();
|
||||
assertThat(headers).containsEntry("type", EVENT.toString());
|
||||
assertThat(headers).containsEntry("topic",topic.toString());
|
||||
|
||||
final DmfBatchDownloadAndUpdateRequest batchRequest = (DmfBatchDownloadAndUpdateRequest) getDmfClient()
|
||||
.getMessageConverter().fromMessage(message);
|
||||
|
||||
assertThat(batchRequest).isExactlyInstanceOf(DmfBatchDownloadAndUpdateRequest.class);
|
||||
assertDmfBatchDownloadAndUpdateRequest(batchRequest, ds.getModules(), targets);
|
||||
}
|
||||
|
||||
protected void assertDmfBatchDownloadAndUpdateRequest(final DmfBatchDownloadAndUpdateRequest request,
|
||||
final Set<SoftwareModule> softwareModules,
|
||||
final List<String> controllerIds) {
|
||||
assertSoftwareModules(softwareModules, request.getSoftwareModules());
|
||||
|
||||
List<Object> tokens = controllerIds.stream().map(controllerId -> {
|
||||
final Optional<Target> target = controllerManagement.getByControllerId(controllerId);
|
||||
assertThat(target).isPresent();
|
||||
return target.get().getSecurityToken();
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
List<DmfTarget> requestTargets = request.getTargets();
|
||||
|
||||
assertThat(requestTargets).hasSameSizeAs(controllerIds);
|
||||
requestTargets.forEach(requestTarget -> {
|
||||
assertThat(requestTarget).isNotNull();
|
||||
assertThat(tokens.contains(requestTarget.getTargetSecurityToken()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user