Software module metadata available to targets (in DMF and DDI) (#608)
* Software module metadata can be configure as target visible. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Added metadata to DDI. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Managed by UI. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Complete DMF integration and started UI. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Add DMF tests and completed UI. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Add RSQL test. Fix sonar issues. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Add JavaDocs. foreachtenant robustness. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Review feedback included. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Updated DMF docs. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * targetVisible optional in builder. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix typos. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix checkbox ID. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * DB optimization. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix component ID of sm metadat details tab. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
@@ -311,9 +312,11 @@ public class AmqpConfiguration {
|
||||
AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate,
|
||||
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
|
||||
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
|
||||
final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement) {
|
||||
final TargetManagement targetManagement, final DistributionSetManagement distributionSetManagement,
|
||||
final SoftwareModuleManagement softwareModuleManagement) {
|
||||
return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,
|
||||
systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement);
|
||||
systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement,
|
||||
softwareModuleManagement);
|
||||
}
|
||||
|
||||
private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() {
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
package org.eclipse.hawkbit.amqp;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.api.ApiType;
|
||||
@@ -25,8 +26,11 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfArtifact;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfArtifactHash;
|
||||
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.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
@@ -34,6 +38,7 @@ import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
@@ -46,6 +51,9 @@ import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.cloud.bus.ServiceMatcher;
|
||||
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
|
||||
@@ -66,6 +74,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
private final TargetManagement targetManagement;
|
||||
private final ServiceMatcher serviceMatcher;
|
||||
private final DistributionSetManagement distributionSetManagement;
|
||||
private final SoftwareModuleManagement softwareModuleManagement;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -92,7 +101,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
|
||||
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
|
||||
final TargetManagement targetManagement, final ServiceMatcher serviceMatcher,
|
||||
final DistributionSetManagement distributionSetManagement) {
|
||||
final DistributionSetManagement distributionSetManagement,
|
||||
final SoftwareModuleManagement softwareModuleManagement) {
|
||||
super(rabbitTemplate);
|
||||
this.artifactUrlHandler = artifactUrlHandler;
|
||||
this.amqpSenderService = amqpSenderService;
|
||||
@@ -101,6 +111,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
this.targetManagement = targetManagement;
|
||||
this.serviceMatcher = serviceMatcher;
|
||||
this.distributionSetManagement = distributionSetManagement;
|
||||
this.softwareModuleManagement = softwareModuleManagement;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,11 +129,22 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
|
||||
LOG.debug("targetAssignDistributionSet retrieved. I will forward it to DMF broker.");
|
||||
|
||||
distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(set ->
|
||||
distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(set -> {
|
||||
|
||||
targetManagement.getByControllerID(assignedEvent.getActions().keySet())
|
||||
.forEach(target -> sendUpdateMessageToTarget(assignedEvent.getTenant(), target,
|
||||
assignedEvent.getActions().get(target.getControllerId()), set.getModules())));
|
||||
final Map<SoftwareModule, List<SoftwareModuleMetadata>> modules = Maps
|
||||
.newHashMapWithExpectedSize(set.getModules().size());
|
||||
set.getModules()
|
||||
.forEach(
|
||||
module -> modules.put(module,
|
||||
softwareModuleManagement.findMetaDataBySoftwareModuleIdAndTargetVisible(
|
||||
new PageRequest(0, RepositoryConstants.MAX_META_DATA_COUNT), module.getId())
|
||||
.getContent()));
|
||||
|
||||
targetManagement.getByControllerID(assignedEvent.getActions().keySet())
|
||||
.forEach(target -> sendUpdateMessageToTarget(assignedEvent.getTenant(), target,
|
||||
assignedEvent.getActions().get(target.getControllerId()), modules));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +181,7 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
}
|
||||
|
||||
protected void sendUpdateMessageToTarget(final String tenant, final Target target, final Long actionId,
|
||||
final Collection<SoftwareModule> modules) {
|
||||
final Map<SoftwareModule, List<SoftwareModuleMetadata>> modules) {
|
||||
|
||||
final URI targetAdress = target.getAddress();
|
||||
if (!IpUtil.isAmqpUri(targetAdress)) {
|
||||
@@ -172,10 +194,11 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
final String targetSecurityToken = systemSecurityContext.runAsSystem(target::getSecurityToken);
|
||||
downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken);
|
||||
|
||||
for (final SoftwareModule softwareModule : modules) {
|
||||
final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, softwareModule);
|
||||
modules.entrySet().forEach(entry -> {
|
||||
|
||||
final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, entry);
|
||||
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
|
||||
}
|
||||
});
|
||||
|
||||
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
|
||||
createConnectorMessagePropertiesEvent(tenant, target.getControllerId(),
|
||||
@@ -248,17 +271,22 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
return messageProperties;
|
||||
}
|
||||
|
||||
private DmfSoftwareModule convertToAmqpSoftwareModule(final Target target, final SoftwareModule softwareModule) {
|
||||
private DmfSoftwareModule convertToAmqpSoftwareModule(final Target target,
|
||||
final Entry<SoftwareModule, List<SoftwareModuleMetadata>> entry) {
|
||||
final DmfSoftwareModule amqpSoftwareModule = new DmfSoftwareModule();
|
||||
amqpSoftwareModule.setModuleId(softwareModule.getId());
|
||||
amqpSoftwareModule.setModuleType(softwareModule.getType().getKey());
|
||||
amqpSoftwareModule.setModuleVersion(softwareModule.getVersion());
|
||||
amqpSoftwareModule.setModuleId(entry.getKey().getId());
|
||||
amqpSoftwareModule.setModuleType(entry.getKey().getType().getKey());
|
||||
amqpSoftwareModule.setModuleVersion(entry.getKey().getVersion());
|
||||
amqpSoftwareModule.setArtifacts(convertArtifacts(target, entry.getKey().getArtifacts()));
|
||||
amqpSoftwareModule.setMetadata(convertMetadata(entry.getValue()));
|
||||
|
||||
final List<DmfArtifact> artifacts = convertArtifacts(target, softwareModule.getArtifacts());
|
||||
amqpSoftwareModule.setArtifacts(artifacts);
|
||||
return amqpSoftwareModule;
|
||||
}
|
||||
|
||||
private List<DmfMetadata> convertMetadata(final List<SoftwareModuleMetadata> metadata) {
|
||||
return metadata.stream().map(md -> new DmfMetadata(md.getKey(), md.getValue())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<DmfArtifact> convertArtifacts(final Target target, final List<Artifact> localArtifacts) {
|
||||
if (localArtifacts.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
|
||||
@@ -12,8 +12,10 @@ import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
@@ -28,6 +30,8 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.builder.ActionStatusCreate;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.slf4j.Logger;
|
||||
@@ -45,6 +49,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
*
|
||||
* {@link AmqpMessageHandlerService} handles all incoming target interaction
|
||||
@@ -199,8 +205,17 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<SoftwareModule, List<SoftwareModuleMetadata>> modules = Maps
|
||||
.newHashMapWithExpectedSize(action.getDistributionSet().getModules().size());
|
||||
|
||||
final Map<Long, List<SoftwareModuleMetadata>> metadata = controllerManagement
|
||||
.findTargetVisibleMetaDataBySoftwareModuleId(action.getDistributionSet().getModules().stream()
|
||||
.map(SoftwareModule::getId).collect(Collectors.toList()));
|
||||
|
||||
action.getDistributionSet().getModules().forEach(module -> modules.put(module, metadata.get(module.getId())));
|
||||
|
||||
amqpMessageDispatcherService.sendUpdateMessageToTarget(action.getTenant(), action.getTarget(), action.getId(),
|
||||
action.getDistributionSet().getModules());
|
||||
modules);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetDeletedEvent;
|
||||
@@ -46,6 +47,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TenantMetaData;
|
||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -109,7 +111,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
|
||||
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher,
|
||||
distributionSetManagement);
|
||||
distributionSetManagement, softwareModuleManagement);
|
||||
|
||||
}
|
||||
|
||||
@@ -129,6 +131,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
|
||||
final DistributionSet createDistributionSet = testdataFactory
|
||||
.createDistributionSet(UUID.randomUUID().toString());
|
||||
testdataFactory.addSoftwareModuleMetadata(createDistributionSet);
|
||||
|
||||
final Action action = createAction(createDistributionSet);
|
||||
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
@@ -142,6 +146,10 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule softwareModule : downloadAndUpdateRequest
|
||||
.getSoftwareModules()) {
|
||||
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty());
|
||||
|
||||
assertThat(softwareModule.getMetadata()).containsExactly(
|
||||
new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE));
|
||||
|
||||
for (final SoftwareModule softwareModule2 : action.getDistributionSet().getModules()) {
|
||||
assertNotNull("Sofware module ID should be set", softwareModule.getModuleId());
|
||||
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
|
||||
|
||||
@@ -22,7 +22,6 @@ import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -421,7 +420,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final ArgumentCaptor<Long> actionIdCaptor = ArgumentCaptor.forClass(Long.class);
|
||||
|
||||
verify(amqpMessageDispatcherServiceMock, times(1)).sendUpdateMessageToTarget(tenantCaptor.capture(),
|
||||
targetCaptor.capture(), actionIdCaptor.capture(), any(Collection.class));
|
||||
targetCaptor.capture(), actionIdCaptor.capture(), any(Map.class));
|
||||
final String tenant = tenantCaptor.getValue();
|
||||
final String controllerId = targetCaptor.getValue().getControllerId();
|
||||
final Long actionId = actionIdCaptor.getValue();
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -45,6 +46,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void sendDownloadAndInstallStatus() {
|
||||
@@ -63,6 +65,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 3) })
|
||||
public void assignDistributionSetMultipleTimes() {
|
||||
@@ -88,6 +91,7 @@ public class AmqpMessageDispatcherServiceIntegrationTest extends AmqpServiceInte
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void sendCancelStatus() {
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
@@ -363,6 +364,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void finishActionStatus() {
|
||||
@@ -376,6 +378,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 0), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void runningActionStatus() {
|
||||
@@ -389,6 +392,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void downloadActionStatus() {
|
||||
@@ -402,6 +406,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void errorActionStatus() {
|
||||
@@ -415,6 +420,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void warningActionStatus() {
|
||||
@@ -428,6 +434,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void retrievedActionStatus() {
|
||||
@@ -441,6 +448,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void cancelNotAllowActionStatus() {
|
||||
@@ -455,6 +463,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 2) })
|
||||
public void receiveDownLoadAndInstallMessageAfterAssignment() {
|
||||
@@ -463,6 +472,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
// setup
|
||||
createAndSendTarget(controllerId, TENANT_EXIST);
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
testdataFactory.addSoftwareModuleMetadata(distributionSet);
|
||||
assignDistributionSet(distributionSet.getId(), controllerId);
|
||||
|
||||
// test
|
||||
@@ -507,6 +517,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
@@ -526,6 +537,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void canceledRejectedNotAllowActionStatus() {
|
||||
@@ -541,6 +553,7 @@ public class AmqpMessageHandlerServiceIntegrationTest extends AmqpServiceIntegra
|
||||
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1), @Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void canceledRejectedActionStatus() {
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfAttributeUpdate;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfDownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfMetadata;
|
||||
import org.eclipse.hawkbit.integration.listener.DeadletterListener;
|
||||
import org.eclipse.hawkbit.integration.listener.ReplyToListener;
|
||||
import org.eclipse.hawkbit.matcher.SoftwareModuleJsonMatcher;
|
||||
@@ -35,6 +36,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
@@ -107,6 +109,8 @@ public abstract class AmqpServiceIntegrationTest extends AbstractAmqpIntegration
|
||||
|
||||
protected DistributionSetAssignmentResult registerTargetAndAssignDistributionSet(final String controllerId) {
|
||||
distributionSet = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
testdataFactory.addSoftwareModuleMetadata(distributionSet);
|
||||
|
||||
return registerTargetAndAssignDistributionSet(distributionSet.getId(), TargetUpdateStatus.REGISTERED,
|
||||
distributionSet.getModules(), controllerId);
|
||||
}
|
||||
@@ -165,6 +169,10 @@ public abstract class AmqpServiceIntegrationTest extends AbstractAmqpIntegration
|
||||
Assert.assertThat(dsModules,
|
||||
SoftwareModuleJsonMatcher.containsExactly(downloadAndUpdateRequest.getSoftwareModules()));
|
||||
|
||||
downloadAndUpdateRequest.getSoftwareModules()
|
||||
.forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly(
|
||||
new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE)));
|
||||
|
||||
final Target updatedTarget = waitUntilIsPresent(() -> targetManagement.getByControllerID(controllerId));
|
||||
|
||||
assertThat(updatedTarget.getSecurityToken()).isEqualTo(downloadAndUpdateRequest.getTargetSecurityToken());
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.hamcrest.BaseMatcher;
|
||||
import org.hamcrest.Description;
|
||||
@@ -44,21 +45,19 @@ public final class SoftwareModuleJsonMatcher {
|
||||
* the json sofware modules.
|
||||
*/
|
||||
@Factory
|
||||
public static SoftwareModulesMatcher containsExactly(
|
||||
final List<org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule> expectedModules) {
|
||||
public static SoftwareModulesMatcher containsExactly(final List<DmfSoftwareModule> expectedModules) {
|
||||
return new SoftwareModulesMatcher(expectedModules);
|
||||
}
|
||||
|
||||
private static class SoftwareModulesMatcher extends BaseMatcher<Set<SoftwareModule>> {
|
||||
|
||||
private final List<org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule> expectedModules;
|
||||
private final List<DmfSoftwareModule> expectedModules;
|
||||
|
||||
public SoftwareModulesMatcher(List<org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule> expectedModules) {
|
||||
public SoftwareModulesMatcher(final List<DmfSoftwareModule> expectedModules) {
|
||||
this.expectedModules = expectedModules;
|
||||
}
|
||||
|
||||
static boolean containsExactly(Object actual,
|
||||
List<org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule> expected) {
|
||||
static boolean containsExactly(final Object actual, final List<DmfSoftwareModule> expected) {
|
||||
if (actual == null) {
|
||||
return expected == null;
|
||||
}
|
||||
@@ -73,7 +72,7 @@ public final class SoftwareModuleJsonMatcher {
|
||||
for (final SoftwareModule repoSoftwareModule : modules) {
|
||||
boolean containsElement = false;
|
||||
|
||||
for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule jsonSoftwareModule : expected) {
|
||||
for (final DmfSoftwareModule jsonSoftwareModule : expected) {
|
||||
if (!jsonSoftwareModule.getModuleId().equals(repoSoftwareModule.getId())) {
|
||||
continue;
|
||||
}
|
||||
@@ -100,12 +99,12 @@ public final class SoftwareModuleJsonMatcher {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(Object actualValue) {
|
||||
public boolean matches(final Object actualValue) {
|
||||
return containsExactly(actualValue, expectedModules);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
public void describeTo(final Description description) {
|
||||
description.appendValue(expectedModules);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ public class DmfArtifactHash {
|
||||
*/
|
||||
@JsonCreator
|
||||
public DmfArtifactHash(@JsonProperty("sha1") final String sha1, @JsonProperty("md5") final String md5) {
|
||||
super();
|
||||
this.sha1 = sha1;
|
||||
this.md5 = md5;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.dmf.json.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Additional metadata to be provided for the target/device.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DmfMetadata {
|
||||
@JsonProperty
|
||||
private final String key;
|
||||
|
||||
@JsonProperty
|
||||
private final String value;
|
||||
|
||||
@JsonCreator
|
||||
public DmfMetadata(@JsonProperty("key") final String key, @JsonProperty("value") final String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((key == null) ? 0 : key.hashCode());
|
||||
result = prime * result + ((value == null) ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final DmfMetadata other = (DmfMetadata) obj;
|
||||
if (key == null) {
|
||||
if (other.key != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!key.equals(other.key)) {
|
||||
return false;
|
||||
}
|
||||
if (value == null) {
|
||||
if (other.value != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!value.equals(other.value)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
/**
|
||||
* JSON representation of a software module.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@@ -36,6 +33,8 @@ public class DmfSoftwareModule {
|
||||
private String moduleVersion;
|
||||
@JsonProperty
|
||||
private List<DmfArtifact> artifacts;
|
||||
@JsonProperty
|
||||
private List<DmfMetadata> metadata;
|
||||
|
||||
public String getModuleType() {
|
||||
return moduleType;
|
||||
@@ -74,4 +73,14 @@ public class DmfSoftwareModule {
|
||||
this.artifacts = artifacts;
|
||||
}
|
||||
|
||||
public List<DmfMetadata> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(final List<DmfMetadata> metadata) {
|
||||
if (metadata != null && !metadata.isEmpty()) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user