Skip to content

Commit

Permalink
Restructure Tenant Configuration View to make it more flexible for ad…
Browse files Browse the repository at this point in the history
…aptations (#1043)

* Extract view creation for Configuration Components into Beans;
Split implementations of config Binders into corresponding view classes:
- add ProxySystemConfig classes respectively for ConfigurationViews;
- create Binder and config Bean in BaseConfigurationView via Generics;
- extend ConfigurationViews from BaseConfigurationView;
- populate Binders and config Bean in ConfigurationView;
- access binder getter/setter in ConfigurationItem through corresponding ProxySystemConfig;
- autowire Collection of Config Views in TenantConfigurationDashboardView;
- create components, call save and undo for each config view in Collection

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Do not send the target token when anonymous download is enabled

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Update amqp tests to cover enabled anonymous download config

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Do not change TargetToken functionality for hawkbit;
Make createDownloadAndUpdateRequest protected;
Undo some of previous test changes;

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Add license header to ProxySystemConfigDsType

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Call save methods for filtered ConfigurationViews only, not the autowired.

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Document public classes

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Adopt Review Comments:
- Rename DefaultDistributionSetTypeLayout
- Remove unnecessary qualifier TenantConfigurationProperties

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Refactoring: implement InitializingBean instead of using PostConstruct

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Apply to remaining classes: implement InitializingBean instead of using PostConstruct

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Removed unnecessary method notifyConfigurationChanged();
Documented Bean creation of configuration views

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Rename TenantConfigurationAutoConfiguration to SystemConfigViewAutoConfiguration

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Rename init method of DefaultDistributionSetTypeView

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>
  • Loading branch information
Nkyn authored Feb 11, 2021
1 parent 3deb325 commit 3422781
Show file tree
Hide file tree
Showing 25 changed files with 1,160 additions and 909 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ public RabbitAdmin rabbitAdmin() {
}

/**
* @return {@link RabbitTemplate} with automatic retry, published confirms
* and {@link Jackson2JsonMessageConverter}.
* @return {@link RabbitTemplate} with automatic retry, published confirms and
* {@link Jackson2JsonMessageConverter}.
*/
@Bean
public RabbitTemplate rabbitTemplate() {
Expand Down Expand Up @@ -140,8 +140,8 @@ public Queue dmfReceiverQueue() {
}

/**
* Create the DMF API receiver queue for authentication requests called by
* 3rd party artifact storages for download authorization by devices.
* Create the DMF API receiver queue for authentication requests called by 3rd
* party artifact storages for download authorization by devices.
*
* @return the receiver queue
*/
Expand Down Expand Up @@ -183,8 +183,7 @@ public FanoutExchange authenticationExchange() {
}

/**
* Create the Binding
* {@link AmqpConfiguration#authenticationReceiverQueue()} to
* Create the Binding {@link AmqpConfiguration#authenticationReceiverQueue()} to
* {@link AmqpConfiguration#authenticationExchange()}.
*
* @return the binding and create the queue and exchange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,13 @@ protected void targetAssignDistributionSet(final TargetAssignDistributionSetEven
if (!shouldBeProcessed(assignedEvent)) {
return;
}

LOG.debug("targetAssignDistributionSet retrieved. I will forward it to DMF broker.");

distributionSetManagement.get(assignedEvent.getDistributionSetId()).ifPresent(ds -> {

final Map<SoftwareModule, List<SoftwareModuleMetadata>> softwareModules = getSoftwareModulesWithMetadata(
ds);

targetManagement.getByControllerID(assignedEvent.getActions().keySet()).forEach(
target -> sendUpdateMessageToTarget(assignedEvent.getActions().get(target.getControllerId()),
target, softwareModules));

});
}

Expand Down Expand Up @@ -186,16 +181,15 @@ private void sendMultiActionRequestMessages(final String tenant, final List<Stri
action -> action.getDistributionSet().getModules().stream()
.collect(Collectors.toMap(m -> m, softwareModuleMetadata::get)));
}

});

}

protected void sendMultiActionRequestToTarget(final String tenant, final Target target, final List<Action> actions,
final Function<Action, Map<SoftwareModule, List<SoftwareModuleMetadata>>> getSoftwareModuleMetaData) {

final URI targetAdress = target.getAddress();
if (!IpUtil.isAmqpUri(targetAdress) || CollectionUtils.isEmpty(actions)) {
final URI targetAddress = target.getAddress();
if (!IpUtil.isAmqpUri(targetAddress) || CollectionUtils.isEmpty(actions)) {
return;
}

Expand All @@ -209,17 +203,15 @@ protected void sendMultiActionRequestToTarget(final String tenant, final Target

final Message message = getMessageConverter().toMessage(multiActionRequest,
createConnectorMessagePropertiesEvent(tenant, target.getControllerId(), EventTopic.MULTI_ACTION));
amqpSenderService.sendMessage(message, targetAdress);

amqpSenderService.sendMessage(message, targetAddress);
}

private DmfActionRequest createDmfActionRequest(final Target target, final Action action,
final Map<SoftwareModule, List<SoftwareModuleMetadata>> softwareModules) {
if (action.isCancelingOrCanceled()) {
return createPlainActionRequest(action);
}
return createDownloadAndUpdateRequest(target, action, softwareModules);

return createDownloadAndUpdateRequest(target, action.getId(), softwareModules);
}

private static DmfActionRequest createPlainActionRequest(final Action action) {
Expand All @@ -228,11 +220,12 @@ private static DmfActionRequest createPlainActionRequest(final Action action) {
return actionRequest;
}

private DmfDownloadAndUpdateRequest createDownloadAndUpdateRequest(final Target target, final Action action,
protected DmfDownloadAndUpdateRequest createDownloadAndUpdateRequest(final Target target, final Long actionId,
final Map<SoftwareModule, List<SoftwareModuleMetadata>> softwareModules) {
final DmfDownloadAndUpdateRequest request = new DmfDownloadAndUpdateRequest();
request.setActionId(action.getId());
request.setActionId(actionId);
request.setTargetSecurityToken(systemSecurityContext.runAsSystem(target::getSecurityToken));

if (softwareModules != null) {
softwareModules.entrySet()
.forEach(entry -> request.addSoftwareModule(convertToAmqpSoftwareModule(target, entry)));
Expand Down Expand Up @@ -325,26 +318,15 @@ protected void sendUpdateMessageToTarget(final ActionProperties action, final Ta

final String tenant = action.getTenant();

final URI targetAdress = target.getAddress();
if (!IpUtil.isAmqpUri(targetAdress)) {
final URI targetAddress = target.getAddress();
if (!IpUtil.isAmqpUri(targetAddress)) {
return;
}

final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = new DmfDownloadAndUpdateRequest();
downloadAndUpdateRequest.setActionId(action.getId());

final String targetSecurityToken = systemSecurityContext.runAsSystem(target::getSecurityToken);
downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken);

modules.entrySet().forEach(entry -> {

final DmfSoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, entry);
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
});

final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = createDownloadAndUpdateRequest(target, action.getId(), modules);
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
createConnectorMessagePropertiesEvent(tenant, target.getControllerId(), getEventTypeForTarget(action)));
amqpSenderService.sendMessage(message, targetAdress);
amqpSenderService.sendMessage(message, targetAddress);
}

protected void sendPingReponseToDmfReceiver(final Message ping, final String tenant, final String virtualHost) {
Expand All @@ -359,7 +341,6 @@ protected void sendPingReponseToDmfReceiver(final Message ping, final String ten
}

private void sendDeleteMessage(final String tenant, final String controllerId, final String targetAddress) {

if (!hasValidAddress(targetAddress)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import java.io.File;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
Expand All @@ -35,6 +35,7 @@
import org.eclipse.hawkbit.dmf.json.model.DmfActionRequest;
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.SystemManagement;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetAttributesRequestedEvent;
Expand Down Expand Up @@ -101,7 +102,7 @@ public void before() throws Exception {

final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class);
when(artifactUrlHandlerMock.getUrls(any(), any()))
.thenReturn(Arrays.asList(new ArtifactUrl("http", "download", "http://mockurl")));
.thenReturn(Collections.singletonList(new ArtifactUrl("http", "download", "http://mockurl")));

systemManagement = Mockito.mock(SystemManagement.class);
final TenantMetaData tenantMetaData = Mockito.mock(TenantMetaData.class);
Expand All @@ -116,20 +117,19 @@ public void before() throws Exception {

}

private Message getCaptureAdressEvent(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) {
private Message getCaptureAddressEvent(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) {
final Target target = targetManagement
.getByControllerID(targetAssignDistributionSetEvent.getActions().keySet().iterator().next()).get();
final Message sendMessage = createArgumentCapture(target.getAddress());
return sendMessage;
return createArgumentCapture(target.getAddress());
}

private Action createAction(final DistributionSet testDs) {
return getFirstAssignedAction(assignDistributionSet(testDs, testTarget));
}

@Test
@Description("Verifies that download and install event with 3 software moduls and no artifacts works")
public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
@Description("Verifies that download and install event with 3 software modules and no artifacts works")
public void testSendDownloadRequestWithSoftwareModulesAndNoArtifacts() {
final DistributionSet createDistributionSet = testdataFactory
.createDistributionSet(UUID.randomUUID().toString());
testdataFactory.addSoftwareModuleMetadata(createDistributionSet);
Expand All @@ -139,7 +139,7 @@ public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
action, serviceMatcher.getServiceId());
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
final Message sendMessage = getCaptureAddressEvent(targetAssignDistributionSetEvent);
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage,
action.getId());
assertThat(createDistributionSet.getModules()).hasSameSizeAs(downloadAndUpdateRequest.getSoftwareModules());
Expand All @@ -152,7 +152,7 @@ public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
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());
assertNotNull("Software module ID should be set", softwareModule.getModuleId());
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
continue;
}
Expand Down Expand Up @@ -186,16 +186,15 @@ public void testSendDownloadRequest() {
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
action, serviceMatcher.getServiceId());
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
final Message sendMessage = getCaptureAddressEvent(targetAssignDistributionSetEvent);
final DmfDownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage,
action.getId());

assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3,
downloadAndUpdateRequest.getSoftwareModules().size());
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);

for (final org.eclipse.hawkbit.dmf.json.model.DmfSoftwareModule softwareModule : downloadAndUpdateRequest
.getSoftwareModules()) {
for (final DmfSoftwareModule softwareModule : downloadAndUpdateRequest.getSoftwareModules()) {
if (!softwareModule.getModuleId().equals(module.getId())) {
continue;
}
Expand Down Expand Up @@ -259,7 +258,7 @@ public void sendDeleteRequest() {

@Test
@Description("Verifies that a delete message is not send if the address is not an amqp address.")
public void sendDeleteRequestWithNoAmqpAdress() {
public void sendDeleteRequestWithNoAmqpAddress() {

// setup
final String noAmqpUri = "http://anyhost";
Expand All @@ -274,8 +273,8 @@ public void sendDeleteRequestWithNoAmqpAdress() {
}

@Test
@Description("Verfies that a delete message is not send if the address is null.")
public void sendDeleteRequestWithNullAdress() {
@Description("Verifies that a delete message is not send if the address is null.")
public void sendDeleteRequestWithNullAddress() {

// setup
final String noAmqpUri = null;
Expand All @@ -293,7 +292,7 @@ private void assertCancelMessage(final Message sendMessage) {
assertEventMessage(sendMessage);
final DmfActionRequest actionId = convertMessage(sendMessage, DmfActionRequest.class);
assertEquals("Action ID should be 1", actionId.getActionId(), Long.valueOf(1));
assertEquals("The topc in the message should be a CANCEL_DOWNLOAD value", EventTopic.CANCEL_DOWNLOAD,
assertEquals("The topic in the message should be a CANCEL_DOWNLOAD value", EventTopic.CANCEL_DOWNLOAD,
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,7 @@ public void initListener() {
}

private <T> T waitUntilIsPresent(final Callable<Optional<T>> callable) {
createConditionFactory().until(() -> {
return securityRule.runAsPrivileged(() -> callable.call().isPresent());
});
createConditionFactory().until(() -> securityRule.runAsPrivileged(() -> callable.call().isPresent()));

try {
return securityRule.runAsPrivileged(() -> callable.call().get());
Expand All @@ -105,10 +103,8 @@ private <T> T waitUntilIsPresent(final Callable<Optional<T>> callable) {
}

protected void waitUntilEventMessagesAreDispatchedToTarget(final EventTopic... eventTopics) {
createConditionFactory().untilAsserted(() -> {
assertThat(replyToListener.getLatestEventMessageTopics())
.containsExactlyInAnyOrderElementsOf(Arrays.asList(eventTopics));
});
createConditionFactory().untilAsserted(() -> assertThat(replyToListener.getLatestEventMessageTopics())
.containsExactlyInAnyOrderElementsOf(Arrays.asList(eventTopics)));
replyToListener.resetLatestEventMessageTopics();
}

Expand Down Expand Up @@ -194,10 +190,10 @@ private void assertAssignmentMessage(final Set<SoftwareModule> dsModules, final
protected void assertDmfDownloadAndUpdateRequest(final DmfDownloadAndUpdateRequest request,
final Set<SoftwareModule> softwareModules, final String controllerId) {
Assert.assertThat(softwareModules, SoftwareModuleJsonMatcher.containsExactly(request.getSoftwareModules()));
request.getSoftwareModules()
.forEach(dmfModule -> assertThat(dmfModule.getMetadata()).containsExactly(
new DmfMetadata(TestdataFactory.VISIBLE_SM_MD_KEY, TestdataFactory.VISIBLE_SM_MD_VALUE)));
request.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).isNotNull();
assertThat(updatedTarget.getSecurityToken()).isEqualTo(request.getTargetSecurityToken());
}

Expand All @@ -223,9 +219,8 @@ protected Message createAndSendPingMessage(final String correlationId, final Str
}

protected void verifyReplyToListener() {
createConditionFactory().untilAsserted(() -> {
Mockito.verify(replyToListener, Mockito.atLeast(1)).handleMessage(Mockito.any());
});
createConditionFactory()
.untilAsserted(() -> Mockito.verify(replyToListener, Mockito.atLeast(1)).handleMessage(Mockito.any()));
}

protected Long cancelAction(final Long actionId, final String controllerId) {
Expand Down Expand Up @@ -273,9 +268,10 @@ protected void registerAndAssertTargetWithExistingTenant(final String target,
final int existingTargetsAfterCreation, final TargetUpdateStatus expectedTargetStatus,
final String createdBy) {
createAndSendThingCreated(target, TENANT_EXIST);
final Target registerdTarget = waitUntilIsPresent(() -> targetManagement.getByControllerID(target));
final Target registeredTarget = waitUntilIsPresent(() -> targetManagement.getByControllerID(target));
assertAllTargetsCount(existingTargetsAfterCreation);
assertTarget(registerdTarget, expectedTargetStatus, createdBy);
assertThat(registeredTarget).isNotNull();
assertTarget(registeredTarget, expectedTargetStatus, createdBy);
}

protected void registerSameTargetAndAssertBasedOnVersion(final String controllerId,
Expand All @@ -284,6 +280,7 @@ protected void registerSameTargetAndAssertBasedOnVersion(final String controller
createAndSendThingCreated(controllerId, TENANT_EXIST);
final Target registeredTarget = waitUntilIsPresent(() -> findTargetBasedOnNewVersion(controllerId, version));
assertAllTargetsCount(existingTargetsAfterCreation);
assertThat(registeredTarget).isNotNull();
assertThat(registeredTarget.getUpdateStatus()).isEqualTo(expectedTargetStatus);
}

Expand Down
Loading

0 comments on commit 3422781

Please sign in to comment.