Merge branch 'master' into Feature_Improve_Code_Quality
Conflicts: hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ArtifactUrlHandlerProperties.java hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/CacheFieldEntityListener.java hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java Signed-off-by: Michael Hirsch <michael.hirsch@bosch-si.com>
This commit is contained in:
@@ -8,20 +8,48 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.hawkbit.amqp.AmqpProperties;
|
||||
import org.eclipse.hawkbit.amqp.AmqpSenderService;
|
||||
import org.eclipse.hawkbit.amqp.DefaultAmqpSenderService;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SystemSecurityContextHolder;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties({ AmqpProperties.class })
|
||||
public class AmqpTestConfiguration {
|
||||
/**
|
||||
* @return the {@link SystemSecurityContext} singleton bean which make it
|
||||
* accessible in beans which cannot access the service directly,
|
||||
* e.g. JPA entities.
|
||||
*/
|
||||
@Bean
|
||||
public SystemSecurityContextHolder systemSecurityContextHolder() {
|
||||
return SystemSecurityContextHolder.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set the Jackson2JsonMessageConverter.
|
||||
@@ -45,4 +73,54 @@ public class AmqpTestConfiguration {
|
||||
public AmqpSenderService amqpSenderServiceBean(final RabbitTemplate rabbitTemplate) {
|
||||
return new DefaultAmqpSenderService(rabbitTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ExecutorService with security context availability in thread
|
||||
* execution..
|
||||
*/
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean
|
||||
public Executor asyncExecutor() {
|
||||
return new DelegatingSecurityContextExecutorService(threadPoolExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return central ThreadPoolExecutor for general purpose multi threaded
|
||||
* operations. Tries an orderly shutdown when destroyed.
|
||||
*/
|
||||
private ThreadPoolExecutor threadPoolExecutor() {
|
||||
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(10);
|
||||
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 10, 1000, TimeUnit.MILLISECONDS,
|
||||
blockingQueue, new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build());
|
||||
|
||||
return threadPoolExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link TaskExecutor} for task execution
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TaskExecutor taskExecutor() {
|
||||
return new ConcurrentTaskExecutor(asyncExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link ScheduledExecutorService} based on
|
||||
* {@link #threadPoolTaskScheduler()}.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ScheduledExecutorService scheduledExecutorService() {
|
||||
return threadPoolTaskScheduler().getScheduledExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link ThreadPoolTaskScheduler} for scheduled operations.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
|
||||
return new ThreadPoolTaskScheduler();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Test
|
||||
@Description("Tests authentication message without principal")
|
||||
public void testAuthenticationMessageBadCredantialsWithoutPricipal() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.createFileResourceBySha1("12345"));
|
||||
@@ -166,8 +166,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT, "vHost");
|
||||
final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -178,7 +177,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Test
|
||||
@Description("Tests authentication message without wrong credential")
|
||||
public void testAuthenticationMessageBadCredantialsWithWrongCredential() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.createFileResourceBySha1("12345"));
|
||||
when(tenantConfigurationManagement.getConfigurationValue(
|
||||
@@ -189,8 +188,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT, "vHost");
|
||||
final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -201,7 +199,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
@Test
|
||||
@Description("Tests authentication message successfull")
|
||||
public void testSuccessfullMessageAuthentication() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, CONTROLLLER_ID,
|
||||
FileResource.createFileResourceBySha1("12345"));
|
||||
when(tenantConfigurationManagement.getConfigurationValue(
|
||||
@@ -212,8 +210,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT, "vHost");
|
||||
final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -232,7 +229,9 @@ public class AmqpControllerAuthenticationTest {
|
||||
|
||||
private MessageProperties createMessageProperties(final MessageType type, final String replyTo) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
|
||||
if (type != null) {
|
||||
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
|
||||
}
|
||||
messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT);
|
||||
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
|
||||
messageProperties.setReplyTo(replyTo);
|
||||
|
||||
@@ -25,8 +25,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
||||
import org.eclipse.hawkbit.TestDataUtil;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
@@ -34,11 +32,12 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTestWithMongoDB;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -48,6 +47,7 @@ import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
@@ -57,6 +57,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
@ActiveProfiles({ "test" })
|
||||
@Features("Component Tests - Device Management Federation API")
|
||||
@Stories("AmqpMessage Dispatcher Service Test")
|
||||
@SpringApplicationConfiguration(classes = { org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
|
||||
public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
private static final String TENANT = "default";
|
||||
@@ -100,6 +101,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
|
||||
assertTrue("No softwaremmodule should be contained in the request",
|
||||
downloadAndUpdateRequest.getSoftwareModules().isEmpty());
|
||||
}
|
||||
@@ -107,8 +109,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
@Test
|
||||
@Description("Verfies that download and install event with 3 software moduls and no artifacts works")
|
||||
public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
|
||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||
distributionSetManagement);
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, TENANT, CONTROLLER_ID, 1L, dsA.getModules(), AMQP_URI, TEST_TOKEN);
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
@@ -116,6 +117,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
assertEquals("Expecting a size of 3 software modules in the reuqest", 3,
|
||||
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
|
||||
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
|
||||
.getSoftwareModules()) {
|
||||
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty());
|
||||
@@ -137,11 +139,10 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
@Test
|
||||
@Description("Verfies that download and install event with software moduls and artifacts works")
|
||||
public void testSendDownloadRequest() {
|
||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||
distributionSetManagement);
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
final SoftwareModule module = dsA.getModules().iterator().next();
|
||||
final List<DbArtifact> receivedList = new ArrayList<>();
|
||||
for (final Artifact artifact : TestDataUtil.generateArtifacts(artifactManagement, module.getId())) {
|
||||
for (final Artifact artifact : testdataFactory.createLocalArtifacts(module.getId())) {
|
||||
module.addArtifact((LocalArtifact) artifact);
|
||||
receivedList.add(new DbArtifact());
|
||||
}
|
||||
@@ -155,6 +156,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
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.SoftwareModule softwareModule : downloadAndUpdateRequest
|
||||
.getSoftwareModules()) {
|
||||
if (!softwareModule.getModuleId().equals(module.getId())) {
|
||||
|
||||
@@ -36,17 +36,23 @@ import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken;
|
||||
import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.security.SecurityTokenGenerator;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -54,6 +60,7 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
@@ -82,6 +89,9 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Mock
|
||||
private ControllerManagement controllerManagementMock;
|
||||
|
||||
@Mock
|
||||
private EntityFactory entityFactoryMock;
|
||||
|
||||
@Mock
|
||||
private ArtifactManagement artifactManagementMock;
|
||||
|
||||
@@ -103,6 +113,9 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Mock
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Mock
|
||||
private SystemSecurityContext systemSecurityContextMock;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
messageConverter = new Jackson2JsonMessageConverter();
|
||||
@@ -114,6 +127,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
amqpMessageHandlerService.setCache(cacheMock);
|
||||
amqpMessageHandlerService.setHostnameResolver(hostnameResolverMock);
|
||||
amqpMessageHandlerService.setEventBus(eventBus);
|
||||
amqpMessageHandlerService.setEntityFactory(entityFactoryMock);
|
||||
amqpMessageHandlerService.setSystemSecurityContext(systemSecurityContextMock);
|
||||
|
||||
}
|
||||
|
||||
@@ -125,8 +140,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = new Message(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to worng content type");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to worng content type");
|
||||
} catch (final AmqpRejectAndDontRequeueException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,8 +175,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no replyTo header was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no replyTo header was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
@@ -174,8 +189,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no thingID was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no thingID was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
}
|
||||
@@ -190,8 +205,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to unknown message type");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to unknown message type");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
}
|
||||
@@ -203,22 +218,22 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = new Message(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to unknown message type");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to unknown message type");
|
||||
} catch (final AmqpRejectAndDontRequeueException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to unknown topic");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted due to unknown topic");
|
||||
} catch (final AmqpRejectAndDontRequeueException e) {
|
||||
}
|
||||
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name());
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted because there was no event topic");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted because there was no event topic");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
@@ -236,8 +251,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no action id was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no action id was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
}
|
||||
@@ -253,8 +268,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no action id was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
fail("AmqpRejectAndDontRequeueException was excepeted since no action id was set");
|
||||
} catch (final AmqpRejectAndDontRequeueException exception) {
|
||||
// test ok - exception was excepted
|
||||
}
|
||||
|
||||
@@ -263,14 +278,14 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Test
|
||||
@Description("Tests that an download request is denied for an artifact which does not exists")
|
||||
public void authenticationRequestDeniedForArtifactWhichDoesNotExists() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.createFileResourceBySha1("12345"));
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123",
|
||||
FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT, "vHost");
|
||||
final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -282,8 +297,9 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Test
|
||||
@Description("Tests that an download request is denied for an artifact which is not assigned to the requested target")
|
||||
public void authenticationRequestDeniedForArtifactWhichIsNotAssignedToTarget() {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.createFileResourceBySha1("12345"));
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123",
|
||||
FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
@@ -293,8 +309,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
.thenThrow(EntityNotFoundException.class);
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT, "vHost");
|
||||
final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -306,8 +321,9 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Test
|
||||
@Description("Tests that an download request is allowed for an artifact which exists and assigned to the requested target")
|
||||
public void authenticationRequestAllowedForArtifactWhichExistsAndAssignedToTarget() throws MalformedURLException {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.AUTHENTIFICATION);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123", FileResource.createFileResourceBySha1("12345"));
|
||||
final MessageProperties messageProperties = createMessageProperties(null);
|
||||
final TenantSecurityToken securityToken = new TenantSecurityToken(TENANT, "123",
|
||||
FileResource.createFileResourceBySha1("12345"));
|
||||
final Message message = amqpMessageHandlerService.getMessageConverter().toMessage(securityToken,
|
||||
messageProperties);
|
||||
|
||||
@@ -324,8 +340,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
when(hostnameResolverMock.resolveHostname()).thenReturn(new URL("http://localhost"));
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT, "vHost");
|
||||
final Message onMessage = amqpMessageHandlerService.onAuthenticationRequest(message);
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -346,7 +361,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
// Mock
|
||||
final Action action = createActionWithTarget(22L, Status.FINISHED);
|
||||
when(controllerManagementMock.findActionWithDetails(Matchers.any())).thenReturn(action);
|
||||
when(controllerManagementMock.addUpdateActionStatus(Matchers.any(), Matchers.any())).thenReturn(action);
|
||||
when(controllerManagementMock.addUpdateActionStatus(Matchers.any())).thenReturn(action);
|
||||
when(entityFactoryMock.generateActionStatus()).thenReturn(new JpaActionStatus());
|
||||
// for the test the same action can be used
|
||||
final List<Action> actionList = new ArrayList<>();
|
||||
actionList.add(action);
|
||||
@@ -356,6 +372,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
when(controllerManagementMock.findSoftwareModulesByDistributionSet(Matchers.any()))
|
||||
.thenReturn(softwareModuleList);
|
||||
|
||||
when(systemSecurityContextMock.runAsSystem(anyObject())).thenReturn("securityToken");
|
||||
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
||||
final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L);
|
||||
@@ -400,7 +418,9 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
private MessageProperties createMessageProperties(final MessageType type, final String replyTo) {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
|
||||
if (type != null) {
|
||||
messageProperties.setHeader(MessageHeaderKey.TYPE, type.name());
|
||||
}
|
||||
messageProperties.setHeader(MessageHeaderKey.TENANT, TENANT);
|
||||
messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON);
|
||||
messageProperties.setReplyTo(replyTo);
|
||||
@@ -409,7 +429,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
private List<SoftwareModule> createSoftwareModuleList() {
|
||||
final List<SoftwareModule> softwareModuleList = new ArrayList<>();
|
||||
final SoftwareModule softwareModule = new SoftwareModule();
|
||||
final JpaSoftwareModule softwareModule = new JpaSoftwareModule();
|
||||
softwareModule.setId(777L);
|
||||
softwareModuleList.add(softwareModule);
|
||||
return softwareModuleList;
|
||||
@@ -420,14 +440,18 @@ public class AmqpMessageHandlerServiceTest {
|
||||
initalizeSecurityTokenGenerator();
|
||||
|
||||
// Mock
|
||||
final Action action = new Action();
|
||||
action.setId(targetId);
|
||||
action.setStatus(status);
|
||||
action.setTenant("DEFAULT");
|
||||
final Target target = new Target("target1");
|
||||
action.setTarget(target);
|
||||
|
||||
return action;
|
||||
final JpaAction actionMock = mock(JpaAction.class);
|
||||
final JpaTarget targetMock = mock(JpaTarget.class);
|
||||
final TargetInfo targetInfoMock = mock(TargetInfo.class);
|
||||
when(actionMock.getId()).thenReturn(targetId);
|
||||
when(actionMock.getStatus()).thenReturn(status);
|
||||
when(actionMock.getTenant()).thenReturn("DEFAULT");
|
||||
when(actionMock.getTarget()).thenReturn(targetMock);
|
||||
when(targetMock.getControllerId()).thenReturn("target1");
|
||||
when(targetMock.getSecurityToken()).thenReturn("securityToken");
|
||||
when(targetMock.getTargetInfo()).thenReturn(targetInfoMock);
|
||||
when(targetInfoMock.getAddress()).thenReturn(null);
|
||||
return actionMock;
|
||||
}
|
||||
|
||||
private void initalizeSecurityTokenGenerator() throws IllegalAccessException {
|
||||
|
||||
@@ -10,17 +10,13 @@ package org.eclipse.hawkbit.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
|
||||
import org.eclipse.hawkbit.AmqpTestConfiguration;
|
||||
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.TestConfiguration;
|
||||
import org.eclipse.hawkbit.TestDataUtil;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.api.UrlProtocol;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.repository.test.util.AbstractIntegrationTestWithMongoDB;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -35,27 +31,27 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
*/
|
||||
@Features("Component Tests - Artifact URL Handler")
|
||||
@Stories("Test to generate the artifact download URL")
|
||||
@SpringApplicationConfiguration(classes = { RepositoryApplicationConfiguration.class, TestConfiguration.class,
|
||||
AmqpTestConfiguration.class })
|
||||
@SpringApplicationConfiguration(classes = { AmqpTestConfiguration.class,
|
||||
org.eclipse.hawkbit.RepositoryApplicationConfiguration.class })
|
||||
public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
private static final String HTTPS_LOCALHOST = "https://localhost:8080/";
|
||||
private static final String HTTP_LOCALHOST = "http://localhost:8080/";
|
||||
|
||||
@Autowired
|
||||
private ArtifactUrlHandler urlHandlerProperties;
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
private LocalArtifact localArtifact;
|
||||
private final String controllerId = "Test";
|
||||
private static final String CONTROLLER_ID = "Test";
|
||||
private String fileName;
|
||||
private Long softwareModuleId;
|
||||
private String sha1Hash;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||
distributionSetManagement);
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
final SoftwareModule module = dsA.getModules().iterator().next();
|
||||
localArtifact = (LocalArtifact) TestDataUtil.generateArtifacts(artifactManagement, module.getId()).stream()
|
||||
.findAny().get();
|
||||
localArtifact = testdataFactory.createLocalArtifacts(module.getId()).stream().findAny().get();
|
||||
softwareModuleId = localArtifact.getSoftwareModule().getId();
|
||||
fileName = localArtifact.getFilename();
|
||||
sha1Hash = localArtifact.getSha1Hash();
|
||||
@@ -66,10 +62,10 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
||||
@Description("Tests the generation of http download url.")
|
||||
public void testHttpUrl() {
|
||||
|
||||
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
|
||||
final String url = urlHandlerProperties.getUrl(CONTROLLER_ID, softwareModuleId, fileName, sha1Hash,
|
||||
UrlProtocol.HTTP);
|
||||
assertEquals("http is build incorrect",
|
||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + CONTROLLER_ID
|
||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||
+ localArtifact.getFilename(),
|
||||
url);
|
||||
@@ -78,10 +74,10 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
||||
@Test
|
||||
@Description("Tests the generation of https download url.")
|
||||
public void testHttpsUrl() {
|
||||
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
|
||||
final String url = urlHandlerProperties.getUrl(CONTROLLER_ID, softwareModuleId, fileName, sha1Hash,
|
||||
UrlProtocol.HTTPS);
|
||||
assertEquals("https is build incorrect",
|
||||
"https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
HTTPS_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + CONTROLLER_ID
|
||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||
+ localArtifact.getFilename(),
|
||||
url);
|
||||
@@ -90,10 +86,10 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
||||
@Test
|
||||
@Description("Tests the generation of coap download url.")
|
||||
public void testCoapUrl() {
|
||||
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
|
||||
final String url = urlHandlerProperties.getUrl(CONTROLLER_ID, softwareModuleId, fileName, sha1Hash,
|
||||
UrlProtocol.COAP);
|
||||
|
||||
assertEquals("coap is build incorrect", "coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/"
|
||||
+ controllerId + "/sha1/" + localArtifact.getSha1Hash(), url);
|
||||
+ CONTROLLER_ID + "/sha1/" + localArtifact.getSha1Hash(), url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
|
||||
|
||||
# supported: H2, MYSQL
|
||||
hawkbit.server.database=H2
|
||||
|
||||
spring.jpa.database=${hawkbit.server.database}
|
||||
|
||||
|
||||
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
|
||||
|
||||
# effective DB setting
|
||||
spring.datasource.url=${${hawkbit.server.database}.spring.datasource.url}
|
||||
spring.datasource.driverClassName=${${hawkbit.server.database}.spring.datasource.driverClassName}
|
||||
spring.datasource.username=${${hawkbit.server.database}.spring.datasource.username}
|
||||
spring.datasource.password=${${hawkbit.server.database}.spring.datasource.password}
|
||||
|
||||
# H2
|
||||
##;AUTOCOMMIT=ON
|
||||
H2.spring.datasource.url=jdbc:h2:mem:sp-db;DB_CLOSE_ON_EXIT=FALSE
|
||||
#H2.spring.datasource.url=jdbc:h2:./db/sp-db;AUTO_SERVER=TRUE;DB_CLOSE_ON_EXIT=FALSE;MVCC=TRUE
|
||||
H2.spring.datasource.driverClassName=org.h2.Driver
|
||||
H2.spring.datasource.username=sa
|
||||
H2.spring.datasource.password=sa
|
||||
|
||||
# MYSQL
|
||||
MYSQL.spring.datasource.url=jdbc:mysql://localhost:3306/sp_test
|
||||
MYSQL.spring.datasource.driverClassName=org.mariadb.jdbc.Driver
|
||||
MYSQL.spring.datasource.username=root
|
||||
MYSQL.spring.datasource.password=
|
||||
35
hawkbit-dmf-amqp/src/test/resources/logback.xml
Normal file
35
hawkbit-dmf-amqp/src/test/resources/logback.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
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
|
||||
|
||||
-->
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||
|
||||
<logger name="org.eclipse.hawkbit.eventbus.DeadEventListener" level="WARN" />
|
||||
<Logger name="org.springframework.boot.actuate.audit.listener.AuditListener" level="WARN" />
|
||||
|
||||
<Logger name="org.hibernate.validator.internal.util.Version" level="WARN" />
|
||||
|
||||
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN" />
|
||||
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN" />
|
||||
<Logger name="org.apache.tomcat.jdbc.pool.ConnectionPool" level="DEBUG" />
|
||||
<Logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR" />
|
||||
|
||||
|
||||
<!-- <Logger name="org.eclipse.hawkbit.rest.util.MockMvcResultPrinter" level="DEBUG" /> -->
|
||||
|
||||
<!-- Security Log with hints on potential attacks -->
|
||||
<logger name="server-security" level="INFO" />
|
||||
|
||||
<Root level="INFO">
|
||||
<AppenderRef ref="Console" />
|
||||
</Root>
|
||||
|
||||
</configuration>
|
||||
Reference in New Issue
Block a user