Merge branch 'master' into
feature_MECS-86_tenant_specific_polling_configuration Conflicts: hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/security/SecurityManagedConfiguration.java hawkbit-core/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationKey.java hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentfication.java hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpControllerAuthentficationTest.java hawkbit-repository/src/test/resources/application-test.properties Signed-off-by: SirWayne <dennis.melzer@bosch-si.com>
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -16,13 +16,13 @@
|
||||
*.jar
|
||||
*.war
|
||||
|
||||
######################
|
||||
# Sonar
|
||||
######################
|
||||
.sonar_lock
|
||||
|
||||
# Eclipse IDE
|
||||
# Created by spring-boot-configuration-processor
|
||||
.factorypath
|
||||
|
||||
# Eclipse IDE
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
Please read this if you intend to contribute to the project.
|
||||
|
||||
## Code Conventions
|
||||
## Conventions
|
||||
|
||||
### Code Style
|
||||
|
||||
* Java files:
|
||||
* we follow the standard eclipse IDE (built in) code formatter with the following changes:
|
||||
@@ -19,6 +21,37 @@ Please read this if you intend to contribute to the project.
|
||||
* Sonarqube:
|
||||
* Our rule set is defined [here](http://sonar.eu-gb.mybluemix.net)
|
||||
|
||||
### Test documentation
|
||||
|
||||
Please documented the test cases that you contribute by means of [Allure](http://allure.qatools.ru) annotations and proper test method naming.
|
||||
|
||||
All test classes are documented with [Allure's](https://github.com/allure-framework/allure-core/wiki/Features-and-Stories) **@Features** and **@Stories** annotations in the following format:
|
||||
```
|
||||
@Features("TEST_TYPE - HAWKBIT_COMPONENT")
|
||||
@Stories("Test class description")
|
||||
```
|
||||
|
||||
Test types are:
|
||||
* Unit Tests - for single units tests with a mocked environment
|
||||
* Component Tests - for complete components including lower layers, e.g. Spring MVC test on rest API including repository and database.
|
||||
* Integration Tests - including clients, e.g. Selenium UI tests with various browsers.
|
||||
* System Tests - on target environments, e.g. Cloud Foundry.
|
||||
|
||||
Examples for hawkBit components:
|
||||
* Management API
|
||||
* Direct Device Integration API
|
||||
* Device Management Federation API
|
||||
* Management UI
|
||||
* Repository
|
||||
* Security
|
||||
|
||||
```
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Distribution Set Type Resource")
|
||||
```
|
||||
|
||||
In addition all test method's name describes in **camel case** what the test is all about and has a long description aith Allures **@Description** annotation.
|
||||
|
||||
## Legal considerations for your contribution
|
||||
|
||||
The following steps are necessary to comply with the Eclipse Foundation's IP policy.
|
||||
|
||||
9
MIGRATION.md
Normal file
9
MIGRATION.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# hawkBit Migration Guides
|
||||
## Release 0.2
|
||||
### Configuration Property changes
|
||||
- hawkbit.server.controller._ have changed to hawkbit.server.ddi._
|
||||
- info.build._ have changed to hawkbit.server.build._
|
||||
- hawkbit.server.demo._ have changed to hawkbit.server.ui.demo._
|
||||
- hawkbit.server.email.support has changed to hawkbit.server.ui.links.support
|
||||
- hawkbit.server.email.request.account has changed to hawkbit.server.ui.links.requestAccount
|
||||
- hawkbit.server.im.login.url has changed to hawkbit.server.ui.links.userManagement
|
||||
@@ -100,7 +100,6 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>19.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
@@ -116,13 +115,18 @@
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
<artifactId>vaadin-bom</artifactId>
|
||||
<version>7.5.5</version>
|
||||
<version>7.6.3</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -9,21 +9,35 @@
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Bean which holds the necessary properties for configuring the AMQP
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.device.simulator.amqp")
|
||||
public class AmqpProperties {
|
||||
|
||||
/**
|
||||
* Queue for receiving DMF messages from update server.
|
||||
*/
|
||||
private String receiverConnectorQueueFromSp;
|
||||
|
||||
/**
|
||||
* Exchange for sending DMF messages to update server.
|
||||
*/
|
||||
private String senderForSpExchange;
|
||||
|
||||
/**
|
||||
* Simulator dead letter queue.
|
||||
*/
|
||||
private String deadLetterQueue;
|
||||
|
||||
/**
|
||||
* Simulator dead letter exchange.
|
||||
*/
|
||||
private String deadLetterExchange;
|
||||
|
||||
public String getReceiverConnectorQueueFromSp() {
|
||||
|
||||
@@ -8,21 +8,12 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.app;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
||||
import org.eclipse.hawkbit.ui.DispatcherRunnable;
|
||||
import org.eclipse.hawkbit.ui.HawkbitUI;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
|
||||
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
||||
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.eventbus.AllowConcurrentEvents;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.vaadin.annotations.Push;
|
||||
import com.vaadin.server.VaadinSession;
|
||||
import com.vaadin.server.VaadinSession.State;
|
||||
import com.vaadin.server.WrappedSession;
|
||||
import com.vaadin.shared.communication.PushMode;
|
||||
import com.vaadin.shared.ui.ui.Transport;
|
||||
import com.vaadin.spring.annotation.SpringUI;
|
||||
@@ -33,45 +24,16 @@ import com.vaadin.spring.annotation.SpringUI;
|
||||
* A {@link SpringUI} annotated class must be present in the classpath. The
|
||||
* easiest way to get an hawkBit UI running is to extend the {@link HawkbitUI}
|
||||
* and to annotated it with {@link SpringUI} as in this example.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@SpringUI
|
||||
@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET)
|
||||
@EventSubscriber
|
||||
public class MyUI extends HawkbitUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* An {@link com.google.common.eventbus.EventBus} subscriber which
|
||||
* subscribes {@link EntityEvent} from the repository to dispatch these
|
||||
* events to the UI {@link SessionEventBus}.
|
||||
*
|
||||
* @param event
|
||||
* the entity event which has been published from the repository
|
||||
*/
|
||||
@Override
|
||||
@Subscribe
|
||||
@AllowConcurrentEvents
|
||||
public void dispatch(final org.eclipse.hawkbit.eventbus.event.Event event) {
|
||||
final VaadinSession session = getSession();
|
||||
if (session != null && session.getState() == State.OPEN) {
|
||||
final WrappedSession wrappedSession = session.getSession();
|
||||
if (wrappedSession != null) {
|
||||
final SecurityContext userContext = (SecurityContext) wrappedSession
|
||||
.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
|
||||
if (eventSecurityCheck(userContext, event)) {
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
try {
|
||||
access(new DispatcherRunnable(eventBus, session, userContext, event));
|
||||
} finally {
|
||||
SecurityContextHolder.setContext(oldContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@Autowired
|
||||
public MyUI(final EventBus systemEventBus, final org.vaadin.spring.events.EventBus.SessionEventBus eventBus) {
|
||||
super(new DelayedEventBusPushStrategy(eventBus, systemEventBus));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,23 +7,20 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
# need to re-name these properties in the defaulthawkbit.properties and code!
|
||||
hawkbit.server.controller.security.authentication.anonymous.enabled=true
|
||||
hawkbit.server.controller.security.authentication.header.enabled=false
|
||||
hawkbit.server.controller.security.authentication.targettoken.enabled=false
|
||||
hawkbit.server.controller.security.authentication.gatewaytoken.enabled=false
|
||||
hawkbit.server.ddi.security.authentication.anonymous.enabled=true
|
||||
hawkbit.server.ddi.security.authentication.targettoken.enabled=false
|
||||
hawkbit.server.ddi.security.authentication.gatewaytoken.enabled=false
|
||||
|
||||
spring.profiles.active=amqp
|
||||
|
||||
vaadin.servlet.productionMode=false
|
||||
vaadin.static.servlet.productionMode=false
|
||||
|
||||
## Configuration for RabbitMQ integration
|
||||
hawkbit.server.amqp.username=guest
|
||||
hawkbit.server.amqp.password=guest
|
||||
hawkbit.server.amqp.virtualHost=/
|
||||
hawkbit.server.amqp.host=localhost
|
||||
hawkbit.server.amqp.port=5672
|
||||
hawkbit.server.amqp.deadLetterQueue=sp_deadletter
|
||||
hawkbit.server.amqp.deadLetterExchange=sp.deadletter
|
||||
hawkbit.server.amqp.receiverQueue=sp_receiver
|
||||
spring.rabbitmq.username=guest
|
||||
spring.rabbitmq.password=guest
|
||||
spring.rabbitmq.virtualHost=/
|
||||
spring.rabbitmq.host=localhost
|
||||
spring.rabbitmq.port=5672
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
|
||||
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
|
||||
@@ -87,5 +87,10 @@
|
||||
<artifactId>google-collections</artifactId>
|
||||
<version>1.0-rc2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -18,8 +18,19 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
@ConfigurationProperties(prefix = "hawkbit")
|
||||
public class ClientConfigurationProperties {
|
||||
|
||||
/**
|
||||
* Update server URI.
|
||||
*/
|
||||
private String url = "localhost:8080";
|
||||
|
||||
/**
|
||||
* Update server user name.
|
||||
*/
|
||||
private String username = "admin";
|
||||
|
||||
/**
|
||||
* Update server password.
|
||||
*/
|
||||
private String password = "admin"; // NOSONAR this password is only used for
|
||||
// examples
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ public class SoftwareModuleAssigmentBuilder {
|
||||
private final List<Long> ids;
|
||||
|
||||
public SoftwareModuleAssigmentBuilder() {
|
||||
ids = new ArrayList<Long>();
|
||||
ids = new ArrayList<>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,4 +11,4 @@ hawkbit.url=localhost:8080
|
||||
hawkbit.username=admin
|
||||
hawkbit.password=admin
|
||||
|
||||
spring.main.banner-mode=OFF
|
||||
spring.main.show-banner=false
|
||||
@@ -1,6 +1,3 @@
|
||||
<!-- 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 -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
|
||||
@@ -34,6 +34,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import com.google.common.io.BaseEncoding;
|
||||
import com.mongodb.gridfs.GridFSDBFile;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Artifact Store MongoDB")
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = { ArtifactStoreAutoConfiguration.class, TestConfiguration.class })
|
||||
public class ArtifactStoreTest {
|
||||
@@ -48,6 +54,7 @@ public class ArtifactStoreTest {
|
||||
private GridFsOperations gridFs;
|
||||
|
||||
@Test
|
||||
@Description("Ensures that storage in MongoDB is correctly executed.s")
|
||||
public void storeArtifactInMongoDB() {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
@@ -60,6 +67,7 @@ public class ArtifactStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that search by SHA1 hash (which is used by hawkBit as artifact ID) finds the expected results.")
|
||||
public void findArtifactBySHA1Hash() throws NoSuchAlgorithmException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
@@ -72,6 +80,7 @@ public class ArtifactStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that search by MD5 hash finds the expected results.")
|
||||
public void findArtifactByMD5Hash() throws NoSuchAlgorithmException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
@@ -84,6 +93,7 @@ public class ArtifactStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that artifact content can be read through InputStream.")
|
||||
public void getInputStreamFromArtifact() throws IOException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
@@ -103,7 +113,8 @@ public class ArtifactStoreTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deleteArtifactWithOnlyOneTenantLast() throws NoSuchAlgorithmException {
|
||||
@Description("Ensures that artifact delete actually results in deletion from database.")
|
||||
public void deleteArtifact() throws NoSuchAlgorithmException {
|
||||
final int filelengthBytes = 128;
|
||||
final String filename = "testfile.json";
|
||||
final String contentType = "application/json";
|
||||
|
||||
@@ -72,5 +72,10 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* 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.autoconfigure.conf;
|
||||
|
||||
import org.eclipse.hawkbit.ControllerPollProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Enable the Controlle Poll.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(ControllerPollProperties.class)
|
||||
@EnableConfigurationProperties(ControllerPollProperties.class)
|
||||
public class ControllerPollAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -13,17 +13,29 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
/**
|
||||
* Properties for the async configurer.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.threadpool")
|
||||
public class AsyncConfigurerThreadpoolProperties {
|
||||
|
||||
/**
|
||||
* Max queue size for central event executor.
|
||||
*/
|
||||
private Integer queuesize = 250;
|
||||
|
||||
/**
|
||||
* Core processing threads for central event executor.
|
||||
*/
|
||||
private Integer corethreads = 5;
|
||||
|
||||
/**
|
||||
* Maximum thread pool size for central event executor.
|
||||
*/
|
||||
private Integer maxthreads = 50;
|
||||
|
||||
/**
|
||||
* When the number of threads is greater than the core, this is the maximum
|
||||
* time that excess idle threads will wait for new tasks before terminating.
|
||||
*/
|
||||
private Long idletimeout = 10000L;
|
||||
|
||||
public Integer getQueuesize() {
|
||||
|
||||
@@ -26,10 +26,9 @@ import org.springframework.security.concurrent.DelegatingSecurityContextExecutor
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
*
|
||||
* Central event processors inside update server.
|
||||
*
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AsyncConfigurerThreadpoolProperties.class)
|
||||
public class ExecutorAutoConfiguration {
|
||||
@@ -40,7 +39,7 @@ public class ExecutorAutoConfiguration {
|
||||
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
|
||||
|
||||
/**
|
||||
* @return ExecutorService for general pupose multi threaded operations
|
||||
* @return ExecutorService for general purpose multi threaded operations
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
@@ -53,7 +53,7 @@ import org.springframework.security.web.authentication.www.BasicAuthenticationFi
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(SecurityProperties.class)
|
||||
@EnableConfigurationProperties(DdiSecurityProperties.class)
|
||||
public class SecurityAutoConfiguration {
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,30 +32,28 @@ import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.rest.resource.RestConstants;
|
||||
import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSource;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DosFilter;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.HttpControllerPreAuthenticatedSecurityHeaderFilter;
|
||||
import org.eclipse.hawkbit.security.HttpDownloadAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
@@ -96,17 +94,11 @@ import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSucc
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
|
||||
@EnableWebMvcSecurity
|
||||
@Order(value = Ordered.HIGHEST_PRECEDENCE)
|
||||
public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
public class SecurityManagedConfiguration {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SecurityManagedConfiguration.class);
|
||||
|
||||
private static final String SP_SERVER_CONFIG_PREFIX = "hawkbit.server.";
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
|
||||
|
||||
}
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* {@link WebSecurityConfigurer} for the internal SP controller API.
|
||||
@@ -125,7 +117,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
@Autowired
|
||||
private SecurityProperties securityConfiguration;
|
||||
private DdiSecurityProperties ddiSecurityConfiguration;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
@Autowired
|
||||
@@ -136,8 +128,9 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
|
||||
|
||||
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
|
||||
securityConfiguration.getRpCnHeader(), securityConfiguration.getRpSslIssuerHashHeader(),
|
||||
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
ddiSecurityConfiguration.getRp().getCnHeader(),
|
||||
ddiSecurityConfiguration.getRp().getSslIssuerHashHeader(), tenantConfigurationManagement,
|
||||
tenantAware, systemSecurityContext);
|
||||
securityHeaderFilter.setAuthenticationManager(authenticationManager());
|
||||
securityHeaderFilter.setCheckForPrincipalChanges(true);
|
||||
securityHeaderFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
@@ -162,7 +155,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
|
||||
}
|
||||
|
||||
if (securityConfiguration.getAnonymousEnabled()) {
|
||||
if (ddiSecurityConfiguration.getAuthentication().getAnonymous().isEnabled()) {
|
||||
LOG.info(
|
||||
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
|
||||
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
|
||||
@@ -181,19 +174,10 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.security.config.annotation.web.configuration.
|
||||
* WebSecurityConfigurerAdapter
|
||||
* #configure(org.springframework.security.config.annotation.
|
||||
* authentication.builders. AuthenticationManagerBuilder)
|
||||
*/
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(
|
||||
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
|
||||
auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(
|
||||
ddiSecurityConfiguration.getRp().getTrustedIPs()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,13 +192,10 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
public FilterRegistrationBean dosFilter() {
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
|
||||
filterRegBean
|
||||
.setFilter(
|
||||
new DosFilter(environment.getProperty("security.dos.filter.maxRead", Integer.class, 200),
|
||||
environment.getProperty("security.dos.filter.maxWrite", Integer.class, 50),
|
||||
environment.getProperty("security.dos.filter.whitelist"), environment
|
||||
.getProperty("security.clients.blacklist"),
|
||||
environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
|
||||
filterRegBean.setFilter(new DosFilter(securityProperties.getDos().getFilter().getMaxRead(),
|
||||
securityProperties.getDos().getFilter().getMaxWrite(),
|
||||
securityProperties.getDos().getFilter().getWhitelist(), securityProperties.getClients().getBlacklist(),
|
||||
securityProperties.getClients().getRemoteIpHeader()));
|
||||
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
|
||||
return filterRegBean;
|
||||
}
|
||||
@@ -314,8 +295,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
@Configuration
|
||||
@Order(400)
|
||||
@EnableVaadinSecurity
|
||||
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter
|
||||
implements EnvironmentAware {
|
||||
public static class UISecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private static final String XFRAME_OPTION_DENY = "DENY";
|
||||
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
|
||||
@@ -324,13 +304,8 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
private VaadinSecurityContext vaadinSecurityContext;
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
|
||||
}
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* post construct for setting the authentication success handler for the
|
||||
@@ -383,13 +358,13 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
// configuration xframe-option
|
||||
final String confXframeOption = environment.getProperty("security.xframe.option", XFRAME_OPTION_DENY);
|
||||
final String confAllowFromUri = environment.getProperty("security.xframe.option.allowfrom");
|
||||
if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri == null) {
|
||||
final String confXframeOption = securityProperties.getXframe().getOption();
|
||||
final String confAllowFromUri = securityProperties.getXframe().getAllowfrom();
|
||||
if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri.isEmpty()) {
|
||||
// if allow-from option is specified but no allowFromUri throw
|
||||
// exception
|
||||
throw new IllegalStateException("hawkbit.server.security.xframe.option has been specified as ALLOW-FROM"
|
||||
+ " but no hawkbit.server.security.xframe.option.allowfrom has been set, "
|
||||
+ " but no hawkbit.server.security.xframe.allowfrom has been set, "
|
||||
+ "please ensure to set allow from URIs");
|
||||
}
|
||||
|
||||
@@ -465,7 +440,7 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
public static class IdRestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties securityConfiguration;
|
||||
private DdiSecurityProperties ddiSecurityConfiguration;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
@@ -487,8 +462,8 @@ public class SecurityManagedConfiguration implements EnvironmentAware {
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(
|
||||
new PreAuthTokenSourceTrustAuthenticationProvider(securityConfiguration.getRpTrustedIPs()));
|
||||
auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(
|
||||
ddiSecurityConfiguration.getRp().getTrustedIPs()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.autoconfigure.url;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.HawkbitServerProperties;
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
@@ -27,11 +28,11 @@ import com.google.common.base.Throwables;
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(ServerProperties.class)
|
||||
@EnableConfigurationProperties(HawkbitServerProperties.class)
|
||||
public class PropertyHostnameResolverAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ServerProperties serverProperties;
|
||||
private HawkbitServerProperties serverProperties;
|
||||
|
||||
/**
|
||||
* @return the default autoconfigure hostname resolver implementation which
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* 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.autoconfigure.url;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for the server e.g. the server's URL which must be configured.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server")
|
||||
public class ServerProperties {
|
||||
|
||||
private String url = "http://localhost:8080";
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -11,5 +11,4 @@ org.eclipse.hawkbit.autoconfigure.eventbus.EventBusAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.conf.ControllerPollAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
# Tomcat / Server
|
||||
server.tomcat.compression=on
|
||||
spring.http.gzip.mime-types=text/html,text/xml,text/plain,application/json,application/javascript,text/css,application/x-javascript,text/javascript,application/vnd.ms-fontobject,application/x-font-opentype,application/x-font-truetype,application/x-font-ttf,application/xml,font/eot,font/opentype,font/otf,image/svg+xml,image/vnd.microsoft.icon
|
||||
server.tomcat.compressable-mime-types=${spring.http.gzip.mime-types}
|
||||
spring.http.gzip.min-gzip-size=256
|
||||
|
||||
# JPA / Datasource
|
||||
spring.jpa.eclipselink.eclipselink.weaving=false
|
||||
spring.jpa.database=H2
|
||||
@@ -21,7 +15,6 @@ spring.datasource.driverClassName=org.h2.Driver
|
||||
|
||||
# MongoDB for artifact-repository
|
||||
spring.data.mongodb.uri=mongodb://localhost/artifactrepo
|
||||
spring.data.mongo.repositories.enabled=true
|
||||
|
||||
# Flyway DDL
|
||||
flyway.enabled=true
|
||||
@@ -29,15 +22,10 @@ flyway.initOnMigrate=true
|
||||
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
|
||||
|
||||
# Vaadin Servlet
|
||||
vaadin.static.servlet.productionMode=true
|
||||
vaadin.servlet.productionMode=true
|
||||
vaadin.servlet.urlMapping=/UI/*
|
||||
vaadin.servlet.params.heartbeatInterval=60
|
||||
vaadin.servlet.params.closeIdleSessions=false
|
||||
|
||||
# Spring MVC
|
||||
spring.mvc.favicon.enabled=false
|
||||
|
||||
vaadin.servlet.heartbeatInterval=60
|
||||
vaadin.servlet.closeIdleSessions=false
|
||||
|
||||
# Defines the thread pool executor
|
||||
hawkbit.threadpool.corethreads=5
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Test -->
|
||||
|
||||
@@ -26,8 +26,6 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
|
||||
* The spring Redis configuration which is enabled by using the profile
|
||||
* {@code redis} to use a Redis server as cache.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(RedisProperties.class)
|
||||
|
||||
@@ -14,14 +14,18 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Bean which holds the necessary properties for configuring the Redis
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server.redis")
|
||||
public class RedisProperties {
|
||||
|
||||
/**
|
||||
* Redis server hostname.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* Redis server port.
|
||||
*/
|
||||
private int port;
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,13 @@ import org.springframework.hateoas.Identifiable;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Cluster Cache")
|
||||
@Stories("EventDistributor Test")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
// TODO: create description annotations
|
||||
public class EventDistributorTest {
|
||||
|
||||
@Mock
|
||||
|
||||
@@ -13,6 +13,11 @@ import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import org.eclipse.hawkbit.cache.RedisProperties;
|
||||
import org.junit.Test;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Cluster Cache")
|
||||
@Stories("Redis Properties Test")
|
||||
public class RedisPropertiesTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -43,6 +43,11 @@
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -9,18 +9,26 @@
|
||||
package org.eclipse.hawkbit;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Defines the polling time for the controllers in HH:MM:SS notation.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "hawkbit.controller")
|
||||
public class ControllerPollProperties {
|
||||
|
||||
/**
|
||||
* Recommended target polling time for DDI API. Final choice is up to the
|
||||
* target.
|
||||
*/
|
||||
private String pollingTime = "00:05:00";
|
||||
|
||||
/**
|
||||
* Assumed time frame where the target is considered overdue when no DDI
|
||||
* polling has been registered by the update server.
|
||||
*/
|
||||
private String pollingOverdueTime = "00:05:00";
|
||||
private String maxPollingTime = "23:59:00";
|
||||
private String minPollingTime = "00:00:30";
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for the server e.g. the server's URL which must be configured.
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.server")
|
||||
public class HawkbitServerProperties {
|
||||
/**
|
||||
* Defines under which URI the update server can be reached. Used to
|
||||
* calculate download URLs for DMF transmitted update actions.
|
||||
*/
|
||||
private String url = "http://localhost:8080";
|
||||
|
||||
private final Build build = new Build();
|
||||
|
||||
public Build getBuild() {
|
||||
return build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build information of the hawkBit instance. Influenced by maven.
|
||||
*
|
||||
*/
|
||||
public static class Build {
|
||||
/**
|
||||
* Project artifact ID.
|
||||
*/
|
||||
private String artifact = "";
|
||||
|
||||
/**
|
||||
* Project name.
|
||||
*/
|
||||
private String name = "";
|
||||
|
||||
/**
|
||||
* Project description.
|
||||
*/
|
||||
private String description = "";
|
||||
|
||||
/**
|
||||
* Project version.
|
||||
*/
|
||||
private String version = "";
|
||||
|
||||
public String getArtifact() {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setArtifact(final String artifact) {
|
||||
this.artifact = artifact;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setDescription(final String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public void setVersion(final String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,12 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
|
||||
|
||||
@Override
|
||||
public Cache getCache(final String name) {
|
||||
final String currentTenant = tenantAware.getCurrentTenant().toUpperCase();
|
||||
String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
currentTenant = currentTenant.toUpperCase();
|
||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||
return null;
|
||||
}
|
||||
@@ -60,7 +65,12 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
|
||||
|
||||
@Override
|
||||
public Collection<String> getCacheNames() {
|
||||
final String currentTenant = tenantAware.getCurrentTenant().toUpperCase();
|
||||
String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
currentTenant = currentTenant.toUpperCase();
|
||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,12 @@ public enum ActionStatusFields implements FieldNameProvider {
|
||||
/**
|
||||
* The id field.
|
||||
*/
|
||||
ID("id");
|
||||
ID("id"),
|
||||
|
||||
/**
|
||||
* The reportedAt field.
|
||||
*/
|
||||
REPORTEDAT("createdAt");
|
||||
|
||||
private final String fieldName;
|
||||
|
||||
|
||||
@@ -29,32 +29,32 @@ public enum TenantConfigurationKey {
|
||||
* boolean value {@code true} {@code false}.
|
||||
*/
|
||||
AUTHENTICATION_MODE_HEADER_ENABLED("authentication.header.enabled",
|
||||
"hawkbit.server.controller.security.authentication.header.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||
"hawkbit.server.ddi.security.authentication.header.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||
TenantConfigurationBooleanValidator.class),
|
||||
/**
|
||||
*
|
||||
*/
|
||||
AUTHENTICATION_MODE_HEADER_AUTHORITY_NAME("authentication.header.authority",
|
||||
"hawkbit.server.controller.security.authentication.header.authority", String.class,
|
||||
Boolean.FALSE.toString(), TenantConfigurationStringValidator.class),
|
||||
"hawkbit.server.ddi.security.authentication.header.authority", String.class, Boolean.FALSE.toString(),
|
||||
TenantConfigurationStringValidator.class),
|
||||
/**
|
||||
* boolean value {@code true} {@code false}.
|
||||
*/
|
||||
AUTHENTICATION_MODE_TARGET_SECURITY_TOKEN_ENABLED("authentication.targettoken.enabled",
|
||||
"hawkbit.server.controller.security.authentication.targettoken.enabled", Boolean.class,
|
||||
Boolean.FALSE.toString(), TenantConfigurationBooleanValidator.class),
|
||||
"hawkbit.server.ddi.security.authentication.targettoken.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||
TenantConfigurationBooleanValidator.class),
|
||||
|
||||
/**
|
||||
* boolean value {@code true} {@code false}.
|
||||
*/
|
||||
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED("authentication.gatewaytoken.enabled",
|
||||
"hawkbit.server.controller.security.authentication.gatewaytoken.enabled", Boolean.class,
|
||||
Boolean.FALSE.toString(), TenantConfigurationBooleanValidator.class),
|
||||
"hawkbit.server.ddi.security.authentication.gatewaytoken.enabled", Boolean.class, Boolean.FALSE.toString(),
|
||||
TenantConfigurationBooleanValidator.class),
|
||||
/**
|
||||
* string value which holds the name of the security token key.
|
||||
*/
|
||||
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_NAME("authentication.gatewaytoken.name",
|
||||
"hawkbit.server.controller.security.authentication.gatewaytoken.name", String.class, null,
|
||||
"hawkbit.server.ddi.security.authentication.gatewaytoken.name", String.class, null,
|
||||
TenantConfigurationStringValidator.class),
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ public enum TenantConfigurationKey {
|
||||
* token.
|
||||
*/
|
||||
AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY("authentication.gatewaytoken.key",
|
||||
"hawkbit.server.controller.security.authentication.gatewaytoken.key", String.class, null,
|
||||
"hawkbit.server.ddi.security.authentication.gatewaytoken.key", String.class, null,
|
||||
TenantConfigurationStringValidator.class),
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,13 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Cluster Event Bus")
|
||||
@Stories("EventBus Subscriber Processor Test")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
// TODO: create description annotations
|
||||
public class EventBusSubscriberProcessorTest {
|
||||
|
||||
@Mock
|
||||
|
||||
@@ -60,6 +60,11 @@
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Test -->
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
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;
|
||||
|
||||
@@ -121,11 +122,22 @@ public class AmqpConfiguration {
|
||||
/**
|
||||
* Create amqp handler service bean.
|
||||
*
|
||||
* @return
|
||||
* @return handler service bean
|
||||
*/
|
||||
@Bean
|
||||
public AmqpMessageHandlerService amqpMessageHandlerService() {
|
||||
return new AmqpMessageHandlerService();
|
||||
return new AmqpMessageHandlerService(rabbitTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default amqp sender service bean.
|
||||
*
|
||||
* @return the default amqp sender service bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AmqpSenderService amqpSenderServiceBean() {
|
||||
return new DefaultAmqpSenderService(rabbitTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,9 +21,9 @@ import org.eclipse.hawkbit.security.CoapAnonymousPreAuthenticatedFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticateSecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedGatewaySecurityTokenFilter;
|
||||
import org.eclipse.hawkbit.security.ControllerPreAuthenticatedSecurityHeaderFilter;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.PreAuthTokenSourceTrustAuthenticationProvider;
|
||||
import org.eclipse.hawkbit.security.PreAuthenficationFilter;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
@@ -56,7 +56,7 @@ public class AmqpControllerAuthentfication {
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private SecurityProperties secruityProperties;
|
||||
private DdiSecurityProperties ddiSecruityProperties;
|
||||
|
||||
@Autowired
|
||||
private SystemSecurityContext systemSecurityContext;
|
||||
@@ -82,7 +82,7 @@ public class AmqpControllerAuthentfication {
|
||||
filterChain.add(gatewaySecurityTokenFilter);
|
||||
|
||||
final ControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new ControllerPreAuthenticatedSecurityHeaderFilter(
|
||||
secruityProperties.getRpCnHeader(), secruityProperties.getRpSslIssuerHashHeader(),
|
||||
ddiSecruityProperties.getRp().getCnHeader(), ddiSecruityProperties.getRp().getSslIssuerHashHeader(),
|
||||
tenantConfigurationManagement, tenantAware, systemSecurityContext);
|
||||
filterChain.add(securityHeaderFilter);
|
||||
|
||||
@@ -131,18 +131,15 @@ public class AmqpControllerAuthentfication {
|
||||
|
||||
LOGGER.debug("preAuthenticatedPrincipal = {} trying to authenticate", principal);
|
||||
|
||||
final PreAuthenticatedAuthenticationToken authRequest = new PreAuthenticatedAuthenticationToken(principal,
|
||||
credentials);
|
||||
|
||||
return authRequest;
|
||||
return new PreAuthenticatedAuthenticationToken(principal, credentials);
|
||||
}
|
||||
|
||||
public void setControllerManagement(final ControllerManagement controllerManagement) {
|
||||
this.controllerManagement = controllerManagement;
|
||||
}
|
||||
|
||||
public void setSecruityProperties(final SecurityProperties secruityProperties) {
|
||||
this.secruityProperties = secruityProperties;
|
||||
public void setSecruityProperties(final DdiSecurityProperties secruityProperties) {
|
||||
this.ddiSecruityProperties = secruityProperties;
|
||||
}
|
||||
|
||||
public void setTenantConfigurationManagement(final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||
|
||||
@@ -25,35 +25,43 @@ import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.eventbus.event.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.util.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* {@link AmqpMessageDispatcherService} handles all outgoing AMQP messages.
|
||||
*
|
||||
*
|
||||
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
|
||||
* delegate the messages to a {@link AmqpSenderService}.
|
||||
*
|
||||
* Additionally the dispatcher listener/subscribe for some target events e.g.
|
||||
* assignment.
|
||||
*
|
||||
*/
|
||||
@EventSubscriber
|
||||
public class AmqpMessageDispatcherService {
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
|
||||
@Autowired
|
||||
private ArtifactUrlHandler artifactUrlHandler;
|
||||
|
||||
@Autowired
|
||||
private AmqpSenderService amqpSenderService;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param messageConverter
|
||||
* message converter
|
||||
*/
|
||||
@Autowired
|
||||
public AmqpMessageDispatcherService(final RabbitTemplate rabbitTemplate) {
|
||||
super(rabbitTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a message to a RabbitMQ Exchange after the Distribution
|
||||
* set has been assign to a Target.
|
||||
@@ -79,11 +87,10 @@ public class AmqpMessageDispatcherService {
|
||||
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
|
||||
}
|
||||
|
||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(
|
||||
downloadAndUpdateRequest,
|
||||
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
|
||||
createConnectorMessageProperties(targetAssignDistributionSetEvent.getTenant(), controllerId,
|
||||
EventTopic.DOWNLOAD_AND_INSTALL));
|
||||
sendMessage(targetAdress.getHost(), message);
|
||||
amqpSenderService.sendMessage(message, targetAdress);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,29 +105,13 @@ public class AmqpMessageDispatcherService {
|
||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent) {
|
||||
final String controllerId = cancelTargetAssignmentDistributionSetEvent.getControllerId();
|
||||
final Long actionId = cancelTargetAssignmentDistributionSetEvent.getActionId();
|
||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(
|
||||
actionId,
|
||||
createConnectorMessageProperties(cancelTargetAssignmentDistributionSetEvent.getTenant(), controllerId,
|
||||
EventTopic.CANCEL_DOWNLOAD));
|
||||
final Message message = getMessageConverter().toMessage(actionId, createConnectorMessageProperties(
|
||||
cancelTargetAssignmentDistributionSetEvent.getTenant(), controllerId, EventTopic.CANCEL_DOWNLOAD));
|
||||
|
||||
sendMessage(cancelTargetAssignmentDistributionSetEvent.getTargetAdress().getHost(), message);
|
||||
amqpSenderService.sendMessage(message, cancelTargetAssignmentDistributionSetEvent.getTargetAdress());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Send message to exchange.
|
||||
*
|
||||
* @param exchange
|
||||
* the exchange
|
||||
* @param message
|
||||
* the message
|
||||
*/
|
||||
public void sendMessage(final String exchange, final Message message) {
|
||||
message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
|
||||
rabbitTemplate.setExchange(exchange);
|
||||
rabbitTemplate.send(message);
|
||||
}
|
||||
|
||||
private MessageProperties createConnectorMessageProperties(final String tenant, final String controllerId,
|
||||
final EventTopic topic) {
|
||||
final MessageProperties messageProperties = createMessageProperties();
|
||||
@@ -155,9 +146,8 @@ public class AmqpMessageDispatcherService {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<Artifact> convertedArtifacts = localArtifacts.stream()
|
||||
.map(localArtifact -> convertArtifact(targetId, localArtifact)).collect(Collectors.toList());
|
||||
return convertedArtifacts;
|
||||
return localArtifacts.stream().map(localArtifact -> convertArtifact(targetId, localArtifact))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Artifact convertArtifact(final String targetId, final LocalArtifact localArtifact) {
|
||||
@@ -175,15 +165,11 @@ public class AmqpMessageDispatcherService {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
public void setTenantAware(final TenantAware tenantAware) {
|
||||
this.tenantAware = tenantAware;
|
||||
}
|
||||
|
||||
public void setRabbitTemplate(final RabbitTemplate rabbitTemplate) {
|
||||
this.rabbitTemplate = rabbitTemplate;
|
||||
}
|
||||
|
||||
public void setArtifactUrlHandler(final ArtifactUrlHandler artifactUrlHandler) {
|
||||
this.artifactUrlHandler = artifactUrlHandler;
|
||||
}
|
||||
|
||||
public void setAmqpSenderService(final AmqpSenderService amqpSenderService) {
|
||||
this.amqpSenderService = amqpSenderService;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -50,8 +49,6 @@ import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.cache.Cache;
|
||||
@@ -72,19 +69,14 @@ import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
*
|
||||
* {@link AmqpMessageHandlerService} handles all incoming AMQP messages.
|
||||
*
|
||||
*
|
||||
*
|
||||
* {@link AmqpMessageHandlerService} handles all incoming AMQP messages for the
|
||||
* queue which is configure for the property hawkbit.dmf.rabbitmq.receiverQueue.
|
||||
*
|
||||
*/
|
||||
public class AmqpMessageHandlerService {
|
||||
public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AmqpMessageHandlerService.class);
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Autowired
|
||||
private ControllerManagement controllerManagement;
|
||||
|
||||
@@ -105,7 +97,23 @@ public class AmqpMessageHandlerService {
|
||||
private HostnameResolver hostnameResolver;
|
||||
|
||||
/**
|
||||
* /** Method to handle all incoming amqp messages.
|
||||
* Constructor.
|
||||
*
|
||||
* @param defaultTemplate
|
||||
* the configured amqp template.
|
||||
*/
|
||||
public AmqpMessageHandlerService(final RabbitTemplate defaultTemplate) {
|
||||
super(defaultTemplate);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = "${hawkbit.dmf.rabbitmq.receiverQueue}", containerFactory = "listenerContainerFactory")
|
||||
private Message onMessage(final Message message, @Header(MessageHeaderKey.TYPE) final String type,
|
||||
@Header(MessageHeaderKey.TENANT) final String tenant) {
|
||||
return onMessage(message, type, tenant, getRabbitTemplate().getConnectionFactory().getVirtualHost());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to handle all incoming amqp messages.
|
||||
*
|
||||
* @param message
|
||||
* incoming message
|
||||
@@ -115,11 +123,11 @@ public class AmqpMessageHandlerService {
|
||||
* the contentType of the message
|
||||
* @param tenant
|
||||
* the contentType of the message
|
||||
* @param virtualHost
|
||||
* the virtual host
|
||||
* @return a message if <null> no message is send back to sender
|
||||
*/
|
||||
@RabbitListener(queues = "${hawkbit.dmf.rabbitmq.receiverQueue}", containerFactory = "listenerContainerFactory")
|
||||
public Message onMessage(final Message message, @Header(MessageHeaderKey.TYPE) final String type,
|
||||
@Header(MessageHeaderKey.TENANT) final String tenant) {
|
||||
public Message onMessage(final Message message, final String type, final String tenant, final String virtualHost) {
|
||||
checkContentTypeJson(message);
|
||||
final SecurityContext oldContext = SecurityContextHolder.getContext();
|
||||
try {
|
||||
@@ -127,7 +135,7 @@ public class AmqpMessageHandlerService {
|
||||
switch (messageType) {
|
||||
case THING_CREATED:
|
||||
setTenantSecurityContext(tenant);
|
||||
registerTarget(message);
|
||||
registerTarget(message, virtualHost);
|
||||
break;
|
||||
case EVENT:
|
||||
setTenantSecurityContext(tenant);
|
||||
@@ -153,8 +161,8 @@ public class AmqpMessageHandlerService {
|
||||
final String sha1 = secruityToken.getSha1();
|
||||
try {
|
||||
SecurityContextHolder.getContext().setAuthentication(authenticationManager.doAuthenticate(secruityToken));
|
||||
final LocalArtifact localArtifact = artifactManagement.findFirstLocalArtifactsBySHA1(secruityToken
|
||||
.getSha1());
|
||||
final LocalArtifact localArtifact = artifactManagement
|
||||
.findFirstLocalArtifactsBySHA1(secruityToken.getSha1());
|
||||
if (localArtifact == null) {
|
||||
throw new EntityNotFoundException();
|
||||
}
|
||||
@@ -177,9 +185,9 @@ public class AmqpMessageHandlerService {
|
||||
final String downloadId = UUID.randomUUID().toString();
|
||||
final DownloadArtifactCache downloadCache = new DownloadArtifactCache(DownloadType.BY_SHA1, sha1);
|
||||
cache.put(downloadId, downloadCache);
|
||||
authentificationResponse.setDownloadUrl(UriComponentsBuilder
|
||||
.fromUri(hostnameResolver.resolveHostname().toURI()).path("/api/v1/downloadserver/downloadId/")
|
||||
.path(downloadId).build().toUriString());
|
||||
authentificationResponse
|
||||
.setDownloadUrl(UriComponentsBuilder.fromUri(hostnameResolver.resolveHostname().toURI())
|
||||
.path("/api/v1/downloadserver/downloadId/").path(downloadId).build().toUriString());
|
||||
authentificationResponse.setResponseCode(HttpStatus.OK.value());
|
||||
} catch (final BadCredentialsException | AuthenticationServiceException | CredentialsExpiredException e) {
|
||||
LOG.error("Login failed", e);
|
||||
@@ -196,7 +204,7 @@ public class AmqpMessageHandlerService {
|
||||
authentificationResponse.setMessage(errorMessage);
|
||||
}
|
||||
|
||||
return rabbitTemplate.getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
||||
return getMessageConverter().toMessage(authentificationResponse, messageProperties);
|
||||
}
|
||||
|
||||
private static Artifact convertDbArtifact(final DbArtifact dbArtifact) {
|
||||
@@ -207,11 +215,6 @@ public class AmqpMessageHandlerService {
|
||||
return artifact;
|
||||
}
|
||||
|
||||
protected void logAndThrowMessageError(final Message message, final String error) {
|
||||
LOG.error("Error \"{}\" reported by message {}", error, message.getMessageProperties().getMessageId());
|
||||
throw new IllegalArgumentException(error);
|
||||
}
|
||||
|
||||
private static void setSecurityContext(final Authentication authentication) {
|
||||
final SecurityContextImpl securityContextImpl = new SecurityContextImpl();
|
||||
securityContextImpl.setAuthentication(authentication);
|
||||
@@ -219,22 +222,13 @@ public class AmqpMessageHandlerService {
|
||||
}
|
||||
|
||||
private static void setTenantSecurityContext(final String tenantId) {
|
||||
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(UUID.randomUUID()
|
||||
.toString(), "AMQP-Controller", Collections.singletonList(new SimpleGrantedAuthority(
|
||||
SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
||||
final AnonymousAuthenticationToken authenticationToken = new AnonymousAuthenticationToken(
|
||||
UUID.randomUUID().toString(), "AMQP-Controller",
|
||||
Collections.singletonList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS)));
|
||||
authenticationToken.setDetails(new TenantAwareAuthenticationDetails(tenantId, true));
|
||||
setSecurityContext(authenticationToken);
|
||||
}
|
||||
|
||||
private String getStringHeaderKey(final Message message, final String key, final String errorMessageIfNull) {
|
||||
final Map<String, Object> header = message.getMessageProperties().getHeaders();
|
||||
final Object value = header.get(key);
|
||||
if (value == null) {
|
||||
logAndThrowMessageError(message, errorMessageIfNull);
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create a new target or to find the target if it already exists.
|
||||
*
|
||||
@@ -243,14 +237,15 @@ public class AmqpMessageHandlerService {
|
||||
* @param ip
|
||||
* the ip of the target/thing
|
||||
*/
|
||||
private void registerTarget(final Message message) {
|
||||
private void registerTarget(final Message message, final String virtualHost) {
|
||||
final String thingId = getStringHeaderKey(message, MessageHeaderKey.THING_ID, "ThingId is null");
|
||||
final String replyTo = message.getMessageProperties().getReplyTo();
|
||||
|
||||
if (StringUtils.isEmpty(replyTo)) {
|
||||
logAndThrowMessageError(message, "No ReplyTo was set for the createThing Event.");
|
||||
}
|
||||
final URI amqpUri = IpUtil.createAmqpUri(replyTo);
|
||||
|
||||
final URI amqpUri = IpUtil.createAmqpUri(virtualHost, replyTo);
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(thingId, amqpUri);
|
||||
LOG.debug("Target {} reported online state.", thingId);
|
||||
|
||||
@@ -267,8 +262,8 @@ public class AmqpMessageHandlerService {
|
||||
final DistributionSet distributionSet = action.getDistributionSet();
|
||||
final List<SoftwareModule> softwareModuleList = controllerManagement
|
||||
.findSoftwareModulesByDistributionSet(distributionSet);
|
||||
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(), target
|
||||
.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress()));
|
||||
eventBus.post(new TargetAssignDistributionSetEvent(target.getOptLockRevision(), target.getTenant(),
|
||||
target.getControllerId(), action.getId(), softwareModuleList, target.getTargetInfo().getAddress()));
|
||||
|
||||
}
|
||||
|
||||
@@ -281,13 +276,11 @@ public class AmqpMessageHandlerService {
|
||||
* the topic of the event.
|
||||
*/
|
||||
private void handleIncomingEvent(final Message message, final EventTopic topic) {
|
||||
switch (topic) {
|
||||
case UPDATE_ACTION_STATUS:
|
||||
if (EventTopic.UPDATE_ACTION_STATUS.equals(topic)) {
|
||||
updateActionStatus(message);
|
||||
return;
|
||||
default:
|
||||
logAndThrowMessageError(message, "Got event without appropriate topic.");
|
||||
}
|
||||
logAndThrowMessageError(message, "Got event without appropriate topic.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,28 +329,24 @@ public class AmqpMessageHandlerService {
|
||||
logAndThrowMessageError(message, "Status for action does not exisit.");
|
||||
}
|
||||
|
||||
Action addUpdateActionStatus;
|
||||
|
||||
if (!actionStatus.getStatus().equals(Status.CANCELED)) {
|
||||
addUpdateActionStatus = controllerManagement.addUpdateActionStatus(actionStatus, action);
|
||||
} else {
|
||||
addUpdateActionStatus = controllerManagement.addCancelActionStatus(actionStatus, action);
|
||||
}
|
||||
final Action addUpdateActionStatus = getUpdateActionStatus(action, actionStatus);
|
||||
|
||||
if (!addUpdateActionStatus.isActive()) {
|
||||
lookIfUpdateAvailable(action.getTarget());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message
|
||||
* @param actionUpdateStatus
|
||||
* @return
|
||||
*/
|
||||
private Action getUpdateActionStatus(final Action action, final ActionStatus actionStatus) {
|
||||
if (actionStatus.getStatus().equals(Status.CANCELED)) {
|
||||
return controllerManagement.addCancelActionStatus(actionStatus, action);
|
||||
}
|
||||
return controllerManagement.addUpdateActionStatus(actionStatus, action);
|
||||
}
|
||||
|
||||
private Action checkActionExist(final Message message, final ActionUpdateStatus actionUpdateStatus) {
|
||||
final Long actionId = actionUpdateStatus.getActionId();
|
||||
LOG.debug("Target notifies intermediate about action {} with status {}.", actionId, actionUpdateStatus
|
||||
.getActionStatus().name());
|
||||
LOG.debug("Target notifies intermediate about action {} with status {}.", actionId,
|
||||
actionUpdateStatus.getActionStatus().name());
|
||||
|
||||
if (actionId == null) {
|
||||
logAndThrowMessageError(message, "Invalid message no action id");
|
||||
@@ -366,8 +355,8 @@ public class AmqpMessageHandlerService {
|
||||
final Action action = controllerManagement.findActionWithDetails(actionId);
|
||||
|
||||
if (action == null) {
|
||||
logAndThrowMessageError(message, "Got intermediate notification about action " + actionId
|
||||
+ " but action does not exist");
|
||||
logAndThrowMessageError(message,
|
||||
"Got intermediate notification about action " + actionId + " but action does not exist");
|
||||
}
|
||||
return action;
|
||||
}
|
||||
@@ -381,38 +370,12 @@ public class AmqpMessageHandlerService {
|
||||
// back to running action status
|
||||
|
||||
} else {
|
||||
logAndThrowMessageError(message, "Cancel Recjected message is not allowed, if action is on state: "
|
||||
+ action.getStatus());
|
||||
logAndThrowMessageError(message,
|
||||
"Cancel recjected message is not allowed, if action is on state: " + action.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is needed to convert a incoming message to is originally object type.
|
||||
*
|
||||
* @param message
|
||||
* the message to convert.
|
||||
* @param clazz
|
||||
* the class of the originally object.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T convertMessage(final Message message, final Class<T> clazz) {
|
||||
message.getMessageProperties().getHeaders()
|
||||
.put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME, clazz.getTypeName());
|
||||
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is needed to verify if an incoming message has the content type json.
|
||||
*
|
||||
* @param message
|
||||
* the to verify
|
||||
* @param contentType
|
||||
* the content type
|
||||
* @return true if the content type has json, false it not.
|
||||
*/
|
||||
|
||||
private static void checkContentTypeJson(final Message message) {
|
||||
private void checkContentTypeJson(final Message message) {
|
||||
final MessageProperties messageProperties = message.getMessageProperties();
|
||||
if (messageProperties.getContentType() != null && messageProperties.getContentType().contains("json")) {
|
||||
return;
|
||||
@@ -428,14 +391,6 @@ public class AmqpMessageHandlerService {
|
||||
this.hostnameResolver = hostnameResolver;
|
||||
}
|
||||
|
||||
void setRabbitTemplate(final RabbitTemplate rabbitTemplate) {
|
||||
this.rabbitTemplate = rabbitTemplate;
|
||||
}
|
||||
|
||||
MessageConverter getMessageConverter() {
|
||||
return rabbitTemplate.getMessageConverter();
|
||||
}
|
||||
|
||||
void setAuthenticationManager(final AmqpControllerAuthentfication authenticationManager) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
}
|
||||
|
||||
@@ -15,16 +15,27 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
* Bean which holds the necessary properties for configuring the AMQP
|
||||
* connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.dmf.rabbitmq")
|
||||
public class AmqpProperties {
|
||||
|
||||
/**
|
||||
* DMF API dead letter queue.
|
||||
*/
|
||||
private String deadLetterQueue = "dmf_connector_deadletter";
|
||||
|
||||
/**
|
||||
* DMF API dead letter exchange.
|
||||
*/
|
||||
private String deadLetterExchange = "dmf.connector.deadletter";
|
||||
|
||||
/**
|
||||
* DMF API receiving queue.
|
||||
*/
|
||||
private String receiverQueue = "dmf_receiver";
|
||||
|
||||
/**
|
||||
* Missing queue fatal.
|
||||
*/
|
||||
private boolean missingQueuesFatal = false;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.amqp;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.amqp.core.Message;
|
||||
|
||||
/**
|
||||
* Interface to send a amqp message.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface AmqpSenderService {
|
||||
|
||||
/**
|
||||
* Send the given message to the given uri. The uri contains the (virtual)
|
||||
* host and exchange e.g amqp://host/exchange.
|
||||
*
|
||||
* @param message
|
||||
* the amqp message
|
||||
* @param uri
|
||||
* the reply to uri
|
||||
*/
|
||||
void sendMessage(Message message, URI uri);
|
||||
|
||||
/**
|
||||
* Extract the exchange from the uri. Default implementation removes the
|
||||
* first /.
|
||||
*
|
||||
* @param amqpUri
|
||||
* the amqp uri
|
||||
* @return the exchange.
|
||||
*/
|
||||
default String extractExchange(final URI amqpUri) {
|
||||
return amqpUri.getPath().substring(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* 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.amqp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
|
||||
/**
|
||||
* A base class which provide basis amqp staff.
|
||||
*/
|
||||
public class BaseAmqpService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(BaseAmqpService.class);
|
||||
private final RabbitTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
* the rabbit template.
|
||||
*/
|
||||
public BaseAmqpService(final RabbitTemplate rabbitTemplate) {
|
||||
this.rabbitTemplate = rabbitTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean message properties before sending a message.
|
||||
*
|
||||
* @param message
|
||||
* the message to cleaned up
|
||||
*/
|
||||
protected void cleanMessageHeaderProperties(final Message message) {
|
||||
message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is needed to convert a incoming message to is originally object type.
|
||||
*
|
||||
* @param message
|
||||
* the message to convert.
|
||||
* @param clazz
|
||||
* the class of the originally object.
|
||||
* @return the converted object
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convertMessage(final Message message, final Class<T> clazz) {
|
||||
if (message == null || message.getBody() == null) {
|
||||
return null;
|
||||
}
|
||||
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
|
||||
clazz.getName());
|
||||
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is needed to convert a incoming message to is originally list object
|
||||
* type.
|
||||
*
|
||||
* @param message
|
||||
* the message to convert.
|
||||
* @param clazz
|
||||
* the class of the list content.
|
||||
* @return the list of converted objects
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<T> convertMessageList(final Message message, final Class<T> clazz) {
|
||||
if (message == null || message.getBody() == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME,
|
||||
ArrayList.class.getName());
|
||||
message.getMessageProperties().getHeaders().put(AbstractJavaTypeMapper.DEFAULT_CONTENT_CLASSID_FIELD_NAME,
|
||||
clazz.getName());
|
||||
return (List<T>) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||
}
|
||||
|
||||
public MessageConverter getMessageConverter() {
|
||||
return rabbitTemplate.getMessageConverter();
|
||||
}
|
||||
|
||||
protected final String getStringHeaderKey(final Message message, final String key,
|
||||
final String errorMessageIfNull) {
|
||||
final Map<String, Object> header = message.getMessageProperties().getHeaders();
|
||||
final Object value = header.get(key);
|
||||
if (value == null) {
|
||||
logAndThrowMessageError(message, errorMessageIfNull);
|
||||
return null;
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
protected final void logAndThrowMessageError(final Message message, final String error) {
|
||||
LOGGER.error("Error \"{}\" reported by message {}", error, message.getMessageProperties().getMessageId());
|
||||
throw new IllegalArgumentException(error);
|
||||
}
|
||||
|
||||
protected RabbitTemplate getRabbitTemplate() {
|
||||
return rabbitTemplate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* 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.amqp;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
|
||||
/**
|
||||
* A default implementation for the sender service. The service sends all amqp
|
||||
* message to the configured spring rabbitmq connections. The exchange is
|
||||
* extracted from the uri.
|
||||
*/
|
||||
public class DefaultAmqpSenderService implements AmqpSenderService {
|
||||
|
||||
private final RabbitTemplate internalAmqpTemplate;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param internalAmqpTemplate
|
||||
* the amqp template
|
||||
*/
|
||||
public DefaultAmqpSenderService(final RabbitTemplate internalAmqpTemplate) {
|
||||
this.internalAmqpTemplate = internalAmqpTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(final Message message, final URI uri) {
|
||||
internalAmqpTemplate.send(extractExchange(uri), null, message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.eclipse.hawkbit.amqp.AmqpSenderService;
|
||||
import org.eclipse.hawkbit.amqp.DefaultAmqpSenderService;
|
||||
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.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class AmqpTestConfiguration {
|
||||
|
||||
/**
|
||||
* Method to set the Jackson2JsonMessageConverter.
|
||||
*
|
||||
* @return the Jackson2JsonMessageConverter
|
||||
*/
|
||||
@Bean
|
||||
public MessageConverter jsonMessageConverter() {
|
||||
return new Jackson2JsonMessageConverter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create default amqp sender service bean.
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
*
|
||||
* @return the default amqp sender service bean
|
||||
*/
|
||||
@Bean
|
||||
@Autowired
|
||||
public AmqpSenderService amqpSenderServiceBean(final RabbitTemplate rabbitTemplate) {
|
||||
return new DefaultAmqpSenderService(rabbitTemplate);
|
||||
}
|
||||
}
|
||||
@@ -24,9 +24,9 @@ import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties.Rp;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -47,11 +47,11 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
*
|
||||
* Test Amqp controller authentfication.
|
||||
* Test Amqp controller authentication.
|
||||
*/
|
||||
@Features("AMQP Authenfication Test")
|
||||
@Stories("Tests the authenfication")
|
||||
public class AmqpControllerAuthentficationTest {
|
||||
@Features("Component Tests - Device Management Federation API")
|
||||
@Stories("AmqpController Authentication Test")
|
||||
public class AmqpControllerAuthenticationTest {
|
||||
|
||||
private static final String TENANT = "DEFAULT";
|
||||
private static String CONTROLLLER_ID = "123";
|
||||
@@ -68,17 +68,20 @@ public class AmqpControllerAuthentficationTest {
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService();
|
||||
messageConverter = new Jackson2JsonMessageConverter();
|
||||
final RabbitTemplate rabbitTemplate = new RabbitTemplate();
|
||||
rabbitTemplate.setMessageConverter(messageConverter);
|
||||
amqpMessageHandlerService.setRabbitTemplate(rabbitTemplate);
|
||||
final RabbitTemplate rabbitTemplate = mock(RabbitTemplate.class);
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate);
|
||||
|
||||
authenticationManager = new AmqpControllerAuthentfication();
|
||||
authenticationManager.setControllerManagement(mock(ControllerManagement.class));
|
||||
final SecurityProperties secruityProperties = mock(SecurityProperties.class);
|
||||
when(secruityProperties.getRpSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
||||
|
||||
final DdiSecurityProperties secruityProperties = mock(DdiSecurityProperties.class);
|
||||
final Rp rp = mock(Rp.class);
|
||||
when(secruityProperties.getRp()).thenReturn(rp);
|
||||
when(rp.getSslIssuerHashHeader()).thenReturn("X-Ssl-Issuer-Hash-%d");
|
||||
authenticationManager.setSecruityProperties(secruityProperties);
|
||||
|
||||
tenantConfigurationManagement = mock(TenantConfigurationManagement.class);
|
||||
authenticationManager.setTenantConfigurationManagement(tenantConfigurationManagement);
|
||||
|
||||
@@ -88,13 +91,9 @@ public class AmqpControllerAuthentficationTest {
|
||||
final ControllerManagement controllerManagement = mock(ControllerManagement.class);
|
||||
when(controllerManagement.getSecurityTokenByControllerId(anyString())).thenReturn(CONTROLLLER_ID);
|
||||
authenticationManager.setControllerManagement(controllerManagement);
|
||||
|
||||
amqpMessageHandlerService.setArtifactManagement(mock(ArtifactManagement.class));
|
||||
|
||||
final SecurityContextTenantAware tenantAware = new SecurityContextTenantAware();
|
||||
authenticationManager.setTenantAware(tenantAware);
|
||||
final SystemSecurityContext systemSecurityContext = new SystemSecurityContext(tenantAware);
|
||||
authenticationManager.setSystemSecurityContext(systemSecurityContext);
|
||||
authenticationManager.setTenantAware(new SecurityContextTenantAware());
|
||||
authenticationManager.postConstruct();
|
||||
amqpMessageHandlerService.setAuthenticationManager(authenticationManager);
|
||||
}
|
||||
@@ -152,7 +151,7 @@ public class AmqpControllerAuthentficationTest {
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT);
|
||||
TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -174,7 +173,7 @@ public class AmqpControllerAuthentficationTest {
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT);
|
||||
TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -196,7 +195,7 @@ public class AmqpControllerAuthentficationTest {
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT);
|
||||
TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -19,6 +19,7 @@ import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -45,7 +46,6 @@ 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.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
@@ -53,43 +53,44 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@ActiveProfiles({ "test" })
|
||||
@Features("AMQP Dispatcher Test")
|
||||
@Stories("Tests send messages")
|
||||
@Features("Component Tests - Device Management Federation API")
|
||||
@Stories("AmqpMessage Dispatcher Service Test")
|
||||
public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
private AmqpMessageDispatcherService amqpMessageDispatcherService;
|
||||
|
||||
private MessageConverter messageConverter;
|
||||
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
private DefaultAmqpSenderService senderService;
|
||||
|
||||
private static final String CONTROLLER_ID = "1";
|
||||
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService();
|
||||
this.rabbitTemplate = Mockito.mock(RabbitTemplate.class);
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter());
|
||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate);
|
||||
amqpMessageDispatcherService = spy(amqpMessageDispatcherService);
|
||||
messageConverter = new Jackson2JsonMessageConverter();
|
||||
|
||||
senderService = Mockito.mock(DefaultAmqpSenderService.class);
|
||||
amqpMessageDispatcherService.setAmqpSenderService(senderService);
|
||||
|
||||
final ArtifactUrlHandler artifactUrlHandlerMock = Mockito.mock(ArtifactUrlHandler.class);
|
||||
when(artifactUrlHandlerMock.getUrl(anyString(), any(), anyObject())).thenReturn("http://mockurl");
|
||||
|
||||
this.rabbitTemplate = Mockito.mock(RabbitTemplate.class);
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
|
||||
amqpMessageDispatcherService.setRabbitTemplate(rabbitTemplate);
|
||||
amqpMessageDispatcherService.setTenantAware(tenantAware);
|
||||
amqpMessageDispatcherService.setArtifactUrlHandler(artifactUrlHandlerMock);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that download and install event with no software modul works")
|
||||
public void testSendDownloadRequesWithEmptySoftwareModules() {
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, new ArrayList<SoftwareModule>(), IpUtil.createAmqpUri("mytest"));
|
||||
1L, "default", CONTROLLER_ID, 1l, new ArrayList<SoftwareModule>(),
|
||||
IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost());
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
assertTrue("No softwaremmodule should be contained in the request",
|
||||
downloadAndUpdateRequest.getSoftwareModules().isEmpty());
|
||||
@@ -101,9 +102,9 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||
distributionSetManagement);
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("mytest"));
|
||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost());
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
assertEquals("Expecting a size of 3 software modules in the reuqest", 3,
|
||||
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||
@@ -140,9 +141,9 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList);
|
||||
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("mytest"));
|
||||
1L, "default", CONTROLLER_ID, 1l, dsA.getModules(), IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress().getHost());
|
||||
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3,
|
||||
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||
@@ -159,11 +160,10 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
@Description("Verfies that send cancel event works")
|
||||
public void testSendCancelRequest() {
|
||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
||||
1L, "default", CONTROLLER_ID, 1l, IpUtil.createAmqpUri("mytest"));
|
||||
1L, "default", CONTROLLER_ID, 1l, IpUtil.createAmqpUri("vHost", "mytest"));
|
||||
amqpMessageDispatcherService
|
||||
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(
|
||||
cancelTargetAssignmentDistributionSetEvent.getTargetAdress().getHost());
|
||||
final Message sendMessage = createArgumentCapture(cancelTargetAssignmentDistributionSetEvent.getTargetAdress());
|
||||
assertCancelMessage(sendMessage);
|
||||
|
||||
}
|
||||
@@ -203,9 +203,9 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
|
||||
MessageProperties.CONTENT_TYPE_JSON, sendMessage.getMessageProperties().getContentType());
|
||||
}
|
||||
|
||||
protected Message createArgumentCapture(final String exchange) {
|
||||
protected Message createArgumentCapture(final URI uri) {
|
||||
final ArgumentCaptor<Message> argumentCaptor = ArgumentCaptor.forClass(Message.class);
|
||||
Mockito.verify(amqpMessageDispatcherService).sendMessage(eq(exchange), argumentCaptor.capture());
|
||||
Mockito.verify(senderService).sendMessage(argumentCaptor.capture(), eq(uri));
|
||||
return argumentCaptor.getValue();
|
||||
}
|
||||
|
||||
|
||||
@@ -68,8 +68,8 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@Features("AMQP Controller Test")
|
||||
@Stories("Tests the servcies for message handler and dispatcher")
|
||||
@Features("Component Tests - Device Management Federation API")
|
||||
@Stories("AmqpMessage Handler Service Test")
|
||||
public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
private static final String TENANT = "DEFAULT";
|
||||
@@ -99,14 +99,15 @@ public class AmqpMessageHandlerServiceTest {
|
||||
@Mock
|
||||
private EventBus eventBus;
|
||||
|
||||
@Mock
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService();
|
||||
amqpMessageHandlerService.setControllerManagement(controllerManagementMock);
|
||||
messageConverter = new Jackson2JsonMessageConverter();
|
||||
final RabbitTemplate rabbitTemplate = new RabbitTemplate();
|
||||
rabbitTemplate.setMessageConverter(messageConverter);
|
||||
amqpMessageHandlerService.setRabbitTemplate(rabbitTemplate);
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate);
|
||||
amqpMessageHandlerService.setControllerManagement(controllerManagementMock);
|
||||
amqpMessageHandlerService.setAuthenticationManager(authenticationManagerMock);
|
||||
amqpMessageHandlerService.setArtifactManagement(artifactManagementMock);
|
||||
amqpMessageHandlerService.setCache(cacheMock);
|
||||
@@ -115,14 +116,17 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@Test
|
||||
@Description("Tests not allowed content-type in message")
|
||||
public void testWrongContentType() {
|
||||
final MessageProperties messageProperties = new MessageProperties();
|
||||
messageProperties.setContentType("xml");
|
||||
final Message message = new Message(new byte[0], messageProperties);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
||||
fail();
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to worng content type");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,10 +142,11 @@ public class AmqpMessageHandlerServiceTest {
|
||||
when(controllerManagementMock.findOrRegisterTargetIfItDoesNotexist(targetIdCaptor.capture(),
|
||||
uriCaptor.capture())).thenReturn(null);
|
||||
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
|
||||
assertThat(targetIdCaptor.getValue()).as("Extraxted Thing should be the same").isEqualTo(knownThingId);
|
||||
assertThat(uriCaptor.getValue().toString()).as("Extraxted Uri should be the same").isEqualTo("amqp://MyTest");
|
||||
// verify
|
||||
assertThat(targetIdCaptor.getValue()).as("Thing id is wrong").isEqualTo(knownThingId);
|
||||
assertThat(uriCaptor.getValue().toString()).as("Uri is not right").isEqualTo("amqp://vHost/MyTest");
|
||||
|
||||
}
|
||||
|
||||
@@ -153,7 +158,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = messageConverter.toMessage("", messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no replyTo header was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
// test ok - exception was excepted
|
||||
@@ -167,7 +172,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.THING_CREATED);
|
||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.THING_CREATED.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no thingID was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
// test ok - exception was excepted
|
||||
@@ -183,7 +188,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final Message message = messageConverter.toMessage(new byte[0], messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, type, TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, type, TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to unknown message type");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
// test ok - exception was excepted
|
||||
@@ -196,21 +201,21 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
|
||||
final Message message = new Message(new byte[0], messageProperties);
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
||||
fail();
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to unknown message type");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
}
|
||||
|
||||
try {
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, "wrongTopic");
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
||||
fail();
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted due to unknown topic");
|
||||
} catch (final IllegalArgumentException e) {
|
||||
}
|
||||
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.CANCEL_DOWNLOAD.name());
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted because there was no event topic");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
// test ok - exception was excepted
|
||||
@@ -229,7 +234,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no action id was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
// test ok - exception was excepted
|
||||
@@ -246,7 +251,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
messageProperties);
|
||||
|
||||
try {
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
fail("IllegalArgumentException was excepeted since no action id was set");
|
||||
} catch (final IllegalArgumentException exception) {
|
||||
// test ok - exception was excepted
|
||||
@@ -264,7 +269,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT);
|
||||
TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -288,7 +293,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT);
|
||||
TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -320,7 +325,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
|
||||
// test
|
||||
final Message onMessage = amqpMessageHandlerService.onMessage(message, MessageType.AUTHENTIFICATION.name(),
|
||||
TENANT);
|
||||
TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final DownloadResponse downloadResponse = (DownloadResponse) messageConverter.fromMessage(onMessage);
|
||||
@@ -328,7 +333,8 @@ public class AmqpMessageHandlerServiceTest {
|
||||
assertThat(downloadResponse.getResponseCode()).as("Message body response code is wrong")
|
||||
.isEqualTo(HttpStatus.OK.value());
|
||||
assertThat(downloadResponse.getArtifact().getSize()).as("Wrong artifact size in message body").isEqualTo(1L);
|
||||
assertThat(downloadResponse.getDownloadUrl()).startsWith("http://localhost/api/v1/downloadserver/downloadId/");
|
||||
assertThat(downloadResponse.getDownloadUrl()).as("download url is wrong")
|
||||
.startsWith("http://localhost/api/v1/downloadserver/downloadId/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -355,7 +361,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
messageProperties);
|
||||
|
||||
// test
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT);
|
||||
amqpMessageHandlerService.onMessage(message, MessageType.EVENT.name(), TENANT, "vHost");
|
||||
|
||||
// verify
|
||||
final ArgumentCaptor<TargetAssignDistributionSetEvent> captorTargetAssignDistributionSetEvent = ArgumentCaptor
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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.amqp;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.dmf.json.model.ActionUpdateStatus;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@Features("Component Tests - Device Management Federation API")
|
||||
@Stories("Base Amqp Service Test")
|
||||
public class BaseAmqpServiceTest {
|
||||
|
||||
@Mock
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
private BaseAmqpService baseAmqpService;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter());
|
||||
baseAmqpService = new BaseAmqpService(rabbitTemplate);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that the message conversion works")
|
||||
public void convertMessageTest() {
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
actionUpdateStatus.setActionId(1L);
|
||||
actionUpdateStatus.setSoftwareModuleId(2L);
|
||||
|
||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(actionUpdateStatus,
|
||||
new MessageProperties());
|
||||
ActionUpdateStatus convertedActionUpdateStatus = baseAmqpService.convertMessage(message,
|
||||
ActionUpdateStatus.class);
|
||||
|
||||
assertThat(convertedActionUpdateStatus).as("Converted Action Status is wrong")
|
||||
.isEqualsToByComparingFields(actionUpdateStatus);
|
||||
|
||||
convertedActionUpdateStatus = baseAmqpService.convertMessage(null, ActionUpdateStatus.class);
|
||||
assertThat(convertedActionUpdateStatus).as("Converted Object should be null when message is null").isNull();
|
||||
|
||||
convertedActionUpdateStatus = baseAmqpService.convertMessage(new Message(null, new MessageProperties()),
|
||||
ActionUpdateStatus.class);
|
||||
assertThat(convertedActionUpdateStatus).as("Converted Object should be null when message body is null")
|
||||
.isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that a conversion of a list from a message works")
|
||||
public void convertMessageListTest() {
|
||||
final List<ActionUpdateStatus> actionUpdateStatusList = new ArrayList<>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
final ActionUpdateStatus actionUpdateStatus = new ActionUpdateStatus();
|
||||
actionUpdateStatus.setActionId(Long.valueOf(i));
|
||||
actionUpdateStatus.setSoftwareModuleId(Long.valueOf(i));
|
||||
actionUpdateStatusList.add(actionUpdateStatus);
|
||||
}
|
||||
|
||||
final Message message = rabbitTemplate.getMessageConverter().toMessage(actionUpdateStatusList,
|
||||
new MessageProperties());
|
||||
List<ActionUpdateStatus> convertedActionUpdateStatus = baseAmqpService.convertMessageList(message,
|
||||
ActionUpdateStatus.class);
|
||||
|
||||
assertThat(convertedActionUpdateStatus).as("Converted Action Status list is wrong")
|
||||
.hasSameClassAs(actionUpdateStatusList);
|
||||
assertThat(convertedActionUpdateStatus).as("Converted Action Status list is wrong")
|
||||
.hasSameSizeAs(actionUpdateStatusList);
|
||||
|
||||
convertedActionUpdateStatus = baseAmqpService.convertMessageList(null, ActionUpdateStatus.class);
|
||||
assertThat(convertedActionUpdateStatus).as("Converted list should be empty when message is null").isEmpty();
|
||||
|
||||
convertedActionUpdateStatus = baseAmqpService.convertMessageList(new Message(null, new MessageProperties()),
|
||||
ActionUpdateStatus.class);
|
||||
assertThat(convertedActionUpdateStatus).as("Converted list should be empty when message body is null")
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,9 @@ 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.dmf.json.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
@@ -20,6 +23,7 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
@@ -31,6 +35,8 @@ 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 })
|
||||
public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
@Autowired
|
||||
@@ -50,29 +56,33 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests generate the http download url")
|
||||
@Description("Tests the generation of http download url.")
|
||||
public void testHttpUrl() {
|
||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTP);
|
||||
assertEquals("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||
+ localArtifact.getFilename(), url);
|
||||
assertEquals("http is build incorrect",
|
||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||
+ localArtifact.getFilename(),
|
||||
url);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests generate the https download url")
|
||||
@Description("Tests the generation of https download url.")
|
||||
public void testHttpsUrl() {
|
||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.HTTPS);
|
||||
assertEquals("https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||
+ localArtifact.getFilename(), url);
|
||||
assertEquals("https is build incorrect",
|
||||
"https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
|
||||
+ localArtifact.getFilename(),
|
||||
url);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests generate the coap download url")
|
||||
@Description("Tests the generation of coap download url.")
|
||||
public void testCoapUrl() {
|
||||
final String url = urlHandlerProperties.getUrl(controllerId, localArtifact, Artifact.UrlProtocol.COAP);
|
||||
|
||||
assertEquals("coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/" + controllerId + "/sha1/"
|
||||
+ localArtifact.getSha1Hash(), url);
|
||||
assertEquals("coap is build incorrect", "coap://127.0.0.1:5683/fw/" + tenantAware.getCurrentTenant() + "/"
|
||||
+ controllerId + "/sha1/" + localArtifact.getSha1Hash(), url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,13 @@ import org.springframework.security.authentication.InsufficientAuthenticationExc
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Security")
|
||||
@Stories("PreAuthToken Source TrustAuthentication Provider Test")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
// TODO: create description annotations
|
||||
public class PreAuthTokenSourceTrustAuthenticationProviderTest {
|
||||
|
||||
private static final String REQUEST_SOURCE_IP = "127.0.0.1";
|
||||
|
||||
@@ -99,6 +99,11 @@
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
@@ -215,7 +220,7 @@
|
||||
<plugin>
|
||||
<groupId>com.ethlo.persistence.tools</groupId>
|
||||
<artifactId>eclipselink-maven-plugin</artifactId>
|
||||
<version>1.1-SNAPSHOT</version>
|
||||
<version>2.6.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-classes</phase>
|
||||
|
||||
@@ -48,7 +48,9 @@ public class MultiTenantJpaTransactionManager extends JpaTransactionManager {
|
||||
&& !definition.getName().startsWith(SystemManagement.class.getCanonicalName() + ".deleteTenant")
|
||||
&& !definition.getName()
|
||||
.startsWith(SystemManagement.class.getCanonicalName() + ".currentTenantKeyGenerator")
|
||||
&& !definition.getName().startsWith(RolloutManagement.class.getCanonicalName() + ".rolloutScheduler")) {
|
||||
&& !definition.getName().startsWith(RolloutManagement.class.getCanonicalName() + ".rolloutScheduler")
|
||||
&& !definition.getName()
|
||||
.startsWith(SystemManagement.class.getCanonicalName() + ".getOrCreateTenantMetadata")) {
|
||||
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant == null) {
|
||||
|
||||
@@ -38,10 +38,6 @@ import org.springframework.validation.beanvalidation.MethodValidationPostProcess
|
||||
/**
|
||||
* General configuration for the SP Repository.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@EnableJpaRepositories(basePackages = { "org.eclipse.hawkbit.repository" })
|
||||
@EnableTransactionManagement
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Rollout Management properties.
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties("hawkbit.rollout")
|
||||
public class RolloutProperties {
|
||||
private final Scheduler scheduler = new Scheduler();
|
||||
|
||||
public Scheduler getScheduler() {
|
||||
return scheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollout scheduler configuration.
|
||||
*/
|
||||
public static class Scheduler {
|
||||
// used by @Scheduled annotation which needs constant
|
||||
public static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${hawkbit.rollout.scheduler.fixedDelay:30000}";
|
||||
|
||||
/**
|
||||
* Schedule where the rollout scheduler looks necessary state changes in
|
||||
* milliseconds.
|
||||
*/
|
||||
private long fixedDelay = 30000L;
|
||||
|
||||
public long getFixedDelay() {
|
||||
return fixedDelay;
|
||||
}
|
||||
|
||||
public void setFixedDelay(final long fixedDelay) {
|
||||
this.fixedDelay = fixedDelay;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,45 +21,47 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
/**
|
||||
* {@link ActionStatus} repository.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public interface ActionStatusRepository
|
||||
extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> {
|
||||
|
||||
/**
|
||||
* @param target
|
||||
* Counts {@link ActionStatus} entries of given {@link Action} in
|
||||
* repository.
|
||||
*
|
||||
* @param action
|
||||
* @return
|
||||
* to count status entries
|
||||
* @return number of actions in repository
|
||||
*/
|
||||
Long countByAction(Action action);
|
||||
|
||||
/**
|
||||
* Counts {@link ActionStatus} entries of given {@link Action} with given
|
||||
* {@link Status} in repository.
|
||||
*
|
||||
* @param action
|
||||
* @param retrieved
|
||||
* @return
|
||||
* to count status entries
|
||||
* @param status
|
||||
* to filter for
|
||||
* @return number of actions in repository
|
||||
*/
|
||||
Long countByActionAndStatus(Action action, Status retrieved);
|
||||
Long countByActionAndStatus(Action action, Status status);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link ActionStatus} entries from repository of given
|
||||
* {@link Action}.
|
||||
*
|
||||
* @param pageReq
|
||||
* parameters
|
||||
* @param action
|
||||
* @return
|
||||
* of the status entries
|
||||
* @return pages list of {@link ActionStatus} entries
|
||||
*/
|
||||
Page<ActionStatus> findByAction(Pageable pageReq, Action action);
|
||||
|
||||
/**
|
||||
* @param pageReq
|
||||
* @param action
|
||||
* @return
|
||||
*/
|
||||
Page<ActionStatus> findByActionOrderByIdDesc(Pageable pageReq, Action action);
|
||||
|
||||
/**
|
||||
* Finds all status updates for the defined action and target order by
|
||||
* {@link ActionStatus#getId()} desc including
|
||||
* Finds all status updates for the defined action and target including
|
||||
* {@link ActionStatus#getMessages()}.
|
||||
*
|
||||
* @param pageReq
|
||||
@@ -71,6 +73,6 @@ public interface ActionStatusRepository
|
||||
* @return Page with found targets
|
||||
*/
|
||||
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
|
||||
Page<ActionStatus> getByActionOrderByIdDesc(Pageable pageReq, Action action);
|
||||
Page<ActionStatus> getByAction(Pageable pageReq, Action action);
|
||||
|
||||
}
|
||||
|
||||
@@ -33,13 +33,11 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Target_;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
@@ -57,7 +55,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
@Transactional(readOnly = true)
|
||||
@Validated
|
||||
@Service
|
||||
public class ControllerManagement implements EnvironmentAware {
|
||||
public class ControllerManagement {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ControllerManagement.class);
|
||||
private static final Logger LOG_DOS = LoggerFactory.getLogger("server-security.dos");
|
||||
|
||||
@@ -85,9 +83,8 @@ public class ControllerManagement implements EnvironmentAware {
|
||||
@Autowired
|
||||
private ActionStatusRepository actionStatusRepository;
|
||||
|
||||
private Integer maxCount = 1000;
|
||||
|
||||
private Integer maxAttributes = 100;
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* Refreshes the time of the last time the controller has been connected to
|
||||
@@ -379,15 +376,16 @@ public class ControllerManagement implements EnvironmentAware {
|
||||
}
|
||||
|
||||
private void checkForToManyStatusEntries(final Action action) {
|
||||
if (maxCount > 0) {
|
||||
if (securityProperties.getDos().getMaxStatusEntriesPerAction() > 0) {
|
||||
|
||||
final Long statusCount = actionStatusRepository.countByAction(action);
|
||||
|
||||
if (statusCount >= maxCount) {
|
||||
if (statusCount >= securityProperties.getDos().getMaxStatusEntriesPerAction()) {
|
||||
LOG_DOS.error(
|
||||
"Potential denial of service (DOS) attack identfied. More status entries in the system than permitted ({})!",
|
||||
maxCount);
|
||||
throw new ToManyStatusEntriesException(String.valueOf(maxCount));
|
||||
securityProperties.getDos().getMaxStatusEntriesPerAction());
|
||||
throw new ToManyStatusEntriesException(
|
||||
String.valueOf(securityProperties.getDos().getMaxStatusEntriesPerAction()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,10 +434,12 @@ public class ControllerManagement implements EnvironmentAware {
|
||||
|
||||
target.getTargetInfo().getControllerAttributes().putAll(data);
|
||||
|
||||
if (target.getTargetInfo().getControllerAttributes().size() > maxAttributes) {
|
||||
if (target.getTargetInfo().getControllerAttributes().size() > securityProperties.getDos()
|
||||
.getMaxAttributeEntriesPerTarget()) {
|
||||
LOG_DOS.info("Target tries to insert more than the allowed number of entries ({}). DOS attack anticipated!",
|
||||
maxAttributes);
|
||||
throw new ToManyAttributeEntriesException(String.valueOf(maxAttributes));
|
||||
securityProperties.getDos().getMaxAttributeEntriesPerTarget());
|
||||
throw new ToManyAttributeEntriesException(
|
||||
String.valueOf(securityProperties.getDos().getMaxAttributeEntriesPerTarget()));
|
||||
}
|
||||
|
||||
target.getTargetInfo().setLastTargetQuery(System.currentTimeMillis());
|
||||
@@ -447,19 +447,6 @@ public class ControllerManagement implements EnvironmentAware {
|
||||
return targetRepository.save(target);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.context.EnvironmentAware#setEnvironment(org.
|
||||
* springframework.core.env. Environment)
|
||||
*/
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
final RelaxedPropertyResolver env = new RelaxedPropertyResolver(environment, "hawkbit.server.");
|
||||
maxCount = env.getProperty("security.dos.maxStatusEntriesPerAction", Integer.class, 1000);
|
||||
maxAttributes = env.getProperty("security.dos.maxAttributeEntriesPerTarget", Integer.class, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers retrieved status for given {@link Target} and {@link Action} if
|
||||
* it does not exist yet.
|
||||
|
||||
@@ -365,7 +365,7 @@ public class DeploymentManagement {
|
||||
}).collect(Collectors.toList())).stream()
|
||||
.collect(Collectors.toMap(a -> a.getTarget().getControllerId(), Function.identity()));
|
||||
|
||||
// MECS-720 create initial action status when action is created so we
|
||||
// create initial action status when action is created so we
|
||||
// remember the initial
|
||||
// running status because we will change the status of the action itself
|
||||
// and with this action
|
||||
@@ -925,7 +925,7 @@ public class DeploymentManagement {
|
||||
|
||||
/**
|
||||
* retrieves all the {@link ActionStatus} entries of the given
|
||||
* {@link Action} and {@link Target} in the order latest first.
|
||||
* {@link Action} and {@link Target}.
|
||||
*
|
||||
* @param pageReq
|
||||
* pagination parameter
|
||||
@@ -937,12 +937,12 @@ public class DeploymentManagement {
|
||||
* @return the corresponding {@link Page} of {@link ActionStatus}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
public Page<ActionStatus> findActionStatusMessagesByActionInDescOrder(final Pageable pageReq, final Action action,
|
||||
public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final Action action,
|
||||
final boolean withMessages) {
|
||||
if (withMessages) {
|
||||
return actionStatusRepository.getByActionOrderByIdDesc(pageReq, action);
|
||||
return actionStatusRepository.getByAction(pageReq, action);
|
||||
} else {
|
||||
return actionStatusRepository.findByActionOrderByIdDesc(pageReq, action);
|
||||
return actionStatusRepository.findByAction(pageReq, action);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,8 +294,7 @@ public class DistributionSetManagement {
|
||||
// hard delete the rest if exixts
|
||||
if (!toHardDelete.isEmpty()) {
|
||||
// don't give the delete statement an empty list, JPA/Oracle cannot
|
||||
// handle the empty list,
|
||||
// see MECS-403
|
||||
// handle the empty list
|
||||
distributionSetRepository.deleteByIdIn(toHardDelete);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,6 @@ import org.eclipse.hawkbit.repository.model.Target_;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -55,14 +54,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
/**
|
||||
* Service layer for generating SP reportings.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@Validated
|
||||
@Service
|
||||
@ConfigurationProperties
|
||||
public class ReportManagement {
|
||||
|
||||
@Value("${spring.jpa.database}")
|
||||
|
||||
@@ -10,14 +10,13 @@ package org.eclipse.hawkbit.repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.RolloutProperties;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -31,15 +30,10 @@ import org.springframework.stereotype.Component;
|
||||
// don't active the rollout scheduler in test, otherwise it is hard to test
|
||||
// rolloutmanagement and leads weird side-effects maybe.
|
||||
@Profile("!test")
|
||||
public class RolloutScheduler implements EnvironmentAware {
|
||||
public class RolloutScheduler {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RolloutScheduler.class);
|
||||
|
||||
private static final String PROP_SCHEDULER_DELAY = "hawkbit.rollout.scheduler.fixedDelay";
|
||||
private static final long DEFAULT_SCHEDULER_DELAY = 30000L;
|
||||
private static final String PROP_SCHEDULER_DELAY_PLACEHOLDER = "${" + PROP_SCHEDULER_DELAY + ":"
|
||||
+ DEFAULT_SCHEDULER_DELAY + "}";
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@@ -52,7 +46,8 @@ public class RolloutScheduler implements EnvironmentAware {
|
||||
@Autowired
|
||||
private SystemSecurityContext systemSecurityContext;
|
||||
|
||||
private long fixedDelay = DEFAULT_SCHEDULER_DELAY;
|
||||
@Autowired
|
||||
private RolloutProperties rolloutProperties;
|
||||
|
||||
/**
|
||||
* Scheduler method called by the spring-async mechanism. Retrieves all
|
||||
@@ -60,7 +55,7 @@ public class RolloutScheduler implements EnvironmentAware {
|
||||
* tenant the {@link RolloutManagement#checkRunningRollouts(long)} in the
|
||||
* {@link SystemSecurityContext}.
|
||||
*/
|
||||
@Scheduled(initialDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER)
|
||||
@Scheduled(initialDelayString = RolloutProperties.Scheduler.PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = RolloutProperties.Scheduler.PROP_SCHEDULER_DELAY_PLACEHOLDER)
|
||||
public void rolloutScheduler() {
|
||||
logger.debug("rollout schedule checker has been triggered.");
|
||||
// run this code in system code privileged to have the necessary
|
||||
@@ -76,16 +71,11 @@ public class RolloutScheduler implements EnvironmentAware {
|
||||
logger.info("Checking rollouts for {} tenants", tenants.size());
|
||||
for (final String tenant : tenants) {
|
||||
tenantAware.runAsTenant(tenant, () -> {
|
||||
rolloutManagement.checkRunningRollouts(fixedDelay);
|
||||
rolloutManagement.checkRunningRollouts(rolloutProperties.getScheduler().getFixedDelay());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
fixedDelay = environment.getProperty(PROP_SCHEDULER_DELAY, Long.class, DEFAULT_SCHEDULER_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ public class SystemManagement {
|
||||
* @return {@code true} in case the tenant exits or {@code false} if not
|
||||
*/
|
||||
@Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator")
|
||||
// MECS-903 set transaction to not supported, due we call this in
|
||||
// set transaction to not supported, due we call this in
|
||||
// BaseEntity#prePersist methods
|
||||
// and it seems that JPA committing the transaction when executing this
|
||||
// transactional method,
|
||||
|
||||
@@ -17,8 +17,8 @@ import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.repository.model.helper.EventBusHolder;
|
||||
import org.eclipse.hawkbit.repository.utils.RepositoryDataGenerator;
|
||||
import org.eclipse.hawkbit.repository.utils.RepositoryDataGenerator.DatabaseCleanupUtil;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
@@ -47,7 +47,7 @@ import com.mongodb.MongoClientOptions;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
|
||||
@EnableConfigurationProperties({ SecurityProperties.class, ControllerPollProperties.class })
|
||||
@EnableConfigurationProperties({ DdiSecurityProperties.class, ControllerPollProperties.class })
|
||||
@Profile("test")
|
||||
public class TestConfiguration implements AsyncConfigurer {
|
||||
|
||||
|
||||
@@ -12,6 +12,11 @@ import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Repository")
|
||||
@Stories("CacheKeys")
|
||||
public class CacheKeysTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,6 +26,11 @@ import org.springframework.cache.CacheManager;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Repository")
|
||||
@Stories("CacheWriteNotify")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CacheWriteNotifyTest {
|
||||
|
||||
|
||||
@@ -27,6 +27,11 @@ import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
import org.springframework.hateoas.Identifiable;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Repository")
|
||||
@Stories("EventBus")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CacheFieldEntityListenerTest {
|
||||
|
||||
|
||||
@@ -14,10 +14,16 @@ import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.junit.Test;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Repository")
|
||||
@Stories("Deployment Management")
|
||||
public class ActionTest {
|
||||
|
||||
// issue MECS-670 timeforced update and eTAG calculation
|
||||
@Test
|
||||
@Description("Ensures that timeforced moded switch from soft to forces after defined timeframe.")
|
||||
public void timeforcedHitNewHasCodeIsGenerated() throws InterruptedException {
|
||||
|
||||
final boolean active = true;
|
||||
|
||||
@@ -25,9 +25,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
/**
|
||||
* Addition tests next to {@link ArtifactManagementTest} with no running MongoDB
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Artifact Management")
|
||||
|
||||
@@ -70,8 +70,8 @@ public class ControllerManagementTest extends AbstractIntegrationTest {
|
||||
.isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
|
||||
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
|
||||
assertThat(deploymentManagement.findActionStatusMessagesByActionInDescOrder(pageReq, savedAction, false)
|
||||
.getNumberOfElements()).isEqualTo(3);
|
||||
assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction, false).getNumberOfElements())
|
||||
.isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -50,7 +50,6 @@ import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Issue;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
@@ -145,7 +144,6 @@ public class DeploymentManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test verifies that an assignment with automatic cancelation works correctly even if the update is split into multiple partitions on the database.")
|
||||
@Issue("MECS-674")
|
||||
public void multiAssigmentHistoryOverMultiplePagesResultsInTwoActiveAction() {
|
||||
|
||||
final DistributionSet cancelDs = TestDataUtil.generateDistributionSet("Canceled DS", "1.0", softwareManagement,
|
||||
@@ -766,12 +764,13 @@ public class DeploymentManagementTest extends AbstractIntegrationTest {
|
||||
distributionSetManagement.findDistributionSetByIdWithDetails(dsA.getId()).getOptLockRevision());
|
||||
|
||||
// verifying that the assignment is correct
|
||||
assertEquals(1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||
assertEquals(1, deploymentManagement.findActionsByTarget(targ).size());
|
||||
assertEquals(TargetUpdateStatus.PENDING, targ.getTargetInfo().getUpdateStatus());
|
||||
assertEquals(dsA, targ.getAssignedDistributionSet());
|
||||
assertEquals(dsA, deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
||||
assertNull(targ.getTargetInfo().getInstalledDistributionSet());
|
||||
assertEquals("Active target actions are wrong", 1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||
assertEquals("Target actions are wrong", 1, deploymentManagement.findActionsByTarget(targ).size());
|
||||
assertEquals("Target status is wrong", TargetUpdateStatus.PENDING, targ.getTargetInfo().getUpdateStatus());
|
||||
assertEquals("Assigned ds is wrong", dsA, targ.getAssignedDistributionSet());
|
||||
assertEquals("Active ds is wrong", dsA,
|
||||
deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
||||
assertNull("Installed ds should be null", targ.getTargetInfo().getInstalledDistributionSet());
|
||||
|
||||
final Page<Action> updAct = actionRepository.findByDistributionSet(pageReq, dsA);
|
||||
final Action action = updAct.getContent().get(0);
|
||||
@@ -781,29 +780,28 @@ public class DeploymentManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
targ = targetManagement.findTargetByControllerID(targ.getControllerId());
|
||||
|
||||
assertEquals(0, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||
// try {
|
||||
assertEquals(1, deploymentManagement.findInActiveActionsByTarget(targ).size());
|
||||
// }
|
||||
// catch( final LazyInitializationException ex ) {
|
||||
//
|
||||
// }
|
||||
assertEquals(TargetUpdateStatus.IN_SYNC, targ.getTargetInfo().getUpdateStatus());
|
||||
assertEquals(dsA, targ.getAssignedDistributionSet());
|
||||
assertEquals(dsA, targ.getTargetInfo().getInstalledDistributionSet());
|
||||
assertEquals("active target actions are wrong", 0, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||
assertEquals("active actions are wrong", 1, deploymentManagement.findInActiveActionsByTarget(targ).size());
|
||||
|
||||
assertEquals("tagret update status is not correct", TargetUpdateStatus.IN_SYNC,
|
||||
targ.getTargetInfo().getUpdateStatus());
|
||||
assertEquals("wrong assigned ds", dsA, targ.getAssignedDistributionSet());
|
||||
assertEquals("wrong installed ds", dsA, targ.getTargetInfo().getInstalledDistributionSet());
|
||||
|
||||
targs = deploymentManagement.assignDistributionSet(dsB.getId(), new String[] { "target-id-A" })
|
||||
.getAssignedTargets();
|
||||
|
||||
targ = targs.iterator().next();
|
||||
|
||||
assertEquals(1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||
assertEquals(TargetUpdateStatus.PENDING,
|
||||
assertEquals("active actions are wrong", 1, deploymentManagement.findActiveActionsByTarget(targ).size());
|
||||
assertEquals("target status is wrong", TargetUpdateStatus.PENDING,
|
||||
targetManagement.findTargetByControllerID(targ.getControllerId()).getTargetInfo().getUpdateStatus());
|
||||
assertEquals(dsB, targ.getAssignedDistributionSet());
|
||||
assertEquals(dsA.getId(), targetManagement.findTargetByControllerIDWithDetails(targ.getControllerId())
|
||||
.getTargetInfo().getInstalledDistributionSet().getId());
|
||||
assertEquals(dsB, deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
||||
assertEquals("wrong assigned ds", dsB, targ.getAssignedDistributionSet());
|
||||
assertEquals("Installed ds is wrong", dsA.getId(),
|
||||
targetManagement.findTargetByControllerIDWithDetails(targ.getControllerId()).getTargetInfo()
|
||||
.getInstalledDistributionSet().getId());
|
||||
assertEquals("Active ds is wrong", dsB,
|
||||
deploymentManagement.findActiveActionsByTarget(targ).get(0).getDistributionSet());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.repository;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -22,6 +23,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.Tag;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -34,18 +36,19 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
/**
|
||||
* Test class for {@link TagManagement}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Tag Management")
|
||||
// TODO: fully document tests -> @Description for long text and reasonable
|
||||
// method name as short text
|
||||
public class TagManagementTest extends AbstractIntegrationTest {
|
||||
public TagManagementTest() {
|
||||
LOG = LoggerFactory.getLogger(TagManagementTest.class);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
assertThat(targetTagRepository.findAll()).as("Not tags should be available").isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Full DS tag lifecycle tested. Create tags, assign them to sets and delete the tags.")
|
||||
public void createAndAssignAndDeleteDistributionSetTags() {
|
||||
@@ -92,7 +95,7 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
// search for not deleted
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true)
|
||||
.setTagNames(Lists.newArrayList(tagA.getName()));
|
||||
assertEquals(
|
||||
assertEquals("filter works not correct",
|
||||
dsAs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown()
|
||||
+ dsACs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(),
|
||||
distributionSetManagement.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build())
|
||||
@@ -100,7 +103,7 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true)
|
||||
.setTagNames(Lists.newArrayList(tagB.getName()));
|
||||
assertEquals(
|
||||
assertEquals("filter works not correct",
|
||||
dsBs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown()
|
||||
+ dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(),
|
||||
distributionSetManagement.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build())
|
||||
@@ -108,7 +111,7 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true)
|
||||
.setTagNames(Lists.newArrayList(tagC.getName()));
|
||||
assertEquals(
|
||||
assertEquals("filter works not correct",
|
||||
dsCs.spliterator().getExactSizeIfKnown() + dsACs.spliterator().getExactSizeIfKnown()
|
||||
+ dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(),
|
||||
distributionSetManagement.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build())
|
||||
@@ -116,22 +119,22 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(true)
|
||||
.setTagNames(Lists.newArrayList(tagX.getName()));
|
||||
assertEquals(0, distributionSetManagement
|
||||
assertEquals("filter works not correct", 0, distributionSetManagement
|
||||
.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build()).getTotalElements());
|
||||
|
||||
assertEquals(5, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
assertEquals("wrong tag size", 5, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
|
||||
tagManagement.deleteDistributionSetTag(tagY.getName());
|
||||
assertEquals(4, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
assertEquals("wrong tag size", 4, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
tagManagement.deleteDistributionSetTag(tagX.getName());
|
||||
assertEquals(3, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
assertEquals("wrong tag size", 3, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
|
||||
tagManagement.deleteDistributionSetTag(tagB.getName());
|
||||
assertEquals(2, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
assertEquals("wrong tag size", 2, distributionSetTagRepository.findAll().spliterator().getExactSizeIfKnown());
|
||||
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
|
||||
.setTagNames(Lists.newArrayList(tagA.getName()));
|
||||
assertEquals(
|
||||
assertEquals("filter works not correct",
|
||||
dsAs.spliterator().getExactSizeIfKnown() + dsABs.spliterator().getExactSizeIfKnown()
|
||||
+ dsACs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(),
|
||||
distributionSetManagement.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build())
|
||||
@@ -139,12 +142,12 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
|
||||
.setTagNames(Lists.newArrayList(tagB.getName()));
|
||||
assertEquals(0, distributionSetManagement
|
||||
assertEquals("filter works not correct", 0, distributionSetManagement
|
||||
.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build()).getTotalElements());
|
||||
|
||||
distributionSetFilterBuilder = getDistributionSetFilterBuilder().setIsComplete(Boolean.TRUE)
|
||||
.setTagNames(Lists.newArrayList(tagC.getName()));
|
||||
assertEquals(
|
||||
assertEquals("filter works not correct",
|
||||
dsCs.spliterator().getExactSizeIfKnown() + dsACs.spliterator().getExactSizeIfKnown()
|
||||
+ dsBCs.spliterator().getExactSizeIfKnown() + dsABCs.spliterator().getExactSizeIfKnown(),
|
||||
distributionSetManagement.findDistributionSetsByFilters(pageReq, distributionSetFilterBuilder.build())
|
||||
@@ -155,45 +158,28 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
return new DistributionSetFilterBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#findTargetTag(java.lang.String)}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testFindTargetTag() {
|
||||
assertThat(targetTagRepository.findAll()).isEmpty();
|
||||
|
||||
@Description("Ensures that all tags are retrieved through repository.")
|
||||
public void findAllTargetTags() {
|
||||
final List<TargetTag> tags = createTargetsWithTags();
|
||||
|
||||
assertThat(targetTagRepository.findAll()).isEqualTo(tagManagement.findAllTargetTags()).isEqualTo(tags)
|
||||
.hasSize(20);
|
||||
.as("Wrong tag size").hasSize(20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#createTargetTag(org.eclipse.hawkbit.repository.model.TargetTag)}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testCreateTargetTag() {
|
||||
assertThat(targetTagRepository.findAll()).isEmpty();
|
||||
|
||||
@Description("Ensures that a created tag is persisted in the repository as defined.")
|
||||
public void createTargetTag() {
|
||||
final Tag tag = tagManagement.createTargetTag(new TargetTag("kai1", "kai2", "colour"));
|
||||
|
||||
assertThat(targetTagRepository.findByNameEquals("kai1").getDescription()).isEqualTo("kai2");
|
||||
assertThat(tagManagement.findTargetTag("kai1").getColour()).isEqualTo("colour");
|
||||
assertThat(tagManagement.findTargetTagById(tag.getId()).getColour()).isEqualTo("colour");
|
||||
assertThat(targetTagRepository.findByNameEquals("kai1").getDescription()).as("wrong tag ed").isEqualTo("kai2");
|
||||
assertThat(tagManagement.findTargetTag("kai1").getColour()).as("wrong tag found").isEqualTo("colour");
|
||||
assertThat(tagManagement.findTargetTagById(tag.getId()).getColour()).as("wrong tag found").isEqualTo("colour");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#deleteTargetTag(java.lang.String[])}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteTargetTagsStringArray() {
|
||||
assertThat(targetTagRepository.findAll()).isEmpty();
|
||||
@Description("Ensures that a deleted tag is removed from the repository as defined.")
|
||||
public void deleteTargetTas() {
|
||||
|
||||
// create test data
|
||||
final Iterable<TargetTag> tags = createTargetsWithTags();
|
||||
@@ -212,16 +198,13 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
assertThat(targetManagement.findTargetByControllerID(target.getControllerId()).getTags())
|
||||
.doesNotContain(toDelete);
|
||||
}
|
||||
assertThat(targetTagRepository.findOne(toDelete.getId())).isNull();
|
||||
assertThat(tagManagement.findAllTargetTags()).hasSize(19);
|
||||
assertThat(targetTagRepository.findOne(toDelete.getId())).as("No tag should be found").isNull();
|
||||
assertThat(tagManagement.findAllTargetTags()).as("Wrong target tag size").hasSize(19);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the creation of a target tag.")
|
||||
@Description("Tests the name update of a target tag.")
|
||||
public void updateTargetTag() {
|
||||
assertThat(targetTagRepository.findAll()).isEmpty();
|
||||
|
||||
// create test data
|
||||
final List<TargetTag> tags = createTargetsWithTags();
|
||||
|
||||
// change data
|
||||
@@ -232,91 +215,104 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
tagManagement.updateTargetTag(savedAssigned);
|
||||
|
||||
// check data
|
||||
assertThat(tagManagement.findAllTargetTags()).hasSize(tags.size());
|
||||
assertThat(targetTagRepository.findOne(savedAssigned.getId()).getName()).isEqualTo("test123");
|
||||
assertThat(targetTagRepository.findOne(savedAssigned.getId()).getOptLockRevision()).isEqualTo(2);
|
||||
assertThat(tagManagement.findAllTargetTags()).as("Wrong target tag size").hasSize(tags.size());
|
||||
assertThat(targetTagRepository.findOne(savedAssigned.getId()).getName()).as("wrong target tag is saved")
|
||||
.isEqualTo("test123");
|
||||
assertThat(targetTagRepository.findOne(savedAssigned.getId()).getOptLockRevision())
|
||||
.as("wrong target tag is saved").isEqualTo(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#createDistributionSetTag(org.eclipse.hawkbit.repository.model.DistributionSetTag)}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testCreateDistributionSetTag() {
|
||||
assertThat(distributionSetTagRepository.findAll()).isEmpty();
|
||||
|
||||
@Description("Ensures that a created tag is persisted in the repository as defined.")
|
||||
public void createDistributionSetTag() {
|
||||
final Tag tag = tagManagement.createDistributionSetTag(new DistributionSetTag("kai1", "kai2", "colour"));
|
||||
|
||||
assertThat(distributionSetTagRepository.findByNameEquals("kai1").getDescription()).isEqualTo("kai2");
|
||||
assertThat(tagManagement.findDistributionSetTag("kai1").getColour()).isEqualTo("colour");
|
||||
assertThat(tagManagement.findDistributionSetTagById(tag.getId()).getColour()).isEqualTo("colour");
|
||||
assertThat(distributionSetTagRepository.findByNameEquals("kai1").getDescription()).as("wrong tag found")
|
||||
.isEqualTo("kai2");
|
||||
assertThat(tagManagement.findDistributionSetTag("kai1").getColour()).as("wrong tag found").isEqualTo("colour");
|
||||
assertThat(tagManagement.findDistributionSetTagById(tag.getId()).getColour()).as("wrong tag found")
|
||||
.isEqualTo("colour");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#createDistributionSetTags(java.lang.Iterable)}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testCreateDistributionSetTags() {
|
||||
assertThat(distributionSetTagRepository.findAll()).isEmpty();
|
||||
|
||||
@Description("Ensures that a created tags are persisted in the repository as defined.")
|
||||
public void createDistributionSetTags() {
|
||||
final List<DistributionSetTag> tags = createDsSetsWithTags();
|
||||
|
||||
assertThat(distributionSetTagRepository.findAll()).hasSize(tags.size());
|
||||
assertThat(distributionSetTagRepository.findAll()).as("Wrong size of tags created").hasSize(tags.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#deleteDistributionSetTag(java.lang.String[])}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteDistributionSetTag() {
|
||||
assertThat(distributionSetTagRepository.findAll()).isEmpty();
|
||||
|
||||
@Description("Ensures that a deleted tag is removed from the repository as defined.")
|
||||
public void deleteDistributionSetTag() {
|
||||
// create test data
|
||||
final Iterable<DistributionSetTag> tags = createDsSetsWithTags();
|
||||
final DistributionSetTag toDelete = tags.iterator().next();
|
||||
|
||||
for (final DistributionSet set : distributionSetRepository.findAll()) {
|
||||
assertThat(distributionSetManagement.findDistributionSetByIdWithDetails(set.getId()).getTags())
|
||||
.contains(toDelete);
|
||||
.as("Wrong tag found").contains(toDelete);
|
||||
}
|
||||
|
||||
// delete
|
||||
tagManagement.deleteDistributionSetTag(tags.iterator().next().getName());
|
||||
|
||||
// check
|
||||
assertThat(distributionSetTagRepository.findOne(toDelete.getId())).isNull();
|
||||
assertThat(tagManagement.findAllDistributionSetTags()).hasSize(19);
|
||||
assertThat(distributionSetTagRepository.findOne(toDelete.getId())).as("Deleted tag should be null").isNull();
|
||||
assertThat(tagManagement.findAllDistributionSetTags()).as("Wrong size of tags after deletion").hasSize(19);
|
||||
for (final DistributionSet set : distributionSetRepository.findAll()) {
|
||||
assertThat(distributionSetManagement.findDistributionSetByIdWithDetails(set.getId()).getTags())
|
||||
.doesNotContain(toDelete);
|
||||
.as("Wrong found tags").doesNotContain(toDelete);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = EntityAlreadyExistsException.class)
|
||||
public void testFailedDuplicateTargetTagNameException() {
|
||||
tagManagement.createTargetTag(new TargetTag("A"));
|
||||
@Description("Ensures that a tag cannot be created if one exists already with that name (ecpects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateTargetTagNameException() {
|
||||
tagManagement.createTargetTag(new TargetTag("A"));
|
||||
try {
|
||||
tagManagement.createTargetTag(new TargetTag("A"));
|
||||
fail("Expected EntityAlreadyExistsException");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = EntityAlreadyExistsException.class)
|
||||
public void testFailedDuplicateDsTagNameException() {
|
||||
tagManagement.createDistributionSetTag(new DistributionSetTag("A"));
|
||||
tagManagement.createDistributionSetTag(new DistributionSetTag("A"));
|
||||
@Description("Ensures that a tag cannot be updated to a name that already exists on another tag (ecpects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateTargetTagNameExceptionAfterUpdate() {
|
||||
tagManagement.createTargetTag(new TargetTag("A"));
|
||||
final TargetTag tag = tagManagement.createTargetTag(new TargetTag("B"));
|
||||
tag.setName("A");
|
||||
try {
|
||||
tagManagement.updateTargetTag(tag);
|
||||
fail("Expected EntityAlreadyExistsException");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Description("Ensures that a tag cannot be created if one exists already with that name (ecpects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateDsTagNameException() {
|
||||
tagManagement.createDistributionSetTag(new DistributionSetTag("A"));
|
||||
try {
|
||||
tagManagement.createDistributionSetTag(new DistributionSetTag("A"));
|
||||
fail("Expected EntityAlreadyExistsException");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Description("Ensures that a tag cannot be updated to a name that already exists on another tag (ecpects EntityAlreadyExistsException).")
|
||||
public void failedDuplicateDsTagNameExceptionAfterUpdate() {
|
||||
tagManagement.createDistributionSetTag(new DistributionSetTag("A"));
|
||||
final DistributionSetTag tag = tagManagement.createDistributionSetTag(new DistributionSetTag("B"));
|
||||
tag.setName("A");
|
||||
try {
|
||||
tagManagement.updateDistributionSetTag(tag);
|
||||
fail("Expected EntityAlreadyExistsException");
|
||||
} catch (final EntityAlreadyExistsException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#updateDistributionSetTag(org.eclipse.hawkbit.repository.model.DistributionSetTag)}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testUpdateDistributionSetTag() {
|
||||
assertThat(distributionSetTagRepository.findAll()).isEmpty();
|
||||
@Description("Tests the name update of a target tag.")
|
||||
public void updateDistributionSetTag() {
|
||||
|
||||
// create test data
|
||||
final List<DistributionSetTag> tags = createDsSetsWithTags();
|
||||
@@ -329,24 +325,19 @@ public class TagManagementTest extends AbstractIntegrationTest {
|
||||
tagManagement.updateDistributionSetTag(savedAssigned);
|
||||
|
||||
// check data
|
||||
assertThat(tagManagement.findAllDistributionSetTags()).hasSize(tags.size());
|
||||
assertThat(distributionSetTagRepository.findOne(savedAssigned.getId()).getName()).isEqualTo("test123");
|
||||
assertThat(tagManagement.findAllDistributionSetTags()).as("Wrong size of ds tags").hasSize(tags.size());
|
||||
assertThat(distributionSetTagRepository.findOne(savedAssigned.getId()).getName()).as("Wrong ds tag found")
|
||||
.isEqualTo("test123");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for
|
||||
* {@link org.eclipse.hawkbit.repository.TagManagement#findAllDistributionSetTags()}
|
||||
* .
|
||||
*/
|
||||
@Test
|
||||
public void testFindDistributionSetTagsAll() {
|
||||
assertThat(distributionSetTagRepository.findAll()).isEmpty();
|
||||
|
||||
@Description("Ensures that all tags are retrieved through repository.")
|
||||
public void findDistributionSetTagsAll() {
|
||||
final List<DistributionSetTag> tags = createDsSetsWithTags();
|
||||
|
||||
// test
|
||||
assertThat(tagManagement.findAllDistributionSetTags()).hasSize(tags.size());
|
||||
assertThat(distributionSetTagRepository.findAll()).hasSize(20);
|
||||
assertThat(tagManagement.findAllDistributionSetTags()).as("Wrong size of tags").hasSize(tags.size());
|
||||
assertThat(distributionSetTagRepository.findAll()).as("Wrong size of tags").hasSize(20);
|
||||
}
|
||||
|
||||
private List<TargetTag> createTargetsWithTags() {
|
||||
|
||||
@@ -47,7 +47,7 @@ public class TargetManagementSearchTest extends AbstractIntegrationTest {
|
||||
final TargetTag targTagC = tagManagement.createTargetTag(new TargetTag("TargTag-C"));
|
||||
final TargetTag targTagD = tagManagement.createTargetTag(new TargetTag("TargTag-D"));
|
||||
|
||||
// TODO kzimmerm: test also installedDS (not only assignedDS)
|
||||
// TODO kaizimmerm: test also installedDS (not only assignedDS)
|
||||
|
||||
final DistributionSet setA = TestDataUtil.generateDistributionSet("", softwareManagement,
|
||||
distributionSetManagement);
|
||||
@@ -90,7 +90,7 @@ public class TargetManagementSearchTest extends AbstractIntegrationTest {
|
||||
final PageRequest pageReq = new PageRequest(0, 500);
|
||||
// try to find several targets with different filter settings
|
||||
|
||||
// TODO kzimmerm: comment and check also the content itself, not only
|
||||
// TODO kaizimmerm: comment and check also the content itself, not only
|
||||
// the numbers
|
||||
// (containsOnly)
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(400);
|
||||
@@ -185,7 +185,7 @@ public class TargetManagementSearchTest extends AbstractIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
// TODO kzimmerm: add filter tests
|
||||
// TODO kaizimmerm: add filter tests
|
||||
@Test
|
||||
@Description("Tests the correct order of targets based on selected distribution set. The system expects to have an order based on installed, assigned DS.")
|
||||
public void targetSearchWithVariousFilterCombinationsAndOrderByDistributionSet() {
|
||||
|
||||
@@ -96,24 +96,26 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
final TargetTag targetTag = tagManagement.createTargetTag(new TargetTag("Tag1"));
|
||||
|
||||
final List<Target> assignedTargets = targetManagement.assignTag(assignTarget, targetTag);
|
||||
assertThat(assignedTargets.size()).isEqualTo(4);
|
||||
assertThat(assignedTargets.size()).as("Assigned targets are wrong").isEqualTo(4);
|
||||
assignedTargets.forEach(target -> assertThat(target.getTags().size()).isEqualTo(1));
|
||||
|
||||
TargetTag findTargetTag = tagManagement.findTargetTag("Tag1");
|
||||
assertThat(assignedTargets.size()).isEqualTo(findTargetTag.getAssignedToTargets().size());
|
||||
assertThat(assignedTargets.size()).as("Assigned targets are wrong")
|
||||
.isEqualTo(findTargetTag.getAssignedToTargets().size());
|
||||
|
||||
assertThat(targetManagement.unAssignTag("NotExist", findTargetTag)).isNull();
|
||||
assertThat(targetManagement.unAssignTag("NotExist", findTargetTag)).as("Unassign target does not work")
|
||||
.isNull();
|
||||
|
||||
final Target unAssignTarget = targetManagement.unAssignTag("targetId123", findTargetTag);
|
||||
assertThat(unAssignTarget.getControllerId()).isEqualTo("targetId123");
|
||||
assertThat(unAssignTarget.getTags().size()).isEqualTo(0);
|
||||
assertThat(unAssignTarget.getControllerId()).as("Controller id is wrong").isEqualTo("targetId123");
|
||||
assertThat(unAssignTarget.getTags()).as("Tag size is wrong").isEmpty();
|
||||
findTargetTag = tagManagement.findTargetTag("Tag1");
|
||||
assertThat(findTargetTag.getAssignedToTargets().size()).isEqualTo(3);
|
||||
assertThat(findTargetTag.getAssignedToTargets()).as("Assigned targets are wrong").hasSize(3);
|
||||
|
||||
final List<Target> unAssignTargets = targetManagement.unAssignAllTargetsByTag(findTargetTag);
|
||||
findTargetTag = tagManagement.findTargetTag("Tag1");
|
||||
assertThat(findTargetTag.getAssignedToTargets().size()).isEqualTo(0);
|
||||
assertThat(unAssignTargets.size()).isEqualTo(3);
|
||||
assertThat(findTargetTag.getAssignedToTargets()).as("Unassigned targets are wrong").isEmpty();
|
||||
assertThat(unAssignTargets).as("Unassigned targets are wrong").hasSize(3);
|
||||
unAssignTargets.forEach(target -> assertThat(target.getTags().size()).isEqualTo(0));
|
||||
}
|
||||
|
||||
@@ -121,14 +123,14 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
@Description("Ensures that targets can deleted e.g. test all cascades")
|
||||
public void deleteAndCreateTargets() {
|
||||
Target target = targetManagement.createTarget(new Target("targetId123"));
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(1);
|
||||
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(1);
|
||||
targetManagement.deleteTargets(target.getId());
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
|
||||
|
||||
target = createTargetWithAttributes("4711");
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(1);
|
||||
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(1);
|
||||
targetManagement.deleteTargets(target.getId());
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
|
||||
|
||||
final List<Long> targets = new ArrayList<Long>();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -136,9 +138,9 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
targets.add(target.getId());
|
||||
targets.add(createTargetWithAttributes("" + (i * i + 1000)).getId());
|
||||
}
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(10);
|
||||
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(10);
|
||||
targetManagement.deleteTargets(targets.toArray(new Long[targets.size()]));
|
||||
assertThat(targetManagement.countTargetsAll()).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
|
||||
}
|
||||
|
||||
private Target createTargetWithAttributes(final String controllerId) {
|
||||
@@ -150,7 +152,8 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
target = controllerManagament.updateControllerAttributes(controllerId, testData);
|
||||
|
||||
target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
|
||||
assertThat(target.getTargetInfo().getControllerAttributes()).isEqualTo(testData);
|
||||
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
|
||||
.isEqualTo(testData);
|
||||
return target;
|
||||
}
|
||||
|
||||
@@ -162,10 +165,14 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
final DistributionSet set2 = TestDataUtil.generateDistributionSet("test2", softwareManagement,
|
||||
distributionSetManagement);
|
||||
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
|
||||
Target target = createTargetWithAttributes("4711");
|
||||
|
||||
@@ -183,13 +190,19 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
target = targetManagement.findTargetByControllerIDWithDetails("4711");
|
||||
// read data
|
||||
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).isEqualTo(1);
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).isEqualTo(1);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).isEqualTo(0);
|
||||
assertThat(target.getTargetInfo().getLastTargetQuery()).isGreaterThanOrEqualTo(current);
|
||||
assertThat(target.getAssignedDistributionSet()).isEqualTo(set2);
|
||||
assertThat(target.getTargetInfo().getInstalledDistributionSet().getId()).isEqualTo(set.getId());
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set.getId())).as("Target count is wrong")
|
||||
.isEqualTo(1);
|
||||
assertThat(targetManagement.countTargetByAssignedDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(1);
|
||||
assertThat(targetManagement.countTargetByInstalledDistributionSet(set2.getId())).as("Target count is wrong")
|
||||
.isEqualTo(0);
|
||||
assertThat(target.getTargetInfo().getLastTargetQuery()).as("Target query is not work")
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
assertThat(target.getAssignedDistributionSet()).as("Assigned ds size is wrong").isEqualTo(set2);
|
||||
assertThat(target.getTargetInfo().getInstalledDistributionSet().getId()).as("Installed ds is wrong")
|
||||
.isEqualTo(set.getId());
|
||||
|
||||
}
|
||||
|
||||
@@ -373,8 +386,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
assertThat(firstSaved.spliterator().getExactSizeIfKnown() - nr2Del).as("Size of splited list")
|
||||
.isEqualTo(allFound.spliterator().getExactSizeIfKnown());
|
||||
|
||||
// verify that all undeleted are still found
|
||||
assertThat(allFound).doesNotContain(deletedTargets);
|
||||
assertThat(allFound).as("Not all undeleted found").doesNotContain(deletedTargets);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -404,7 +416,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
targetInfo = targetInfoRepository.save(targetInfo);
|
||||
}
|
||||
final Query qry = entityManager.createNativeQuery("select * from sp_target_attributes ta");
|
||||
final List result = qry.getResultList();
|
||||
final List<?> result = qry.getResultList();
|
||||
|
||||
assertThat(attribs.size() * ts.spliterator().getExactSizeIfKnown()).as("Amount of all target attributes")
|
||||
.isEqualTo(result.size());
|
||||
@@ -467,7 +479,8 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
final Target tNoAttrib = targetManagement.findTargetByControllerID(tNoAttribl.getControllerId());
|
||||
|
||||
if (tNoAttrib.getControllerId().equals(target.getControllerId())) {
|
||||
assertThat(target.getTargetInfo().getControllerAttributes()).isEmpty();
|
||||
assertThat(target.getTargetInfo().getControllerAttributes())
|
||||
.as("Controller attributes should be empty").isEmpty();
|
||||
continue restTarget_;
|
||||
}
|
||||
}
|
||||
@@ -479,7 +492,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
if (tNoAttrib.getControllerId().equals(target.getControllerId())) {
|
||||
assertThat(target.getTargetInfo().getControllerAttributes().keySet().toArray())
|
||||
.doesNotContain(attribs2Del.toArray());
|
||||
.as("Controller attributes are wrong").doesNotContain(attribs2Del.toArray());
|
||||
continue restTarget_;
|
||||
}
|
||||
}
|
||||
@@ -504,12 +517,14 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
t2 = targetManagement.createTarget(t2);
|
||||
|
||||
t1 = targetManagement.findTargetByControllerID(t1.getControllerId());
|
||||
assertThat(t1.getTags()).hasSize(noT1Tags).containsAll(t1Tags);
|
||||
assertThat(t1.getTags()).hasSize(noT1Tags).doesNotContain(Iterables.toArray(t2Tags, TargetTag.class));
|
||||
assertThat(t1.getTags()).as("Tag size is wrong").hasSize(noT1Tags).containsAll(t1Tags);
|
||||
assertThat(t1.getTags()).as("Tag size is wrong").hasSize(noT1Tags)
|
||||
.doesNotContain(Iterables.toArray(t2Tags, TargetTag.class));
|
||||
|
||||
t2 = targetManagement.findTargetByControllerID(t2.getControllerId());
|
||||
assertThat(t2.getTags()).hasSize(noT2Tags).containsAll(t2Tags);
|
||||
assertThat(t2.getTags()).hasSize(noT2Tags).doesNotContain(Iterables.toArray(t1Tags, TargetTag.class));
|
||||
assertThat(t2.getTags()).as("Tag size is wrong").hasSize(noT2Tags).containsAll(t2Tags);
|
||||
assertThat(t2.getTags()).as("Tag size is wrong").hasSize(noT2Tags)
|
||||
.doesNotContain(Iterables.toArray(t1Tags, TargetTag.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -531,7 +546,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
final TargetTag tagA = tagManagement.createTargetTag(new TargetTag("A"));
|
||||
final TargetTag tagB = tagManagement.createTargetTag(new TargetTag("B"));
|
||||
final TargetTag tagC = tagManagement.createTargetTag(new TargetTag("C"));
|
||||
final TargetTag tagX = tagManagement.createTargetTag(new TargetTag("X"));
|
||||
tagManagement.createTargetTag(new TargetTag("X"));
|
||||
|
||||
// doing different assignments
|
||||
targetManagement.toggleTagAssignment(tagATargets, tagA);
|
||||
@@ -545,7 +560,8 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
targetManagement.toggleTagAssignment(tagABCTargets, tagB);
|
||||
targetManagement.toggleTagAssignment(tagABCTargets, tagC);
|
||||
|
||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "X")).isEqualTo(0);
|
||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "X"))
|
||||
.as("Target count is wrong").isEqualTo(0);
|
||||
|
||||
// search for targets with tag tagA
|
||||
final List<Target> targetWithTagA = new ArrayList<Target>();
|
||||
@@ -575,11 +591,11 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
|
||||
// check again target lists refreshed from DB
|
||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "A"))
|
||||
.isEqualTo(targetWithTagA.size());
|
||||
.as("Target count is wrong").isEqualTo(targetWithTagA.size());
|
||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "B"))
|
||||
.isEqualTo(targetWithTagB.size());
|
||||
.as("Target count is wrong").isEqualTo(targetWithTagB.size());
|
||||
assertThat(targetManagement.countTargetByFilters(null, null, null, Boolean.FALSE, "C"))
|
||||
.isEqualTo(targetWithTagC.size());
|
||||
.as("Target count is wrong").isEqualTo(targetWithTagC.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -656,14 +672,15 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
targetManagement.toggleTagAssignment(targAs, targTagA);
|
||||
|
||||
assertThat(targetManagement.findTargetsByControllerIDsWithTags(
|
||||
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList()))).hasSize(25);
|
||||
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList())))
|
||||
.as("Target count is wrong").hasSize(25);
|
||||
|
||||
// no lazy loading exception and tag correctly assigned
|
||||
assertThat(targetManagement
|
||||
.findTargetsByControllerIDsWithTags(
|
||||
targAs.stream().map(target -> target.getControllerId()).collect(Collectors.toList()))
|
||||
.stream().map(target -> target.getTags().contains(targTagA)).collect(Collectors.toList()))
|
||||
.containsOnly(true);
|
||||
.as("Tags not correctly assigned").containsOnly(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -678,7 +695,7 @@ public class TargetManagementTest extends AbstractIntegrationTest {
|
||||
final List<String> findAllTargetIds = findAllTargetIdNames.stream().map(TargetIdName::getControllerId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(findAllTargetIds).containsOnly(createdTargetIds);
|
||||
assertThat(findAllTargetIds).as("Target list has wrong content").containsOnly(createdTargetIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,7 +26,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter actions")
|
||||
public class RSQLActionFieldsTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter distribution set")
|
||||
public class RSQLDistributionSetFieldTest extends AbstractIntegrationTest {
|
||||
|
||||
@@ -98,7 +98,7 @@ public class RSQLDistributionSetFieldTest extends AbstractIntegrationTest {
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==true", 4);
|
||||
try {
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==noExist*", 0);
|
||||
fail();
|
||||
fail("Expected RSQLParameterSyntaxException");
|
||||
} catch (final RSQLParameterSyntaxException e) {
|
||||
}
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=in=(true)", 4);
|
||||
@@ -140,7 +140,7 @@ public class RSQLDistributionSetFieldTest extends AbstractIntegrationTest {
|
||||
final Page<DistributionSet> find = distributionSetManagement.findDistributionSetsAll(
|
||||
RSQLUtility.parse(rsqlParam, DistributionSetFields.class), new PageRequest(0, 100), false);
|
||||
final long countAll = find.getTotalElements();
|
||||
assertThat(find).isNotNull();
|
||||
assertThat(countAll).isEqualTo(excpectedEntity);
|
||||
assertThat(find).as("Founded entity is should not be null").isNotNull();
|
||||
assertThat(countAll).as("Founded entity size is wrong").isEqualTo(excpectedEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter distribution set metadata")
|
||||
public class RSQLDistributionSetMetadataFieldsTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter rollout group")
|
||||
public class RSQLRolloutGroupFields extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter software module")
|
||||
public class RSQLSoftwareModuleFieldTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter software module metadata")
|
||||
public class RSQLSoftwareModuleMetadataFieldsTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter software module test type")
|
||||
public class RSQLSoftwareModuleTypeFieldsTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter target and distribution set tags")
|
||||
public class RSQLTagFieldsTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL filter target")
|
||||
public class RSQLTargetFieldTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@Features("Component Tests - RSQL filtering")
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("RSQL search utility")
|
||||
// TODO: fully document tests -> @Description for long text and reasonable
|
||||
// method name as short text
|
||||
|
||||
@@ -10,8 +10,6 @@ package org.eclipse.hawkbit.tenancy;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.eclipse.hawkbit.AbstractIntegrationTest;
|
||||
import org.eclipse.hawkbit.WithSpringAuthorityRule;
|
||||
import org.eclipse.hawkbit.WithUser;
|
||||
@@ -31,9 +29,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
* CRUD-Operations are tenant aware and cannot access or delete entities not
|
||||
* belonging to the current tenant.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Repository")
|
||||
@Stories("Multi Tenancy")
|
||||
@@ -97,13 +92,9 @@ public class MultiTenancyEntityTest extends AbstractIntegrationTest {
|
||||
// check that the cache is not getting in the way, i.e. "bumlux" results
|
||||
// in bumlux and not
|
||||
// mytenant
|
||||
assertThat(
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", "bumlux"), new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return systemManagement.getTenantMetadata().getTenant().toUpperCase();
|
||||
}
|
||||
})).isEqualTo("bumlux".toUpperCase());
|
||||
assertThat(securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", "bumlux"),
|
||||
() -> systemManagement.getTenantMetadata().getTenant().toUpperCase()))
|
||||
.isEqualTo("bumlux".toUpperCase());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -154,59 +145,38 @@ public class MultiTenancyEntityTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
private Target createTargetForTenant(final String controllerId, final String tenant) throws Exception {
|
||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), new Callable<Target>() {
|
||||
@Override
|
||||
public Target call() throws Exception {
|
||||
return targetManagement.createTarget(new Target(controllerId));
|
||||
}
|
||||
});
|
||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
||||
() -> targetManagement.createTarget(new Target(controllerId)));
|
||||
}
|
||||
|
||||
private Slice<Target> findTargetsForTenant(final String tenant) throws Exception {
|
||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
||||
new Callable<Slice<Target>>() {
|
||||
@Override
|
||||
public Slice<Target> call() throws Exception {
|
||||
return targetManagement.findTargetsAll(pageReq);
|
||||
}
|
||||
});
|
||||
() -> targetManagement.findTargetsAll(pageReq));
|
||||
}
|
||||
|
||||
private void deleteTargetsForTenant(final String tenant, final Long... targetIds) throws Exception {
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
targetManagement.deleteTargets(targetIds);
|
||||
return null;
|
||||
}
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), () -> {
|
||||
targetManagement.deleteTargets(targetIds);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private DistributionSet createDistributionSetForTenant(final String name, final String version, final String tenant)
|
||||
throws Exception {
|
||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
||||
new Callable<DistributionSet>() {
|
||||
@Override
|
||||
public DistributionSet call() throws Exception {
|
||||
final DistributionSet ds = new DistributionSet();
|
||||
ds.setName(name);
|
||||
ds.setTenant(tenant);
|
||||
ds.setVersion(version);
|
||||
ds.setType(distributionSetManagement
|
||||
.createDistributionSetType(new DistributionSetType("typetest", "test", "foobar")));
|
||||
return distributionSetManagement.createDistributionSet(ds);
|
||||
}
|
||||
});
|
||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant), () -> {
|
||||
final DistributionSet ds = new DistributionSet();
|
||||
ds.setName(name);
|
||||
ds.setTenant(tenant);
|
||||
ds.setVersion(version);
|
||||
ds.setType(distributionSetManagement
|
||||
.createDistributionSetType(new DistributionSetType("typetest", "test", "foobar")));
|
||||
return distributionSetManagement.createDistributionSet(ds);
|
||||
});
|
||||
}
|
||||
|
||||
private Page<DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
|
||||
return securityRule.runAs(WithSpringAuthorityRule.withUserAndTenant("user", tenant),
|
||||
new Callable<Page<DistributionSet>>() {
|
||||
@Override
|
||||
public Page<DistributionSet> call() throws Exception {
|
||||
return distributionSetManagement.findDistributionSetsAll(pageReq, false, false);
|
||||
}
|
||||
});
|
||||
() -> distributionSetManagement.findDistributionSetsAll(pageReq, false, false));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value}
|
||||
spring.data.mongodb.port=28017
|
||||
|
||||
hawkbit.server.controller.security.authentication.header.enabled=true
|
||||
hawkbit.server.controller.security.authentication.gatewaytoken.name=TestToken
|
||||
hawkbit.server.ddi.security.authentication.header.enabled=true
|
||||
hawkbit.server.ddi.security.authentication.gatewaytoken.name=TestToken
|
||||
|
||||
hawkbit.server.artifact.repo.upload.maxFileSize=5MB
|
||||
|
||||
@@ -30,11 +30,6 @@ flyway.initOnMigrate=true
|
||||
flyway.sqlMigrationSuffix=${spring.jpa.database}.sql
|
||||
#spring.jpa.show-sql=true
|
||||
|
||||
# SP Controller configuration
|
||||
# DDI configuration
|
||||
hawkbit.controller.pollingTime=00:01:00
|
||||
hawkbit.controller.pollingOverdueTime=00:01:00
|
||||
|
||||
## Configuration for RabbitMQ integration
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter
|
||||
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
hawkbit.controller.pollingOverdueTime=00:01:00
|
||||
@@ -25,13 +25,11 @@ import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.LocalArtifact;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
|
||||
@@ -55,7 +53,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(ControllerConstants.ARTIFACTS_V1_REQUEST_MAPPING)
|
||||
public class ArtifactStoreController implements EnvironmentAware {
|
||||
public class ArtifactStoreController {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ArtifactStoreController.class);
|
||||
|
||||
@Autowired
|
||||
@@ -67,14 +65,8 @@ public class ArtifactStoreController implements EnvironmentAware {
|
||||
@Autowired
|
||||
private CacheWriteNotify cacheWriteNotify;
|
||||
|
||||
private static final String SP_SERVER_CONFIG_PREFIX = "hawkbit.server.";
|
||||
private RelaxedPropertyResolver environment;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
this.environment = new RelaxedPropertyResolver(environment, SP_SERVER_CONFIG_PREFIX);
|
||||
|
||||
}
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* Handles GET {@link Artifact} download request. This could be full or
|
||||
@@ -138,8 +130,8 @@ public class ArtifactStoreController implements EnvironmentAware {
|
||||
|
||||
private Action checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid,
|
||||
final LocalArtifact artifact) {
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(
|
||||
request, environment.getProperty("security.rp.remote_ip_header", String.class, "X-Forwarded-For")));
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
final Action action = controllerManagement
|
||||
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), artifact.getSoftwareModule());
|
||||
|
||||
@@ -41,15 +41,13 @@ 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.rest.resource.helper.RestResourceConversionHelper;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -74,7 +72,7 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(ControllerConstants.BASE_V1_REQUEST_MAPPING)
|
||||
public class RootController implements EnvironmentAware {
|
||||
public class RootController {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(RootController.class);
|
||||
private static final String GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET = "given action ({}) is not assigned to given target ({}).";
|
||||
@@ -99,16 +97,8 @@ public class RootController implements EnvironmentAware {
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
private String requestHeader;
|
||||
|
||||
@Override
|
||||
public void setEnvironment(final Environment environment) {
|
||||
final RelaxedPropertyResolver relaxedPropertyResolver = new RelaxedPropertyResolver(environment,
|
||||
SP_SERVER_CONFIG_PREFIX);
|
||||
|
||||
requestHeader = relaxedPropertyResolver.getProperty("security.rp.remote_ip_header", String.class,
|
||||
"X-Forwarded-For");
|
||||
}
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
/**
|
||||
* Returns all artifacts of a given software module and target.
|
||||
@@ -155,12 +145,13 @@ public class RootController implements EnvironmentAware {
|
||||
LOG.debug("getControllerBase({})", targetid);
|
||||
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
if (target.getTargetInfo().getUpdateStatus() == TargetUpdateStatus.UNKNOWN) {
|
||||
LOG.debug("target with {} extsisted but was in status UNKNOWN -> REGISTERED)", targetid);
|
||||
controllerManagement.updateTargetStatus(target.getTargetInfo(), TargetUpdateStatus.REGISTERED,
|
||||
System.currentTimeMillis(), IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
System.currentTimeMillis(),
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
}
|
||||
|
||||
return new ResponseEntity<>(
|
||||
@@ -195,7 +186,7 @@ public class RootController implements EnvironmentAware {
|
||||
ResponseEntity<Void> result;
|
||||
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
|
||||
|
||||
if (checkModule(fileName, module)) {
|
||||
@@ -265,7 +256,8 @@ public class RootController implements EnvironmentAware {
|
||||
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable final String targetid,
|
||||
@PathVariable final Long softwareModuleId, @PathVariable final String fileName,
|
||||
final HttpServletResponse response, final HttpServletRequest request) {
|
||||
controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
|
||||
|
||||
@@ -311,7 +303,7 @@ public class RootController implements EnvironmentAware {
|
||||
LOG.debug("getControllerBasedeploymentAction({},{})", targetid, resource);
|
||||
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
@@ -362,7 +354,7 @@ public class RootController implements EnvironmentAware {
|
||||
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", targetid, actionId, feedback);
|
||||
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
if (!actionId.equals(feedback.getId())) {
|
||||
LOG.warn(
|
||||
@@ -435,8 +427,6 @@ public class RootController implements EnvironmentAware {
|
||||
LOG.debug("Controller reported intermediate status (actionid: {}, targetid: {}) as we got {} report.", actionid,
|
||||
targetid, feedback.getStatus().getExecution());
|
||||
actionStatus.setStatus(Status.RUNNING);
|
||||
// MECS-400: we should not use the unstructed message list for
|
||||
// the server comment on the status.
|
||||
actionStatus.addMessage("Controller reported: " + feedback.getStatus().getExecution());
|
||||
}
|
||||
|
||||
@@ -469,7 +459,8 @@ public class RootController implements EnvironmentAware {
|
||||
+ ControllerConstants.CONFIG_DATA_ACTION, method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final ConfigData configData,
|
||||
@PathVariable final String targetid, final HttpServletRequest request) {
|
||||
controllerManagement.updateLastTargetQuery(targetid, IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
controllerManagement.updateControllerAttributes(targetid, configData.getData());
|
||||
|
||||
@@ -495,7 +486,7 @@ public class RootController implements EnvironmentAware {
|
||||
LOG.debug("getControllerCancelAction({})", targetid);
|
||||
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
@@ -542,7 +533,7 @@ public class RootController implements EnvironmentAware {
|
||||
LOG.debug("provideCancelActionFeedback for target [{}]: {}", targetid, feedback);
|
||||
|
||||
final Target target = controllerManagement.updateLastTargetQuery(targetid,
|
||||
IpUtil.getClientIpFromRequest(request, requestHeader));
|
||||
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
|
||||
|
||||
if (!actionId.equals(feedback.getId())) {
|
||||
LOG.warn(
|
||||
|
||||
@@ -23,11 +23,6 @@ import org.springframework.data.domain.Sort.Direction;
|
||||
/**
|
||||
* Utility class for for paged body generation.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public final class PagingUtility {
|
||||
/*
|
||||
@@ -90,8 +85,9 @@ public final class PagingUtility {
|
||||
if (sortParam != null) {
|
||||
sorting = new Sort(SortUtility.parse(ActionFields.class, sortParam));
|
||||
} else {
|
||||
// default sort
|
||||
sorting = new Sort(Direction.ASC, ActionFields.ID.getFieldName());
|
||||
// default sort is DESC in case of action to match behavior
|
||||
// of management UI (last entry on top)
|
||||
sorting = new Sort(Direction.DESC, ActionFields.ID.getFieldName());
|
||||
}
|
||||
return sorting;
|
||||
}
|
||||
@@ -101,8 +97,9 @@ public final class PagingUtility {
|
||||
if (sortParam != null) {
|
||||
sorting = new Sort(SortUtility.parse(ActionStatusFields.class, sortParam));
|
||||
} else {
|
||||
// default sort
|
||||
sorting = new Sort(Direction.ASC, ActionStatusFields.ID.getFieldName());
|
||||
// default sort is DESC in case of action status to match behavior
|
||||
// of management UI (last entry on top)
|
||||
sorting = new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName());
|
||||
}
|
||||
return sorting;
|
||||
}
|
||||
|
||||
@@ -297,8 +297,8 @@ final public class TargetMapper {
|
||||
final ActionStatusRest result = new ActionStatusRest();
|
||||
|
||||
result.setMessages(actionStatus.getMessages());
|
||||
result.setReportedAt(action.getCreatedAt());
|
||||
result.setStatusId(action.getId());
|
||||
result.setReportedAt(actionStatus.getCreatedAt());
|
||||
result.setStatusId(actionStatus.getId());
|
||||
result.setType(getNameOfActionStatusType(actionStatus.getStatus()));
|
||||
|
||||
return result;
|
||||
|
||||
@@ -235,7 +235,7 @@ public class TargetResource implements TargetRestApi {
|
||||
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
|
||||
final Sort sorting = PagingUtility.sanitizeActionStatusSortParam(sortParam);
|
||||
|
||||
final Page<ActionStatus> statusList = this.deploymentManagement.findActionStatusMessagesByActionInDescOrder(
|
||||
final Page<ActionStatus> statusList = this.deploymentManagement.findActionStatusByAction(
|
||||
new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting), action, true);
|
||||
|
||||
return new ResponseEntity<>(
|
||||
|
||||
@@ -60,7 +60,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
*/
|
||||
|
||||
@ActiveProfiles({ "im", "test" })
|
||||
@Features("Component Tests - Controller RESTful API")
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Artifact Download Resource")
|
||||
public class ArtifactDownloadTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@ActiveProfiles({ "im", "test" })
|
||||
@Features("Component Tests - Controller RESTful API")
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Cancel Action Resource")
|
||||
public class CancelActionTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@ActiveProfiles({ "im", "test" })
|
||||
@Features("Component Tests - Controller RESTful API")
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Config Data Resource")
|
||||
public class ConfigDataTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@ActiveProfiles({ "im", "test" })
|
||||
@Features("Component Tests - Controller RESTful API")
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Deployment Action Resource")
|
||||
public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
|
||||
@@ -45,13 +45,11 @@ import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@ActiveProfiles({ "im", "test" })
|
||||
@Features("Component Tests - Controller RESTful API")
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Root Poll Resource")
|
||||
// TODO: fully document tests -> @Description for long text and reasonable
|
||||
// method name as short text
|
||||
public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
@Test()
|
||||
@Test
|
||||
@Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists but can be created if the tenant exists.")
|
||||
@WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = "ROLE_CONTROLLER", autoCreateTenant = false)
|
||||
public void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception {
|
||||
@@ -73,6 +71,7 @@ public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target poll request does not change audit data on the entity.")
|
||||
@WithUser(principal = "knownPrincipal", authorities = { SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET,
|
||||
SpPermission.CREATE_TARGET })
|
||||
public void targetPollDoesNotModifyAuditData() throws Exception {
|
||||
@@ -104,11 +103,13 @@ public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that server returns a not found response in case of empty controlloer ID.")
|
||||
public void rootRsWithoutId() throws Exception {
|
||||
mvc.perform(get("/controller/v1/")).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the system creates a new target in plug and play manner, i.e. target is authenticated but does not exist yet.")
|
||||
public void rootRsPlugAndPlay() throws Exception {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
@@ -133,6 +134,7 @@ public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that etag check results in not modified response if provided etag by client is identical to entity in repository.")
|
||||
public void rootRsNotModified() throws Exception {
|
||||
final String etag = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -197,6 +199,8 @@ public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the target state machine of a precomissioned target switches from "
|
||||
+ "UNKNOWN to REGISTERED when the target polls for the first time.")
|
||||
public void rootRsPrecommissioned() throws Exception {
|
||||
final Target target = new Target("4711");
|
||||
targetManagement.createTarget(target);
|
||||
@@ -219,6 +223,7 @@ public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the source IP address of the polling target is correctly stored in repository")
|
||||
public void rootRsPlugAndPlayIpAddress() throws Exception {
|
||||
// test
|
||||
final String knownControllerId1 = "0815";
|
||||
|
||||
@@ -47,7 +47,6 @@ import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.annotation.Description;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -59,15 +58,8 @@ import com.jayway.jsonpath.JsonPath;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Management RESTful API")
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Distribution Set Resource")
|
||||
// TODO: fully document tests -> @Description for long text and reasonable
|
||||
// method name as short text
|
||||
public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@@ -235,6 +227,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that multi target assignment through API is reflected by the repository.")
|
||||
public void assignMultipleTargetsToDistributionSet() throws Exception {
|
||||
// prepare distribution set
|
||||
final Set<DistributionSet> createDistributionSetsAlphabetical = createDistributionSetsAlphabetical(1);
|
||||
@@ -255,9 +248,13 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.assigned", equalTo(knownTargetIds.length - 1)))
|
||||
.andExpect(jsonPath("$.alreadyAssigned", equalTo(1)))
|
||||
.andExpect(jsonPath("$.total", equalTo(knownTargetIds.length)));
|
||||
|
||||
assertThat(targetManagement.findTargetByAssignedDistributionSet(createdDs.getId(), pageReq).getContent())
|
||||
.as("Five targets in repository have DS assigned").hasSize(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that assigned targets of DS are returned as reflected by the repository.")
|
||||
public void getAssignedTargetsOfDistributionSet() throws Exception {
|
||||
// prepare distribution set
|
||||
final String knownTargetId = "knownTargetId1";
|
||||
@@ -273,6 +270,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that assigned targets of DS are returned as persisted in the repository.")
|
||||
public void getAssignedTargetsOfDistributionSetIsEmpty() throws Exception {
|
||||
final Set<DistributionSet> createDistributionSetsAlphabetical = createDistributionSetsAlphabetical(1);
|
||||
final DistributionSet createdDs = createDistributionSetsAlphabetical.iterator().next();
|
||||
@@ -283,6 +281,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that installed targets of DS are returned as persisted in the repository.")
|
||||
public void getInstalledTargetsOfDistributionSet() throws Exception {
|
||||
// prepare distribution set
|
||||
final String knownTargetId = "knownTargetId1";
|
||||
@@ -305,46 +304,50 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that DS in repository are listed with proper paging properties.")
|
||||
public void getDistributionSetsWithoutAddtionalRequestParameters() throws Exception {
|
||||
final int modules = 5;
|
||||
createDistributionSetsAlphabetical(modules);
|
||||
final int sets = 5;
|
||||
createDistributionSetsAlphabetical(sets);
|
||||
mvc.perform(get(RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(modules)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(modules)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(modules)));
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(sets)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(sets)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(sets)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that DS in repository are listed with proper paging results with paging limit parameter.")
|
||||
public void getDistributionSetsWithPagingLimitRequestParameter() throws Exception {
|
||||
final int modules = 5;
|
||||
final int sets = 5;
|
||||
final int limitSize = 1;
|
||||
createDistributionSetsAlphabetical(modules);
|
||||
createDistributionSetsAlphabetical(sets);
|
||||
mvc.perform(get(RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
|
||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(modules)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(sets)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that DS in repository are listed with proper paging results with paging limit and offset parameter.")
|
||||
public void getDistributionSetsWithPagingLimitAndOffsetRequestParameter() throws Exception {
|
||||
final int modules = 5;
|
||||
final int sets = 5;
|
||||
final int offsetParam = 2;
|
||||
final int expectedSize = modules - offsetParam;
|
||||
createDistributionSetsAlphabetical(modules);
|
||||
final int expectedSize = sets - offsetParam;
|
||||
createDistributionSetsAlphabetical(sets);
|
||||
mvc.perform(get(RestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
|
||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(offsetParam))
|
||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(modules)))
|
||||
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(sets)))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(modules)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_TOTAL, equalTo(sets)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_SIZE, equalTo(expectedSize)))
|
||||
.andExpect(jsonPath(TargetResourceTest.JSON_PATH_PAGED_LIST_CONTENT, hasSize(expectedSize)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Ensures that multiple DS requested are listed with expected payload.")
|
||||
public void getDistributionSets() throws Exception {
|
||||
// prepare test data
|
||||
assertThat(distributionSetManagement.findDistributionSetsAll(pageReq, false, true)).hasSize(0);
|
||||
@@ -389,6 +392,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Ensures that single DS requested by ID is listed with expected payload.")
|
||||
public void getDistributionSet() throws Exception {
|
||||
final DistributionSet set = createTestDistributionSet(softwareManagement, distributionSetManagement);
|
||||
|
||||
@@ -420,6 +424,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Ensures that multipe DS posted to API are created in the repository.")
|
||||
public void createDistributionSets() throws JSONException, Exception {
|
||||
assertThat(distributionSetManagement.findDistributionSetsAll(pageReq, false, true)).hasSize(0);
|
||||
|
||||
@@ -534,7 +539,8 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteUnassignedistributionSet() throws Exception {
|
||||
@Description("Ensures that DS deletion request to API is reflected by the repository.")
|
||||
public void deleteUnassignedistributionSet() throws Exception {
|
||||
// prepare test data
|
||||
assertThat(distributionSetManagement.findDistributionSetsAll(pageReq, false, true)).hasSize(0);
|
||||
|
||||
@@ -553,7 +559,8 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteAssignedDistributionSet() throws Exception {
|
||||
@Description("Ensures that assigned DS deletion request to API is reflected by the repository by means of deleted flag set.")
|
||||
public void deleteAssignedDistributionSet() throws Exception {
|
||||
// prepare test data
|
||||
assertThat(distributionSetManagement.findDistributionSetsAll(pageReq, false, true)).hasSize(0);
|
||||
|
||||
@@ -574,6 +581,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that DS property update request to API is reflected by the repository.")
|
||||
public void updateDistributionSet() throws Exception {
|
||||
|
||||
// prepare test data
|
||||
@@ -601,6 +609,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the server reacts properly to invalid requests (URI, Media Type, Methods) with correct reponses.")
|
||||
public void invalidRequestsOnDistributionSetsResource() throws Exception {
|
||||
final DistributionSet set = TestDataUtil.generateDistributionSet("one", softwareManagement,
|
||||
distributionSetManagement);
|
||||
@@ -642,6 +651,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the metadata creation through API is reflected by the repository.")
|
||||
public void createMetadata() throws Exception {
|
||||
final DistributionSet testDS = TestDataUtil.generateDistributionSet("one", softwareManagement,
|
||||
distributionSetManagement);
|
||||
@@ -674,6 +684,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata update through API is reflected by the repository.")
|
||||
public void updateMetadata() throws Exception {
|
||||
// prepare and create metadata for update
|
||||
final String knownKey = "knownKey";
|
||||
@@ -700,6 +711,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry deletion through API is reflected by the repository.")
|
||||
public void deleteMetadata() throws Exception {
|
||||
// prepare and create metadata for deletion
|
||||
final String knownKey = "knownKey";
|
||||
@@ -722,6 +734,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry selection through API reflectes the repository content.")
|
||||
public void getSingleMetadata() throws Exception {
|
||||
// prepare and create metadata
|
||||
final String knownKey = "knownKey";
|
||||
@@ -737,6 +750,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a metadata entry paged list selection through API reflectes the repository content.")
|
||||
public void getPagedListofMetadata() throws Exception {
|
||||
|
||||
final int totalMetadata = 10;
|
||||
@@ -760,6 +774,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a DS search with query parameters returns the expected result.")
|
||||
public void searchDistributionSetRsql() throws Exception {
|
||||
final String dsSuffix = "test";
|
||||
final int amount = 10;
|
||||
@@ -776,11 +791,13 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
@Description("Ensures that a DS search with complete==true parameter returns only DS that are actually completely filled with mandatory modules.")
|
||||
public void filterDistributionSetComplete() throws Exception {
|
||||
final int amount = 10;
|
||||
TestDataUtil.generateDistributionSets(amount, softwareManagement, distributionSetManagement);
|
||||
distributionSetManagement.createDistributionSet(new DistributionSet("incomplete", "2", "incomplete",
|
||||
distributionSetManagement.findDistributionSetTypeByKey("ecl_os"), null));
|
||||
|
||||
final String rsqlFindLikeDs1OrDs2 = "complete==" + Boolean.TRUE;
|
||||
|
||||
@@ -790,6 +807,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a DS assigned target search with controllerId==1 parameter returns only the target with the given ID.")
|
||||
public void searchDistributionSetAssignedTargetsRsql() throws Exception {
|
||||
// prepare distribution set
|
||||
final Set<DistributionSet> createDistributionSetsAlphabetical = createDistributionSetsAlphabetical(1);
|
||||
@@ -815,6 +833,7 @@ public class DistributionSetResourceTest extends AbstractIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a DS metadata filtered query with value==knownValue1 parameter returns only the metadata entries with that value.")
|
||||
public void searchDistributionSetMetadataRsql() throws Exception {
|
||||
final int totalMetadata = 10;
|
||||
final String knownKeyPrefix = "knownKey";
|
||||
|
||||
@@ -46,11 +46,8 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
/**
|
||||
* Test for {@link DistributionSetTypeResource}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Management RESTful API")
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Distribution Set Type Resource")
|
||||
public class DistributionSetTypeResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
|
||||
@@ -30,11 +30,7 @@ import org.springframework.context.annotation.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests- Download Restful API")
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Download Resource")
|
||||
public class DownloadResourceTest extends AbstractIntegrationTestWithMongoDB {
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
/**
|
||||
* Tests for covering the {@link RolloutResource}.
|
||||
*/
|
||||
@Features("Component Tests - Management RESTful API")
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Rollout Resource")
|
||||
public class RolloutResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
@@ -99,7 +99,7 @@ public class RolloutResourceTest extends AbstractIntegrationTest {
|
||||
.andReturn();
|
||||
}
|
||||
|
||||
@Description("TODO")
|
||||
@Description("Ensures that the repository refuses to create rollout without a defined target filter set.")
|
||||
public void missingTargetFilterQueryInRollout() throws Exception {
|
||||
|
||||
final String targetFilterQuery = null;
|
||||
@@ -435,7 +435,6 @@ public class RolloutResourceTest extends AbstractIntegrationTest {
|
||||
.andExpect(jsonPath("$content", hasSize(5))).andExpect(jsonPath("$total", equalTo(5)));
|
||||
}
|
||||
|
||||
// TODO
|
||||
@Test
|
||||
@Description("Start the rollout in async mode")
|
||||
public void startingRolloutSwitchesIntoRunningStateAsync() throws Exception {
|
||||
@@ -528,7 +527,6 @@ public class RolloutResourceTest extends AbstractIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
// TODO copied code from sp-bic-test
|
||||
protected <T> T doWithTimeout(final Callable<T> callable, final SuccessCondition<T> successCondition,
|
||||
final long timeout, final long pollInterval) throws Exception // NOPMD
|
||||
{
|
||||
|
||||
@@ -23,13 +23,16 @@ import org.junit.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Tests {@link SoftwareModuleResource} in case of missing MongoDB connection.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Download Resource")
|
||||
public class SMRessourceMisingMongoDbConnectionTest extends AbstractIntegrationTest {
|
||||
|
||||
@BeforeClass
|
||||
@@ -40,7 +43,8 @@ public class SMRessourceMisingMongoDbConnectionTest extends AbstractIntegrationT
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMissingMongoDbConnection() throws Exception {
|
||||
@Description("Ensures that the correct error code is returned in case MongoDB unavailable.")
|
||||
public void missingMongoDbConnectionResultsInErrorAtUpload() throws Exception {
|
||||
|
||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||
assertThat(artifactRepository.findAll()).hasSize(0);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user