Feature horizontal scalability (#305)
Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
committed by
Kai Zimmermann
parent
07cb62a3dd
commit
866bc72114
@@ -63,7 +63,6 @@ $ java -jar ./examples/hawkbit-example-mgmt-simulator/target/hawkbit-example-mgm
|
||||
* `examples` : hawkBit examples
|
||||
* `hawkbit-artifact-repository-mongo` : Artifact repository implementation to mongoDB.
|
||||
* `hawkbit-autoconfigure` : Spring-boot auto-configuration.
|
||||
* `hawkbit-cache-redis` : Spring cache manager configuration and implementation with redis, distributed cache and distributed events.
|
||||
* `hawkbit-core` : Core elements for internal interfaces and utility classes.
|
||||
* `hawkbit-ddi-api` : The hawkBit DDI API.
|
||||
* `hawkbit-ddi-dl-api` : The hawkBit DDI Download API.
|
||||
|
||||
@@ -8,5 +8,4 @@ Example projects that show how _hawkBit_ can be used to create, run or access an
|
||||
- `hawkbit-example-core-feign-client` : Core resources for the client examples.
|
||||
- `hawkbit-example-ddi-feign-client` : Example _hawkBit_ DDI client based on the _hawkBit_ DDI API.
|
||||
- `hawkbit-example-mgmt-feign-client` : Example _hawkBit_ Management client based on the _hawkBit_ Management API
|
||||
- `hawkbit-example-mgmt-simulator` : Example client simulation for the _hawkBit_ Management API based on Spring Boot and the hawkbit-example-mgmt-feign-client.
|
||||
|
||||
- `hawkbit-example-mgmt-simulator` : Example client simulation for the _hawkBit_ Management API based on Spring Boot and the hawkbit-example-mgmt-feign-client.
|
||||
@@ -93,16 +93,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
|
||||
@@ -8,14 +8,10 @@ package org.eclipse.hawkbit.app;
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.eclipse.hawkbit.ui.HawkbitUI;
|
||||
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy;
|
||||
import org.eclipse.hawkbit.ui.push.UIEventProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.eclipse.hawkbit.ui.push.EventPushStrategy;
|
||||
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.vaadin.annotations.Push;
|
||||
import com.vaadin.annotations.Theme;
|
||||
import com.vaadin.annotations.Title;
|
||||
@@ -39,9 +35,15 @@ public class MyUI extends HawkbitUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
public MyUI(final ScheduledExecutorService executorService, final EventBus systemEventBus,
|
||||
final org.vaadin.spring.events.EventBus.SessionEventBus eventBus, final UIEventProvider provider) {
|
||||
super(new DelayedEventBusPushStrategy(executorService, eventBus, systemEventBus, provider));
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param pushStrategy
|
||||
* the push strategy
|
||||
* @param eventBus
|
||||
* the event bus
|
||||
*/
|
||||
public MyUI(final EventPushStrategy pushStrategy, final SessionEventBus eventBus) {
|
||||
super(pushStrategy, eventBus);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,11 +105,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -12,9 +12,6 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
|
||||
/**
|
||||
* Event description which indicates the initialization of an update.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
*/
|
||||
public class InitUpdate {
|
||||
|
||||
|
||||
@@ -13,10 +13,7 @@ import java.util.Collection;
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
|
||||
/**
|
||||
* Event description which indicates an poll time update.
|
||||
*
|
||||
* @author Michael Hirsch
|
||||
*
|
||||
* Event description which indicates a poll time update.
|
||||
*/
|
||||
public class NextPollCounterUpdate {
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
|
||||
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
|
||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.event.InitUpdate;
|
||||
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
||||
import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
|
||||
@@ -58,9 +57,6 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
|
||||
@SuppressWarnings("squid:MaximumInheritanceDepth")
|
||||
public class SimulatorView extends VerticalLayout implements View {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final String HTML_SPAN = ";</span>";
|
||||
|
||||
private static final String NEXT_POLL_COUNTER_SEC_COL = "nextPollCounterSec";
|
||||
@@ -81,10 +77,9 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
private transient SpSenderService spSenderService;
|
||||
@Autowired
|
||||
private transient DeviceSimulatorRepository repository;
|
||||
|
||||
@Autowired
|
||||
private transient SimulatedDeviceFactory deviceFactory;
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ security.user.password=${BASIC_PASSWORD:admin}
|
||||
security.user.role=USER
|
||||
security.require-ssl=false
|
||||
security.enable-csrf=false
|
||||
security.basic.enabled=true
|
||||
security.basic.realm=DeviceSimulator
|
||||
security.basic.path= /**
|
||||
security.basic.authorize-mode=ROLE
|
||||
|
||||
@@ -12,16 +12,7 @@
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||
|
||||
<logger name="org.eclipse.hawkbit.eventbus.DeadEventListener" level="WARN" />
|
||||
<Logger name="org.springframework.boot.actuate.audit.listener.AuditListener" level="WARN" />
|
||||
|
||||
<Logger name="org.hibernate.validator.internal.util.Version" level="WARN" />
|
||||
|
||||
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN" />
|
||||
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN" />
|
||||
<Logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR" />
|
||||
|
||||
<Root level="INFO">
|
||||
<Root level="ERROR">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</Root>
|
||||
|
||||
|
||||
@@ -33,3 +33,45 @@ The Management API can be accessed via http://localhost:8080/rest/v1
|
||||
- **manifest-simple.yml** for a standalone hawkBit installation with embedded H2.
|
||||
- **manifest.yml** for a standalone hawkBit installation with embedded H2 and RabbitMQ service binding for DMF integration (note: this manifest is used for the sandbox above).
|
||||
- Run ```cf push``` against you cloud foundry environment.
|
||||
|
||||
# Enable Clustering (experimental)
|
||||
|
||||
Clustering in hawkBit is based on _Spring Cloud Bus_. It is not enabled in the example app by default.
|
||||
|
||||
Add to your `application.properties` :
|
||||
|
||||
```
|
||||
spring.cloud.bus.enabled=true
|
||||
```
|
||||
|
||||
Add to your `pom.xml` :
|
||||
|
||||
```
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Optional as well is the addition of [Protostuff](https://github.com/protostuff/protostuff) based message payload serialization for improved performance.
|
||||
|
||||
|
||||
Add to your `application.properties` :
|
||||
|
||||
```
|
||||
spring.cloud.stream.bindings.springCloudBusInput.content-type=application/binary+protostuff
|
||||
spring.cloud.stream.bindings.springCloudBusOutput.content-type=application/binary+protostuff
|
||||
```
|
||||
|
||||
Add to your `pom.xml` :
|
||||
|
||||
```
|
||||
<dependency>
|
||||
<groupId>io.protostuff</groupId>
|
||||
<artifactId>protostuff-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.protostuff</groupId>
|
||||
<artifactId>protostuff-runtime</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
||||
@@ -8,14 +8,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.app;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.eclipse.hawkbit.ui.HawkbitUI;
|
||||
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy;
|
||||
import org.eclipse.hawkbit.ui.push.UIEventProvider;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.eclipse.hawkbit.ui.push.EventPushStrategy;
|
||||
import org.vaadin.spring.events.EventBus.SessionEventBus;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.vaadin.annotations.Push;
|
||||
import com.vaadin.shared.communication.PushMode;
|
||||
import com.vaadin.shared.ui.ui.Transport;
|
||||
@@ -35,12 +31,18 @@ import com.vaadin.spring.annotation.SpringUI;
|
||||
// Vaadin.
|
||||
@SuppressWarnings({ "squid:MaximumInheritanceDepth" })
|
||||
public class MyUI extends HawkbitUI {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Autowired
|
||||
public MyUI(final ScheduledExecutorService scheduledExecutorService, final EventBus systemEventBus,
|
||||
final org.vaadin.spring.events.EventBus.SessionEventBus eventBus, final UIEventProvider provider) {
|
||||
super(new DelayedEventBusPushStrategy(scheduledExecutorService, eventBus, systemEventBus, provider));
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param pushStrategy
|
||||
* the push strategy
|
||||
* @param eventBus
|
||||
* the event bus
|
||||
*/
|
||||
public MyUI(final EventPushStrategy pushStrategy, final SessionEventBus eventBus) {
|
||||
super(pushStrategy, eventBus);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -46,7 +46,7 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -41,11 +41,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -36,12 +36,11 @@
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<!-- need to overwrite for the interface inheritance feature of feign-core -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<groupId>io.github.openfeign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<artifactId>hawkbit-examples-parent</artifactId>
|
||||
<name>hawkBit-example :: Parent</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>repo.eclipse.org</id>
|
||||
@@ -42,22 +42,4 @@
|
||||
<module>hawkbit-example-mgmt-feign-client</module>
|
||||
<module>hawkbit-example-mgmt-simulator</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-dependencies</artifactId>
|
||||
<version>Brixton.SR5</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
<version>8.16.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
@@ -26,13 +26,7 @@
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-cache-redis</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-dmf-amqp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
@@ -83,5 +77,15 @@
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.protostuff</groupId>
|
||||
<artifactId>protostuff-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.protostuff</groupId>
|
||||
<artifactId>protostuff-runtime</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -8,17 +8,21 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.autoconfigure.cache;
|
||||
|
||||
import static com.google.common.cache.CacheBuilder.newBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.guava.GuavaCacheManager;
|
||||
import org.springframework.cache.interceptor.CacheOperationInvocationContext;
|
||||
@@ -27,6 +31,8 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
||||
/**
|
||||
* A configuration for configuring the spring {@link CacheManager} for specific
|
||||
* multi-tenancy caching. The caches between tenants must not interfere each
|
||||
@@ -37,33 +43,58 @@ import org.springframework.context.annotation.Primary;
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheAutoConfiguration extends CachingConfigurerSupport {
|
||||
public class CacheAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("directCacheManager")
|
||||
private CacheManager directCacheManager;
|
||||
|
||||
/**
|
||||
* @return the default cache manager bean if none other cache manager is
|
||||
* existing.
|
||||
*/
|
||||
@Override
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Primary
|
||||
public TenancyCacheManager cacheManager() {
|
||||
return new TenantAwareCacheManager(directCacheManager(), tenantAware);
|
||||
return new TenantAwareCacheManager(directCacheManager, tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the direct cache manager to access without tenant aware check,
|
||||
* cause in sometimes it's necessary to access the cache directly
|
||||
* without having the current tenant, e.g. initial creation of
|
||||
* tenant
|
||||
* A separate configuration of the direct cache manager for the
|
||||
* {@link TenantAwareCacheManager} that it can get overridden by another
|
||||
* configuration.
|
||||
*/
|
||||
@Bean(name = "directCacheManager")
|
||||
@ConditionalOnMissingBean(name = "directCacheManager")
|
||||
public CacheManager directCacheManager() {
|
||||
return new GuavaCacheManager();
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(CacheProperties.class)
|
||||
static class DirectCacheManagerConfiguration {
|
||||
|
||||
@Autowired
|
||||
private CacheProperties cacheProperties;
|
||||
|
||||
/**
|
||||
* @return the direct cache manager to access without tenant aware
|
||||
* check, cause in sometimes it's necessary to access the cache
|
||||
* directly without having the current tenant, e.g. initial
|
||||
* creation of tenant
|
||||
*/
|
||||
@Bean(name = "directCacheManager")
|
||||
@ConditionalOnMissingBean(name = "directCacheManager")
|
||||
public CacheManager directCacheManager() {
|
||||
final GuavaCacheManager cacheManager = new GuavaCacheManager();
|
||||
|
||||
if (cacheProperties.getTtl() > 0) {
|
||||
final CacheBuilder<Object, Object> cacheBuilder = newBuilder()
|
||||
.expireAfterWrite(cacheProperties.getTtl(), cacheProperties.getTtlUnit());
|
||||
cacheManager.setCacheBuilder(cacheBuilder);
|
||||
}
|
||||
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,6 +229,11 @@ public class CacheAutoConfiguration extends CachingConfigurerSupport {
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(final Object key, final Callable<T> valueLoader) {
|
||||
return delegate.get(key, valueLoader);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
54
hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java
vendored
Normal file
54
hawkbit-autoconfigure/src/main/java/org/eclipse/hawkbit/autoconfigure/cache/CacheProperties.java
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.MILLISECONDS;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties for configuring the cache within a cluster. The TTL (time to live)
|
||||
* is used for the lifetime limit of data in caches. After lifetime the data
|
||||
* gets reloaded out of the database.
|
||||
*/
|
||||
@ConfigurationProperties("hawkbit.cache.global")
|
||||
public class CacheProperties {
|
||||
|
||||
/**
|
||||
* TTL for cached entries in millis.
|
||||
*/
|
||||
private int ttl;
|
||||
|
||||
/**
|
||||
* Initial delay in millis
|
||||
*/
|
||||
private int initialDelay;
|
||||
|
||||
public long getInitialDelay() {
|
||||
return initialDelay;
|
||||
}
|
||||
|
||||
public void setInitialDelay(final int initialDelay) {
|
||||
this.initialDelay = initialDelay;
|
||||
}
|
||||
|
||||
public int getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
public void setTtl(final int ttl) {
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
public final TimeUnit getTtlUnit() {
|
||||
return MILLISECONDS;
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.autoconfigure.cache;
|
||||
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.cache.TenancyCacheManager;
|
||||
import org.eclipse.hawkbit.cache.DefaultDownloadIdCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -20,9 +20,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
* A configuration for configuring a cache for the download id's.
|
||||
*
|
||||
* This is done by providing a named cache.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class DownloadIdCacheAutoConfiguration {
|
||||
@@ -31,16 +28,18 @@ public class DownloadIdCacheAutoConfiguration {
|
||||
private CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* Bean for the download id cache.
|
||||
* Bean for the downloadId cache that returns the DefaultDownloadIdCache.
|
||||
* The DefaultDownloadIdCache cannot be used within a cluster because the
|
||||
* downloadId cache is not shared among notes. This means, a downloadId
|
||||
* which is stored on note A for downloading an artifact can only be used
|
||||
* for downloading the artifact form node A.
|
||||
*
|
||||
* @return the cache
|
||||
* @return the DefaultDownloadIdCache
|
||||
*/
|
||||
@Bean(name = CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
public Cache downloadIdCache() {
|
||||
if (cacheManager instanceof TenancyCacheManager) {
|
||||
return ((TenancyCacheManager) cacheManager).getDirectCache(CacheConstants.DOWNLOAD_ID_CACHE);
|
||||
}
|
||||
return cacheManager.getCache(CacheConstants.DOWNLOAD_ID_CACHE);
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public DownloadIdCache downloadIdCache() {
|
||||
return new DefaultDownloadIdCache(cacheManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.cache;
|
||||
|
||||
import org.eclipse.hawkbit.cache.RedisConfiguration;
|
||||
import org.eclipse.hawkbit.cache.annotation.EnableRedis;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* A configuration for configuring the redis configuration.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(value = RedisConfiguration.class)
|
||||
@EnableRedis
|
||||
public class RedisAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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.event;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter;
|
||||
import org.eclipse.hawkbit.repository.event.remote.RemoteTenantAwareEvent;
|
||||
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.cloud.bus.ConditionalOnBusEnabled;
|
||||
import org.springframework.cloud.bus.ServiceMatcher;
|
||||
import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ApplicationEventMulticaster;
|
||||
import org.springframework.context.event.SimpleApplicationEventMulticaster;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.messaging.converter.MessageConverter;
|
||||
|
||||
import io.protostuff.ProtostuffIOUtil;
|
||||
import io.protostuff.Schema;
|
||||
|
||||
/**
|
||||
* Auto configuration for the event bus.
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@RemoteApplicationEventScan(basePackages = "org.eclipse.hawkbit.repository.event.remote")
|
||||
public class EventPublisherAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("asyncExecutor")
|
||||
private Executor executor;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
/**
|
||||
* Server internal event publisher that allows parallel event processing if
|
||||
* the event listener is marked as so.
|
||||
*
|
||||
* @return publisher bean
|
||||
*/
|
||||
@Bean(name = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)
|
||||
public ApplicationEventMulticaster applicationEventMulticaster() {
|
||||
final SimpleApplicationEventMulticaster simpleApplicationEventMulticaster = new TenantAwareApplicationEventPublisher(
|
||||
tenantAware);
|
||||
simpleApplicationEventMulticaster.setTaskExecutor(executor);
|
||||
return simpleApplicationEventMulticaster;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean for creating a singleton instance of the
|
||||
* {@link EventPublisherHolder}
|
||||
*
|
||||
* @return the singleton instance of the {@link EventPublisherHolder}
|
||||
*/
|
||||
@Bean
|
||||
public EventPublisherHolder eventBusHolder() {
|
||||
return EventPublisherHolder.getInstance();
|
||||
}
|
||||
|
||||
private static class TenantAwareApplicationEventPublisher extends SimpleApplicationEventMulticaster {
|
||||
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ServiceMatcher serviceMatcher;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenantAware
|
||||
* the tenant ware
|
||||
*/
|
||||
protected TenantAwareApplicationEventPublisher(final TenantAware tenantAware) {
|
||||
this.tenantAware = tenantAware;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was overridden that not every event has to run within a own
|
||||
* tenantAware.
|
||||
*/
|
||||
@Override
|
||||
public void multicastEvent(final ApplicationEvent event, final ResolvableType eventType) {
|
||||
if (serviceMatcher == null || !(event instanceof RemoteTenantAwareEvent)) {
|
||||
super.multicastEvent(event, eventType);
|
||||
return;
|
||||
}
|
||||
final RemoteTenantAwareEvent remoteEvent = (RemoteTenantAwareEvent) event;
|
||||
|
||||
if (serviceMatcher.isFromSelf(remoteEvent)) {
|
||||
super.multicastEvent(event, eventType);
|
||||
return;
|
||||
}
|
||||
|
||||
tenantAware.runAsTenant(remoteEvent.getTenant(), () -> {
|
||||
super.multicastEvent(event, eventType);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnBusEnabled
|
||||
@ConditionalOnClass({ Schema.class, ProtostuffIOUtil.class })
|
||||
protected static class BusProtoStuffAutoConfiguration {
|
||||
/**
|
||||
*
|
||||
* @return the protostuff io message converter
|
||||
*/
|
||||
@Bean
|
||||
public MessageConverter busProtoBufConverter() {
|
||||
return new BusProtoStuffMessageConverter();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,66 +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.eventbus;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.EventBusSubscriberProcessor;
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.EventBusHolder;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import com.google.common.eventbus.AsyncEventBus;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Auto configuration for the event bus.
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class EventBusAutoConfiguration {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("asyncExecutor")
|
||||
private Executor executor;
|
||||
|
||||
/**
|
||||
* Server internal eventBus that allows parallel event processing if the
|
||||
* subscriber is marked as so.
|
||||
*
|
||||
* @return eventbus bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EventBus eventBus() {
|
||||
return new AsyncEventBus(executor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link EventBusSubscriberProcessor} to find classes annotated
|
||||
* with {@link EventSubscriber}.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public EventBusSubscriberProcessor eventBusSubscriberProcessor() {
|
||||
return new EventBusSubscriberProcessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the singleton instance of the {@link EventBusHolder}
|
||||
*/
|
||||
@Bean
|
||||
public EventBusHolder eventBusHolder() {
|
||||
return EventBusHolder.getInstance();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,7 +10,7 @@ package org.eclipse.hawkbit.autoconfigure.repository;
|
||||
|
||||
import org.eclipse.hawkbit.EnableJpaRepository;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.jpa.rsql.VirtualPropertyResolver;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
@@ -23,7 +23,7 @@ import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter;
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
|
||||
@@ -47,12 +47,10 @@ 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.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.annotation.Order;
|
||||
@@ -436,8 +434,7 @@ public class SecurityManagedConfiguration {
|
||||
private DdiSecurityProperties ddiSecurityConfiguration;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
private Cache downloadIdCache;
|
||||
private DownloadIdCache downloadIdCache;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
@@ -9,15 +9,20 @@
|
||||
package org.eclipse.hawkbit.autoconfigure.ui;
|
||||
|
||||
import org.eclipse.hawkbit.DistributedResourceBundleMessageSource;
|
||||
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy;
|
||||
import org.eclipse.hawkbit.ui.push.EventPushStrategy;
|
||||
import org.eclipse.hawkbit.ui.push.HawkbitEventProvider;
|
||||
import org.eclipse.hawkbit.ui.push.UIEventProvider;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.vaadin.spring.annotation.EnableVaadinExtensions;
|
||||
import org.vaadin.spring.events.annotation.EnableEventBus;
|
||||
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
|
||||
|
||||
import com.vaadin.spring.annotation.UIScope;
|
||||
|
||||
/**
|
||||
* The hawkbit-ui autoconfiguration.
|
||||
*/
|
||||
@@ -48,4 +53,22 @@ public class UIAutoConfiguration {
|
||||
return new HawkbitEventProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* The UI scoped event push strategy. Session scope is necessary, that every
|
||||
* UI has an own strategy.
|
||||
*
|
||||
* @param applicationContext
|
||||
* the context to add the listener
|
||||
*
|
||||
* @return the provider bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@UIScope
|
||||
public EventPushStrategy eventPushStrategy(final ConfigurableApplicationContext applicationContext) {
|
||||
final DelayedEventBusPushStrategy delayedEventBusPushStrategy = new DelayedEventBusPushStrategy();
|
||||
applicationContext.addApplicationListener(delayedEventBusPushStrategy);
|
||||
return delayedEventBusPushStrategy;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,28 +24,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
@Configuration
|
||||
public class WebMvcAutoConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||
* #configurePathMatch
|
||||
* (org.springframework.web.servlet.config.annotation.PathMatchConfigurer)
|
||||
*/
|
||||
@Override
|
||||
public void configurePathMatch(final PathMatchConfigurer configurer) {
|
||||
configurer.setUseSuffixPatternMatch(false);
|
||||
configurer.setUseRegisteredSuffixPatternMatch(false);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.web.servlet.config.annotation.
|
||||
* WebMvcConfigurerAdapter# configureContentNegotiation
|
||||
* (org.springframework.web.servlet.config.annotation.
|
||||
* ContentNegotiationConfigurer)
|
||||
*/
|
||||
@Override
|
||||
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
|
||||
configurer.favorPathExtension(false);
|
||||
|
||||
@@ -7,9 +7,8 @@ org.eclipse.hawkbit.autoconfigure.url.PropertyHostnameResolverAutoConfiguration,
|
||||
org.eclipse.hawkbit.autoconfigure.web.WebMvcAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.DownloadIdCacheAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.eventbus.EventBusAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.event.EventPublisherAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementConfiguration
|
||||
|
||||
@@ -14,6 +14,19 @@ security.basic.realm=HawkBit
|
||||
security.user.name=admin
|
||||
security.user.password=admin
|
||||
|
||||
# Spring cloud bus and stream
|
||||
spring.cloud.bus.enabled=false
|
||||
# Disable Cloud Bus default events
|
||||
spring.cloud.bus.env.enabled=false
|
||||
spring.cloud.bus.ack.enabled=false
|
||||
spring.cloud.bus.trace.enabled=false
|
||||
spring.cloud.bus.refresh.enabled=false
|
||||
# Disable Cloud Bus endpoints
|
||||
endpoints.spring.cloud.bus.refresh.enabled=false
|
||||
endpoints.spring.cloud.bus.env.enabled=false
|
||||
# Spring cloud bus and stream END
|
||||
|
||||
|
||||
### JPA / Datasource - START
|
||||
spring.jpa.database=H2
|
||||
spring.jpa.show-sql=false
|
||||
|
||||
@@ -1,81 +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
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-cache-redis</artifactId>
|
||||
<name>hawkBit :: Redis Cache Manager</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<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 -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,118 +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.cache;
|
||||
|
||||
import org.eclipse.hawkbit.cache.eventbus.EventDistributor;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.cache.RedisCacheManager;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||
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)
|
||||
public class RedisConfiguration {
|
||||
|
||||
@Autowired
|
||||
private RedisProperties redisProperties;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
/**
|
||||
* @return the {@link EventDistributor} to distribute and consume the events
|
||||
* from Redis
|
||||
*/
|
||||
@Bean
|
||||
public EventDistributor eventDistributor() {
|
||||
return new EventDistributor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring redis cache manager.
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
public CacheManager cacheManager() {
|
||||
return new TenantAwareCacheManager(directCacheManager(), tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return bean for the direct cache manager.
|
||||
*/
|
||||
@Bean(name = "directCacheManager")
|
||||
public CacheManager directCacheManager() {
|
||||
return new RedisCacheManager(redisTemplate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the redis connection factory to create a redis connection based
|
||||
* on the {@link RedisProperties}
|
||||
*/
|
||||
@Bean
|
||||
public JedisConnectionFactory jedisConnectionFactory() {
|
||||
final JedisConnectionFactory factory = new JedisConnectionFactory();
|
||||
factory.setHostName(redisProperties.getHost());
|
||||
factory.setPort(redisProperties.getPort());
|
||||
factory.setUsePool(true);
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring {@link RedisTemplate} configured with the necessary
|
||||
* object serializers
|
||||
*/
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate() {
|
||||
final RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
redisTemplate.setConnectionFactory(jedisConnectionFactory());
|
||||
redisTemplate.setKeySerializer(new JdkSerializationRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
|
||||
redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
|
||||
return redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring-redis message listener adapter to consume messages
|
||||
* from the Redis server
|
||||
*/
|
||||
@Bean
|
||||
public MessageListenerAdapter messageListenerAdapter() {
|
||||
final MessageListenerAdapter messageListenerAdapter = new MessageListenerAdapter(eventDistributor());
|
||||
messageListenerAdapter.setSerializer(new JdkSerializationRedisSerializer());
|
||||
return messageListenerAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the spring-redis message listener container to register the
|
||||
* message listener adapter
|
||||
*/
|
||||
@Bean
|
||||
public RedisMessageListenerContainer redisContainer() {
|
||||
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
container.setConnectionFactory(jedisConnectionFactory());
|
||||
container.addMessageListener(messageListenerAdapter(), eventDistributor().getTopics());
|
||||
return container;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,60 +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.cache;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @return the host
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host
|
||||
* the host to set
|
||||
*/
|
||||
public void setHost(final String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the port
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param port
|
||||
* the port to set
|
||||
*/
|
||||
public void setPort(final int port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +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.cache.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.eclipse.hawkbit.cache.RedisConfiguration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Annotation to enable redis caching.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Import(RedisConfiguration.class)
|
||||
public @interface EnableRedis {
|
||||
|
||||
}
|
||||
@@ -1,140 +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.cache.eventbus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.eventbus.event.DistributedEvent;
|
||||
import org.eclipse.hawkbit.eventbus.event.Event;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.PatternTopic;
|
||||
import org.springframework.data.redis.listener.Topic;
|
||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* The distributor for events.
|
||||
*
|
||||
*/
|
||||
@EventSubscriber
|
||||
@Service
|
||||
public class EventDistributor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EventDistributor.class);
|
||||
/**
|
||||
* the node id to filter self published events in the redis message
|
||||
* subscriber.
|
||||
*/
|
||||
private static final String NODE_ID = UUID.randomUUID().toString();
|
||||
|
||||
private static final String DISTRIBUTION_CHANNEL_TOPIC = "com/bosch/sp/distEvent";
|
||||
private static final String SEND_DISTRIBUTION_CHANNEL = DISTRIBUTION_CHANNEL_TOPIC + "/" + NODE_ID;
|
||||
private static final String SUB_DISTRIBUTION_CHANNEL = DISTRIBUTION_CHANNEL_TOPIC + "*";
|
||||
|
||||
@Autowired(required = false)
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
/**
|
||||
* consumes all {@link DistributedEvent}s posted on the {@link EventBus} and
|
||||
* distribute them to the Redis server.
|
||||
*
|
||||
* @param event
|
||||
* the distributed event posted on the {@link EventBus}
|
||||
*/
|
||||
@Subscribe
|
||||
public void distribute(final DistributedEvent event) {
|
||||
if (redisTemplate != null) {
|
||||
if (!NODE_ID.equals(event.getNodeId())) {
|
||||
logDistributingEvent(event, SEND_DISTRIBUTION_CHANNEL);
|
||||
event.setOriginNodeId(NODE_ID);
|
||||
redisTemplate.convertAndSend(SEND_DISTRIBUTION_CHANNEL, event);
|
||||
}
|
||||
} else {
|
||||
logNotDistributingEvent(event, SEND_DISTRIBUTION_CHANNEL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* message listener callback method for the {@link MessageListenerAdapter}
|
||||
* which calls the method in case a message is received from the Redis
|
||||
* server of the type {@link DistributedEventWrapper}.
|
||||
*
|
||||
* @param event
|
||||
* the {@link DistributedEventWrapper} event which was received
|
||||
* by the Redis client
|
||||
* @param channel
|
||||
* the on which the event was received
|
||||
*/
|
||||
public void handleMessage(final DistributedEvent event, final String channel) {
|
||||
LOGGER.trace("retrieving event from redis {} on channel {}, posting to the local event bus", event, channel);
|
||||
if (!NODE_ID.equals(event.getOriginNodeId())) {
|
||||
event.setNodeId(NODE_ID);
|
||||
eventBus.post(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a collection of all topics which this Redis message listener
|
||||
* wants to subscribe
|
||||
*/
|
||||
public Collection<Topic> getTopics() {
|
||||
final List<Topic> topics = new ArrayList<>();
|
||||
topics.add(new PatternTopic(SUB_DISTRIBUTION_CHANNEL));
|
||||
return topics;
|
||||
}
|
||||
|
||||
private static void logDistributingEvent(final Event event, final String channel) {
|
||||
LOGGER.trace("distributing event {} from node {} to topic {}", event, NODE_ID, channel);
|
||||
}
|
||||
|
||||
private static void logNotDistributingEvent(final Event event, final String channel) {
|
||||
LOGGER.debug("no redis template configured, event {} will not be distributed to channel {} from node {}", event,
|
||||
channel, NODE_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* testing purposes.
|
||||
*
|
||||
* @param redisTemplate
|
||||
* the redisTemplate to set
|
||||
*/
|
||||
void setRedisTemplate(final RedisTemplate<String, Object> redisTemplate) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* testing purposes.
|
||||
*
|
||||
* @param eventBus
|
||||
* the eventBus to set
|
||||
*/
|
||||
void setEventBus(final EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nodeId
|
||||
*/
|
||||
static String getNodeId() {
|
||||
return NODE_ID;
|
||||
}
|
||||
}
|
||||
@@ -1,228 +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.cache.eventbus;
|
||||
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.EntityEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
|
||||
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.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.listener.Topic;
|
||||
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
|
||||
private RedisTemplate<String, Object> redisTemplateMock;
|
||||
|
||||
@Mock
|
||||
private EventBus eventBusMock;
|
||||
|
||||
private EventDistributor underTest;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
underTest = new EventDistributor();
|
||||
underTest.setEventBus(eventBusMock);
|
||||
underTest.setRedisTemplate(redisTemplateMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void distributeDistributedEventSendsToRedis() {
|
||||
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
underTest.distribute(event);
|
||||
|
||||
// origin node ID should be set by distributing the event
|
||||
assertThat(event.getOriginNodeId()).isNotNull();
|
||||
verify(redisTemplateMock).convertAndSend(anyString(), eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dontDistributeDistributedEventIfSameNode() {
|
||||
final String knownNodeId = EventDistributor.getNodeId();
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
event.setNodeId(knownNodeId);
|
||||
|
||||
// test
|
||||
underTest.distribute(event);
|
||||
|
||||
assertThat(event.getOriginNodeId()).isNull();
|
||||
verify(redisTemplateMock, times(0)).convertAndSend(anyString(), eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleDistributedMessageFromRedis() {
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
final String knownChannel = "someChannel";
|
||||
|
||||
underTest.handleMessage(event, knownChannel);
|
||||
|
||||
assertThat(event.getNodeId()).isEqualTo(EventDistributor.getNodeId());
|
||||
verify(eventBusMock).post(eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleDistributedMessageFilteredIfSameNodeId() {
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
final String knownChannel = "someChannel";
|
||||
event.setOriginNodeId(EventDistributor.getNodeId());
|
||||
|
||||
underTest.handleMessage(event, knownChannel);
|
||||
|
||||
assertThat(event.getNodeId()).isNull();
|
||||
verify(eventBusMock, times(0)).post(eq(event));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void subscribedTopicsContains2PatternTopics() {
|
||||
final Collection<Topic> topics = underTest.getTopics();
|
||||
assertThat(topics).hasSize(1);
|
||||
}
|
||||
|
||||
private class TestEntityEvent implements EntityEvent {
|
||||
|
||||
private String originNodeId;
|
||||
private String nodeId;
|
||||
private final String tenant;
|
||||
private final MyEntity entity;
|
||||
|
||||
/**
|
||||
* @param myEntity
|
||||
*/
|
||||
public TestEntityEvent(final MyEntity myEntity, final String tenant) {
|
||||
this.entity = myEntity;
|
||||
this.tenant = tenant;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.Event#getRevision()
|
||||
*/
|
||||
@Override
|
||||
public long getRevision() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#getOriginNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getOriginNodeId() {
|
||||
return originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setOriginNodeId(
|
||||
* java. lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void setOriginNodeId(final String originNodeId) {
|
||||
this.originNodeId = originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.NodeAware#getNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getNodeId() {
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setNodeId(java.
|
||||
* lang. String)
|
||||
*/
|
||||
@Override
|
||||
public void setNodeId(final String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getEntity(java.
|
||||
* lang. Class)
|
||||
*/
|
||||
@Override
|
||||
public <E> E getEntity(final Class<E> entityClass) {
|
||||
return entityClass.cast(entity);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getEntity()
|
||||
*/
|
||||
@Override
|
||||
public Object getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getTenant()
|
||||
*/
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyEntity implements Identifiable<String> {
|
||||
private final String id = "123";
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.hateoas.Identifiable#getId()
|
||||
*/
|
||||
@Override
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +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.cache.redis;
|
||||
|
||||
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
|
||||
public void setAndGetProps() {
|
||||
final String knownHost = "bumlux";
|
||||
final int knownPort = 1234;
|
||||
|
||||
final RedisProperties underTest = new RedisProperties();
|
||||
underTest.setHost(knownHost);
|
||||
underTest.setPort(knownPort);
|
||||
|
||||
assertThat(underTest.getHost()).isEqualTo(knownHost);
|
||||
assertThat(underTest.getPort()).isEqualTo(knownPort);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -53,6 +53,16 @@
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easytesting</groupId>
|
||||
<artifactId>fest-assert</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
|
||||
57
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DefaultDownloadIdCache.java
vendored
Normal file
57
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DefaultDownloadIdCache.java
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.Cache.ValueWrapper;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
* A default implementation of the {@link DownloadIdCache} which uses the
|
||||
* {@link CacheManager} implementation to store the download-ids.
|
||||
*/
|
||||
public class DefaultDownloadIdCache implements DownloadIdCache {
|
||||
|
||||
static final String DOWNLOAD_ID_CACHE = "DowonloadIdCache";
|
||||
|
||||
private final CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* @param cacheManager
|
||||
* the underlying cache-manager to store the download-ids
|
||||
*/
|
||||
@Autowired
|
||||
public DefaultDownloadIdCache(final CacheManager cacheManager) {
|
||||
this.cacheManager = cacheManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(final String downloadId, final DownloadArtifactCache object) {
|
||||
getCache().put(downloadId, object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DownloadArtifactCache get(final String downloadId) {
|
||||
final ValueWrapper valueWrapper = getCache().get(downloadId);
|
||||
return (valueWrapper == null) ? null : (DownloadArtifactCache) valueWrapper.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(final String downloadId) {
|
||||
getCache().evict(downloadId);
|
||||
}
|
||||
|
||||
private Cache getCache() {
|
||||
if (cacheManager instanceof TenancyCacheManager) {
|
||||
return ((TenancyCacheManager) cacheManager).getDirectCache(DOWNLOAD_ID_CACHE);
|
||||
}
|
||||
return cacheManager.getCache(DOWNLOAD_ID_CACHE);
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,7 @@
|
||||
package org.eclipse.hawkbit.cache;
|
||||
|
||||
/**
|
||||
* Cache Object for download a Artifact.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Cache Object for downloading an artifact.
|
||||
*/
|
||||
public class DownloadArtifactCache {
|
||||
|
||||
@@ -21,7 +18,7 @@ public class DownloadArtifactCache {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param downloadType
|
||||
* the type for searching the artifact.
|
||||
* @param id
|
||||
|
||||
57
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadIdCache.java
vendored
Normal file
57
hawkbit-core/src/main/java/org/eclipse/hawkbit/cache/DownloadIdCache.java
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
/**
|
||||
* A interface declaration of the download-id-cache which allows to store
|
||||
* volatile generated download-IDs used to have a single unique download-request
|
||||
* e.g. for distributed download-server.
|
||||
*
|
||||
* A valid download-id is created during a successful download-authorization
|
||||
* request e.g. from a download-server. In the DMF response a unique
|
||||
* download-URL containing a generated download-id which can be used to download
|
||||
* the artifact using this single download-url.
|
||||
*
|
||||
* The {@link DownloadIdCache} handles storing this unique download-id from the
|
||||
* DMF authorization request until the actual artifact download-request via HTTP
|
||||
* with the unique ID is performed.
|
||||
*
|
||||
*/
|
||||
public interface DownloadIdCache {
|
||||
|
||||
/**
|
||||
* Puts a given artifact cache object with the given downloadId key into the
|
||||
* cache.
|
||||
*
|
||||
* @param downloadId
|
||||
* the ID to store the cache object to look it up later on
|
||||
* @param downloadArtifactCacheObject
|
||||
* the object to store into the cache
|
||||
*/
|
||||
void put(final String downloadId, final DownloadArtifactCache downloadArtifactCacheObject);
|
||||
|
||||
/**
|
||||
* Retrieves a {@link DownloadArtifactCache} by a given downloadId.
|
||||
*
|
||||
* @param downloadId
|
||||
* the ID to retrieve the artifact cache object
|
||||
* @return the found {@link DownloadArtifactCache} or {@code null} if none
|
||||
* exists for the given ID
|
||||
*/
|
||||
DownloadArtifactCache get(final String downloadId);
|
||||
|
||||
/**
|
||||
* Evicts a {@link DownloadArtifactCache} for the given downloadId
|
||||
*
|
||||
* @param downloadId
|
||||
* the ID to be evicted
|
||||
*/
|
||||
void evict(String downloadId);
|
||||
|
||||
}
|
||||
@@ -10,9 +10,6 @@ package org.eclipse.hawkbit.cache;
|
||||
|
||||
/**
|
||||
* The type of the id which is saved.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public enum DownloadType {
|
||||
BY_SHA1
|
||||
|
||||
@@ -12,7 +12,6 @@ import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* A cache interface which handles multi tenancy.
|
||||
*/
|
||||
public interface TenancyCacheManager extends CacheManager {
|
||||
@@ -21,7 +20,7 @@ public interface TenancyCacheManager extends CacheManager {
|
||||
* A direct access for retrieving the cache without including the current
|
||||
* tenant key. This is necessary e.g. for retrieving caches not for the
|
||||
* current tenant.
|
||||
*
|
||||
*
|
||||
* @param name
|
||||
* the name of the cache to retrieve directly
|
||||
* @return the cache associated with the name without tenancy separation
|
||||
@@ -31,10 +30,9 @@ public interface TenancyCacheManager extends CacheManager {
|
||||
/**
|
||||
* Evicts all caches for a given tenant. All caches under a certain tenant
|
||||
* gets evicted.
|
||||
*
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to evict caches
|
||||
*/
|
||||
void evictCaches(final String tenant);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.cache;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
@@ -25,10 +26,6 @@ import org.springframework.cache.CacheManager;
|
||||
*
|
||||
* Additionally it also provide functionality to retrieve all caches overall
|
||||
* tenants at once, for monitoring and system access.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TenantAwareCacheManager implements TenancyCacheManager {
|
||||
|
||||
@@ -39,47 +36,45 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
|
||||
private final TenantAware tenantAware;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param delegate
|
||||
* the {@link CacheManager} to delegate to.
|
||||
* @param tenantAware
|
||||
* the tenant aware to retrieve the current tenant
|
||||
*/
|
||||
public TenantAwareCacheManager(final CacheManager delegate, final TenantAware tenantAware) {
|
||||
this.delegate = delegate;
|
||||
this.tenantAware = tenantAware;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cache getCache(final String name) {
|
||||
String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant == null) {
|
||||
if (isTenantInvalid(currentTenant)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
currentTenant = currentTenant.toUpperCase();
|
||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||
return null;
|
||||
}
|
||||
return delegate.getCache(currentTenant + TENANT_CACHE_DELIMITER + name);
|
||||
|
||||
return delegate.getCache(buildKey(currentTenant, name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getCacheNames() {
|
||||
String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant == null) {
|
||||
return Collections.emptyList();
|
||||
if (isTenantInvalid(currentTenant)) {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
currentTenant = currentTenant.toUpperCase();
|
||||
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return getCacheNames(currentTenant);
|
||||
}
|
||||
|
||||
/**
|
||||
* A direct access for retrieving all cache names overall tenants.
|
||||
*
|
||||
*
|
||||
* @return all cache names without tenant check
|
||||
*/
|
||||
public Collection<String> getDirectCacheNames() {
|
||||
@@ -91,17 +86,17 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
|
||||
return delegate.getCache(name);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.cache.TenancyCacheManager#evictCaches(java.
|
||||
* lang. String)
|
||||
*/
|
||||
@Override
|
||||
public void evictCaches(final String tenant) {
|
||||
getCacheNames(tenant)
|
||||
.forEach(cachename -> delegate.getCache(tenant + TENANT_CACHE_DELIMITER + cachename).clear());
|
||||
getCacheNames(tenant).forEach(cachename -> delegate.getCache(buildKey(tenant, cachename)).clear());
|
||||
}
|
||||
|
||||
private boolean isTenantInvalid(final String tenant) {
|
||||
return tenant == null || tenant.contains(TENANT_CACHE_DELIMITER);
|
||||
}
|
||||
|
||||
private String buildKey(final String tenant, final String cacheName) {
|
||||
return tenant + TENANT_CACHE_DELIMITER + cacheName;
|
||||
}
|
||||
|
||||
private Collection<String> getCacheNames(final String tenant) {
|
||||
|
||||
@@ -1,40 +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.eventbus;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.google.common.eventbus.DeadEvent;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* Catches all dead events by means of events with no fitting subscriber on the
|
||||
* bus.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@EventSubscriber
|
||||
@Service
|
||||
public class DeadEventListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DeadEventListener.class);
|
||||
|
||||
/**
|
||||
* Listens for dead vents and prints them into LOG.
|
||||
*
|
||||
* @param event
|
||||
* to print
|
||||
*/
|
||||
@Subscribe
|
||||
public void listen(final DeadEvent event) {
|
||||
LOG.info("DeadEvent on bus! {}", event.getEvent());
|
||||
}
|
||||
}
|
||||
@@ -1,88 +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.eventbus;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
/**
|
||||
* An {@link BeanPostProcessor} implementation which registers all beans as a
|
||||
* event bus subscriber if the classes are annotated with
|
||||
* {@link EventSubscriber} and have at least one method annotated with the
|
||||
* guava's {@link Subscribe} annoation.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
public class EventBusSubscriberProcessor implements BeanPostProcessor {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EventBusSubscriberProcessor.class);
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#
|
||||
* postProcessBeforeInitialization (java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(final Object bean, final String beanName) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#
|
||||
* postProcessAfterInitialization( java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(final Object bean, final String beanName) {
|
||||
final Class<? extends Object> beanClass = bean.getClass();
|
||||
final EventSubscriber eventSubscriber = beanClass.getAnnotation(EventSubscriber.class);
|
||||
if (eventSubscriber != null) {
|
||||
LOGGER.trace("Found bean {} with {} annotation ", bean.getClass().getName(),
|
||||
EventSubscriber.class.getSimpleName());
|
||||
final Method[] declaredMethods = beanClass.getDeclaredMethods();
|
||||
for (final Method method : declaredMethods) {
|
||||
final Subscribe subscriber = method.getAnnotation(Subscribe.class);
|
||||
if (subscriber != null) {
|
||||
LOGGER.trace("Found method {} for bean {} with {} annotation", method.getName(),
|
||||
bean.getClass().getName(), Subscribe.class.getSimpleName());
|
||||
eventBus.register(bean);
|
||||
return bean;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (eventSubscriber != null) {
|
||||
LOGGER.debug("Found bean {} with {} annotation but without any method with necessary {} annotation",
|
||||
bean.getClass().getName(), EventSubscriber.class.getSimpleName(), Subscribe.class.getSimpleName());
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* package private setter for testing purposes.
|
||||
*
|
||||
* @param eventBus
|
||||
* the event bus
|
||||
*/
|
||||
void setEventBus(final EventBus eventBus) {
|
||||
this.eventBus = eventBus;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +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.eventbus;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE;
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks an class as an event subscriber to listen on event on the event bus
|
||||
* without explicit register this class to the event bus.
|
||||
*
|
||||
* <pre>
|
||||
* @EventSubscriber
|
||||
* public class MySubscriber {
|
||||
* @Subscribe
|
||||
* public void listen(MyEvent event) {
|
||||
* System.out.println("event received: " + event);
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Target({ TYPE })
|
||||
@Retention(RUNTIME)
|
||||
public @interface EventSubscriber {
|
||||
|
||||
}
|
||||
@@ -1,105 +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.eventbus.event;
|
||||
|
||||
/**
|
||||
* An abstract class of the {@link DistributedEvent} implementation which holds
|
||||
* all the necessary information of distributing events to other nodes.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractDistributedEvent implements DistributedEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long revision;
|
||||
private String originNodeId;
|
||||
private String nodeId;
|
||||
private final String tenant;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param revision
|
||||
* the revision of this event
|
||||
* @param tenant
|
||||
* the tenant for this event
|
||||
*/
|
||||
protected AbstractDistributedEvent(final long revision, final String tenant) {
|
||||
this.revision = revision;
|
||||
this.tenant = tenant;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setOriginNodeId(java.
|
||||
* lang. String)
|
||||
*/
|
||||
@Override
|
||||
public void setOriginNodeId(final String originNodeId) {
|
||||
this.originNodeId = originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#setNodeId(java.lang.
|
||||
* String)
|
||||
*/
|
||||
@Override
|
||||
public void setNodeId(final String nodeId) {
|
||||
this.nodeId = nodeId;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see
|
||||
* org.eclipse.hawkbit.server.eventbus.event.NodeAware#getOriginNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getOriginNodeId() {
|
||||
return this.originNodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.NodeAware#getNodeId()
|
||||
*/
|
||||
@Override
|
||||
public String getNodeId() {
|
||||
return this.nodeId;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.Event#getRevision()
|
||||
*/
|
||||
@Override
|
||||
public long getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.hawkbit.server.eventbus.event.EntityEvent#getTenant()
|
||||
*/
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +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.eventbus.event;
|
||||
|
||||
/**
|
||||
* Abstract event definition class which holds the necessary revsion and tenant
|
||||
* information which every event needs.
|
||||
*
|
||||
* @see AbstractDistributedEvent for events which should be distributed to other
|
||||
* cluster nodes
|
||||
*/
|
||||
public class DefaultEvent implements Event {
|
||||
|
||||
private final long revision;
|
||||
private final String tenant;
|
||||
|
||||
/**
|
||||
* @param revision
|
||||
* the revision number of the event
|
||||
* @param tenant
|
||||
* the tenant of the event
|
||||
*/
|
||||
protected DefaultEvent(final long revision, final String tenant) {
|
||||
this.revision = revision;
|
||||
this.tenant = tenant;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getRevision() {
|
||||
return revision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTenant() {
|
||||
return tenant;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +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.eventbus.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Marks an event to as an distributed event which will be distributed to other
|
||||
* nodes.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface DistributedEvent extends Event, NodeAware, Serializable {
|
||||
|
||||
}
|
||||
@@ -1,48 +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.eventbus.event;
|
||||
|
||||
/**
|
||||
* An event interface which declares event types that an entity has been
|
||||
* changed. {@link EntityEvent}s should not implement {@link DistributedEvent}
|
||||
* due all {@link EntityEvent}s will be distributed to other nodes.
|
||||
*
|
||||
* Retrieving an {@link EntityEvent} on a different node the entity will be load
|
||||
* lazy.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface EntityEvent extends Event, NodeAware {
|
||||
|
||||
/**
|
||||
* A typesafe way to retrieve the entity from the event, which might be
|
||||
* loaded lazy in case the event has been distributed from another node.
|
||||
*
|
||||
* @param entityClass
|
||||
* the class of the entity to retrieve
|
||||
* @return the entity might be lazy loaded. Might be {@code null} in case
|
||||
* the entity e.g. is queried lazy on a different node and has been
|
||||
* already deleted from the database
|
||||
* @throws ClassCastException
|
||||
* in case a wrong entity class is given for this event
|
||||
*/
|
||||
<E> E getEntity(Class<E> entityClass);
|
||||
|
||||
/**
|
||||
* An unsafe way to retrieve the entity from this event which might be
|
||||
* loaded lazy in case the event has been distributed from another node.
|
||||
*
|
||||
* @return the entity might be lazy loaded. Might be {@code null} in case
|
||||
* the entity e.g. is queried lazy on a different node and has been
|
||||
* already deleted from the database
|
||||
*/
|
||||
Object getEntity();
|
||||
}
|
||||
@@ -1,32 +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.eventbus.event;
|
||||
|
||||
/**
|
||||
* An event declaration which holds an revision for each event so consumers have
|
||||
* the chance to know if they might already retrieved an newer event.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface Event {
|
||||
|
||||
/**
|
||||
* @return the revision of this event which should be increment or each new
|
||||
* event in case the event have a causalität. Might be {@code -1} in
|
||||
* case the events does not provide any revision.
|
||||
*/
|
||||
long getRevision();
|
||||
|
||||
/**
|
||||
* @return the tenant of the entity.
|
||||
*/
|
||||
String getTenant();
|
||||
}
|
||||
@@ -1,52 +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.eventbus.event;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by events which are distributed to other nodes
|
||||
* where it's necessary to know which node sent an event and which nodes
|
||||
* retrieved the event from which node. Using the EventDistributor the
|
||||
* implementation only needs to contain the necessary node IDs, setting and
|
||||
* retrieving the node IDs is transparent by the EventDistributor so the event
|
||||
* distributor does not hang in an endless loop of distributing the events which
|
||||
* self posted.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public interface NodeAware {
|
||||
|
||||
/**
|
||||
* @return the origin node ID in case the event has been forwarded to other
|
||||
* nodes or {@code null} if the event has not been forwarded to
|
||||
* other nodes
|
||||
*/
|
||||
String getOriginNodeId();
|
||||
|
||||
/**
|
||||
* @param originNodeId
|
||||
* the origin node ID where this event has been sent originally
|
||||
*/
|
||||
void setOriginNodeId(String originNodeId);
|
||||
|
||||
/**
|
||||
* @return the node ID which is processing this event locally, set by the
|
||||
* EventDistributor so he can determine if this event has been
|
||||
* received by another node and is processing on the current node.
|
||||
*/
|
||||
String getNodeId();
|
||||
|
||||
/**
|
||||
* @param nodeId
|
||||
* the ID of the node this event is processing.
|
||||
*/
|
||||
void setNodeId(String nodeId);
|
||||
|
||||
}
|
||||
124
hawkbit-core/src/test/java/org/eclipse/hawkbit/cache/DefaultDownloadIdCacheTest.java
vendored
Normal file
124
hawkbit-core/src/test/java/org/eclipse/hawkbit/cache/DefaultDownloadIdCacheTest.java
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* 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.cache;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
@Features("Unit Tests - Cache")
|
||||
@Stories("Download ID Cache")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DefaultDownloadIdCacheTest {
|
||||
|
||||
@Mock
|
||||
private CacheManager cacheManagerMock;
|
||||
|
||||
@Mock
|
||||
private TenancyCacheManager tenancyCacheManagerMock;
|
||||
|
||||
@Mock
|
||||
private Cache cacheMock;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<String> cacheManagerKeyCaptor;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<DownloadArtifactCache> cacheManagerValueCaptor;
|
||||
|
||||
private DefaultDownloadIdCache underTest;
|
||||
|
||||
private final String knownKey = "12345";
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
underTest = new DefaultDownloadIdCache(cacheManagerMock);
|
||||
when(cacheManagerMock.getCache(DefaultDownloadIdCache.DOWNLOAD_ID_CACHE)).thenReturn(cacheMock);
|
||||
when(tenancyCacheManagerMock.getDirectCache(DefaultDownloadIdCache.DOWNLOAD_ID_CACHE)).thenReturn(cacheMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that putting key and value is delegated to the CacheManager implementation")
|
||||
public void putKeyAndValueIsDelegatedToCacheManager() {
|
||||
final DownloadArtifactCache value = new DownloadArtifactCache(DownloadType.BY_SHA1, knownKey);
|
||||
|
||||
underTest.put(knownKey, value);
|
||||
|
||||
verify(cacheMock).put(cacheManagerKeyCaptor.capture(), cacheManagerValueCaptor.capture());
|
||||
|
||||
assertThat(cacheManagerKeyCaptor.getValue()).isEqualTo(knownKey);
|
||||
assertThat(cacheManagerValueCaptor.getValue()).isEqualTo(value);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that evicting a key is delegated to the CacheManager implementation")
|
||||
public void evictKeyIsDelegatedToCacheManager() {
|
||||
|
||||
underTest.evict(knownKey);
|
||||
|
||||
verify(cacheMock).evict(cacheManagerKeyCaptor.capture());
|
||||
|
||||
assertThat(cacheManagerKeyCaptor.getValue()).isEqualTo(knownKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that retrieving a value for a specific key is delegated to the CacheManager implementation")
|
||||
public void getValueReturnsTheAssociatedValueForKey() {
|
||||
final String knownKey = "12345";
|
||||
final DownloadArtifactCache knownValue = new DownloadArtifactCache(DownloadType.BY_SHA1, knownKey);
|
||||
|
||||
when(cacheMock.get(knownKey)).thenReturn(new SimpleValueWrapper(knownValue));
|
||||
|
||||
final DownloadArtifactCache downloadArtifactCache = underTest.get(knownKey);
|
||||
|
||||
assertThat(downloadArtifactCache).isEqualTo(knownValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that retrieving a null value for a specific key is delegated to the CacheManager implementation")
|
||||
public void getValueReturnsNullIfNoKeyIsAssociated() {
|
||||
|
||||
when(cacheMock.get(knownKey)).thenReturn(new SimpleValueWrapper(null));
|
||||
|
||||
final DownloadArtifactCache downloadArtifactCache = underTest.get(knownKey);
|
||||
|
||||
assertThat(downloadArtifactCache).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that TenancyCacheManager is using direct cache because download-ids are global unique and don't need to run as tenant aware")
|
||||
public void tenancyCacheManagerIsUsingDirectCache() {
|
||||
|
||||
underTest = new DefaultDownloadIdCache(tenancyCacheManagerMock);
|
||||
final DownloadArtifactCache value = new DownloadArtifactCache(DownloadType.BY_SHA1, knownKey);
|
||||
|
||||
underTest.put(knownKey, value);
|
||||
|
||||
verify(cacheMock).put(cacheManagerKeyCaptor.capture(), cacheManagerValueCaptor.capture());
|
||||
|
||||
verify(tenancyCacheManagerMock).getDirectCache(DefaultDownloadIdCache.DOWNLOAD_ID_CACHE);
|
||||
assertThat(cacheManagerKeyCaptor.getValue()).isEqualTo(knownKey);
|
||||
assertThat(cacheManagerValueCaptor.getValue()).isEqualTo(value);
|
||||
}
|
||||
}
|
||||
@@ -1,75 +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.eventbus;
|
||||
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
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.stereotype.Service;
|
||||
|
||||
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
|
||||
private EventBus eventBusMock;
|
||||
|
||||
private final EventBusSubscriberProcessor postProcessorUnderTest = new EventBusSubscriberProcessor();
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
reset(eventBusMock);
|
||||
postProcessorUnderTest.setEventBus(eventBusMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void correctAnnotatedClassAndMethodIsRegistered() {
|
||||
final TestEventSubscriberClass testEventSubscriberClass = new TestEventSubscriberClass();
|
||||
postProcessorUnderTest.postProcessAfterInitialization(testEventSubscriberClass, "correctEventSubscriber");
|
||||
verify(eventBusMock, times(1)).register(testEventSubscriberClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eventSubscriberWithoutMethodAnnotationIsNotRegistered() {
|
||||
final TestWrongEventSubscriberClass testEventSubscriberClass = new TestWrongEventSubscriberClass();
|
||||
postProcessorUnderTest.postProcessAfterInitialization(testEventSubscriberClass, "correctEventSubscriber");
|
||||
verify(eventBusMock, times(0)).register(testEventSubscriberClass);
|
||||
}
|
||||
|
||||
@EventSubscriber
|
||||
@Service
|
||||
private class TestEventSubscriberClass {
|
||||
@Subscribe
|
||||
public void subscribe(final String s) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@EventSubscriber
|
||||
@Service
|
||||
private class TestWrongEventSubscriberClass {
|
||||
public void methodWithoutAnnotation(final String s) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,9 +37,5 @@
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -67,22 +67,6 @@
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
@@ -103,13 +87,6 @@
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-http-security</artifactId>
|
||||
|
||||
@@ -30,7 +30,8 @@ import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
@@ -41,15 +42,15 @@ import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.eventbus.EventBus;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
@@ -61,6 +62,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
*/
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Artifact Download Resource")
|
||||
@SpringApplicationConfiguration(classes = DownloadTestConfiguration.class)
|
||||
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB {
|
||||
|
||||
private static final int ARTIFACT_SIZE = 5 * 1024 * 1024;
|
||||
@@ -69,9 +71,8 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class);
|
||||
}
|
||||
|
||||
private volatile int downLoadProgress = 0;
|
||||
private volatile long shippedBytes = 0;
|
||||
private volatile long shippedBytesTotal = 0;
|
||||
private volatile static int downLoadProgress = 0;
|
||||
private volatile static long shippedBytes = 0;
|
||||
|
||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
|
||||
|
||||
@@ -80,9 +81,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private EventBus eventBus;
|
||||
|
||||
@Test
|
||||
@Description("Tests non allowed requests on the artifact ressource, e.g. invalid URI, wrong if-match, wrong command.")
|
||||
public void invalidRequestsOnArtifactResource() throws Exception {
|
||||
@@ -252,8 +250,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
public void downloadArtifactThroughFileName() throws Exception {
|
||||
downLoadProgress = 1;
|
||||
shippedBytes = 0;
|
||||
shippedBytesTotal = 0;
|
||||
eventBus.register(this);
|
||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||
|
||||
// create target
|
||||
@@ -293,7 +289,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
|
||||
// download complete
|
||||
assertThat(downLoadProgress).isEqualTo(10);
|
||||
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE);
|
||||
assertThat(shippedBytes).isEqualTo(ARTIFACT_SIZE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -332,8 +328,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception {
|
||||
downLoadProgress = 1;
|
||||
shippedBytes = 0;
|
||||
shippedBytesTotal = 0;
|
||||
eventBus.register(this);
|
||||
|
||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||
|
||||
@@ -357,7 +351,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
assertThat(downLoadProgress).isEqualTo(1);
|
||||
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(0L);
|
||||
assertThat(shippedBytes).isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -366,8 +360,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
public void downloadArtifactByNameByNamedController() throws Exception {
|
||||
downLoadProgress = 1;
|
||||
shippedBytes = 0;
|
||||
shippedBytesTotal = 0;
|
||||
eventBus.register(this);
|
||||
|
||||
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
|
||||
|
||||
@@ -414,7 +406,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
|
||||
// download complete
|
||||
assertThat(downLoadProgress).isEqualTo(10);
|
||||
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE);
|
||||
assertThat(shippedBytes).isEqualTo(ARTIFACT_SIZE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -573,11 +565,23 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
|
||||
.isEqualTo(new String(artifact.getMd5Hash() + " file1.tar.bz2").getBytes(Charsets.US_ASCII));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void listen(final DownloadProgressEvent event) {
|
||||
downLoadProgress++;
|
||||
shippedBytes += event.getShippedBytesSinceLast();
|
||||
shippedBytesTotal = event.getShippedBytesOverall();
|
||||
public static class DownloadTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public Listener cancelEventHandlerStubBean() {
|
||||
return new Listener();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Listener {
|
||||
|
||||
@EventListener(classes = DownloadProgressEvent.class)
|
||||
public void listen(final DownloadProgressEvent event) {
|
||||
downLoadProgress++;
|
||||
shippedBytes += event.getShippedBytesSinceLast();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.Test;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
@@ -74,7 +73,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
// get update action anyway
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/" + updateAction.getId(),
|
||||
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(updateAction.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
@@ -118,7 +117,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -150,7 +149,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -170,7 +169,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction.getId()))));
|
||||
assertThat(targetManagement.findTargetByControllerID("4712").getTargetInfo().getLastTargetQuery())
|
||||
@@ -360,14 +359,14 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction.getId()))));
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -386,14 +385,14 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
assertThat(deploymentManagement.findActionsByTarget(savedTarget)).hasSize(3);
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction2.getId(),
|
||||
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction2.getId()))));
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -426,7 +425,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction3.getId(),
|
||||
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction3.getId()))));
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(12);
|
||||
@@ -435,7 +434,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction3.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction3.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(13);
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class DdiConfigDataTest extends AbstractRestIntegrationTest {
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.configData.href", equalTo(
|
||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
|
||||
@@ -75,7 +75,7 @@ public class DdiConfigDataTest extends AbstractRestIntegrationTest {
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.configData.href").doesNotExist());
|
||||
}
|
||||
|
||||
@@ -27,13 +27,13 @@ import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
@@ -44,7 +44,6 @@ import org.fest.assertions.core.Condition;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
@@ -136,7 +135,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
@@ -155,7 +154,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
@@ -236,7 +235,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
|
||||
MvcResult mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)).andReturn();
|
||||
|
||||
final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
|
||||
.read(mvcResult.getResponse().getContentAsString()).toString();
|
||||
@@ -244,7 +243,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
// Time is not yet over, so we should see the same URL
|
||||
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)).andReturn();
|
||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).isEqualTo(urlBeforeSwitch)
|
||||
.startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -255,7 +254,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
|
||||
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)).andReturn();
|
||||
|
||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).isNotEqualTo(urlBeforeSwitch);
|
||||
@@ -300,7 +299,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
@@ -319,7 +318,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("attempt")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("attempt")))
|
||||
@@ -424,7 +423,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
@@ -441,7 +440,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/{actionId}", tenantAware.getCurrentTenant(),
|
||||
uaction.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
|
||||
@@ -122,7 +122,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/default-tenant/controller/v1/4711")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
|
||||
assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
@@ -154,7 +154,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
|
||||
return null;
|
||||
});
|
||||
@@ -165,7 +165,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
|
||||
public void rootRsNotModified() throws Exception {
|
||||
final String etag = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))).andReturn().getResponse()
|
||||
.getHeader("ETag");
|
||||
|
||||
@@ -182,7 +182,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
|
||||
.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -215,7 +215,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header("If-None-Match", etagWithFirstUpdate).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
@@ -236,8 +236,9 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
|
||||
|
||||
assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery())
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
logging.level.=INFO
|
||||
logging.level.org.eclipse.persistence=ERROR
|
||||
|
||||
spring.data.mongodb.uri=mongodb://localhost/spArtifactRepository${random.value}
|
||||
spring.data.mongodb.port=28017
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
which accompanies this distribution, and is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||
|
||||
<!-- <Logger name="org.eclipse.hawkbit.rest.util.MockMvcResultPrinter" level="DEBUG" /> -->
|
||||
|
||||
<Root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</Root>
|
||||
|
||||
</configuration>
|
||||
@@ -57,10 +57,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
@@ -69,6 +65,8 @@
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.eclipse.hawkbit.cache.DownloadArtifactCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash;
|
||||
@@ -31,7 +32,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.cache.Cache;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
@@ -56,7 +56,7 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService {
|
||||
|
||||
private final ArtifactManagement artifactManagement;
|
||||
|
||||
private final Cache cache;
|
||||
private final DownloadIdCache cache;
|
||||
|
||||
private final HostnameResolver hostnameResolver;
|
||||
|
||||
@@ -78,7 +78,7 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService {
|
||||
*/
|
||||
public AmqpAuthenticationMessageHandler(final RabbitTemplate rabbitTemplate,
|
||||
final AmqpControllerAuthentication authenticationManager, final ArtifactManagement artifactManagement,
|
||||
final Cache cache, final HostnameResolver hostnameResolver,
|
||||
final DownloadIdCache cache, final HostnameResolver hostnameResolver,
|
||||
final ControllerManagement controllerManagement) {
|
||||
super(rabbitTemplate);
|
||||
this.authenticationManager = authenticationManager;
|
||||
@@ -89,7 +89,7 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed on a authentication request.
|
||||
* Executed on an authentication request.
|
||||
*
|
||||
* @param message
|
||||
* the amqp message
|
||||
|
||||
@@ -15,12 +15,13 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.AmqpSettings;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
@@ -45,7 +46,7 @@ import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cloud.bus.ServiceMatcher;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
|
||||
@@ -74,6 +75,9 @@ public class AmqpConfiguration {
|
||||
@Autowired
|
||||
private ConnectionFactory rabbitConnectionFactory;
|
||||
|
||||
@Autowired(required = false)
|
||||
private ServiceMatcher serviceMatcher;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(ConnectionFactory.class)
|
||||
@ConditionalOnProperty(prefix = "hawkbit.dmf.rabbitmq", name = "enabled", matchIfMissing = true)
|
||||
@@ -288,7 +292,7 @@ public class AmqpConfiguration {
|
||||
* for target authentication
|
||||
* @param artifactManagement
|
||||
* for artifact URI generation
|
||||
* @param cache
|
||||
* @param downloadIdCache
|
||||
* for download IDs
|
||||
* @param hostnameResolver
|
||||
* for resolving the host for downloads
|
||||
@@ -299,10 +303,10 @@ public class AmqpConfiguration {
|
||||
@Bean
|
||||
public AmqpAuthenticationMessageHandler amqpAuthenticationMessageHandler(final RabbitTemplate rabbitTemplate,
|
||||
final AmqpControllerAuthentication authenticationManager, final ArtifactManagement artifactManagement,
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE) final Cache cache, final HostnameResolver hostnameResolver,
|
||||
final DownloadIdCache downloadIdCache, final HostnameResolver hostnameResolver,
|
||||
final ControllerManagement controllerManagement) {
|
||||
return new AmqpAuthenticationMessageHandler(rabbitTemplate, authenticationManager, artifactManagement, cache,
|
||||
hostnameResolver, controllerManagement);
|
||||
return new AmqpAuthenticationMessageHandler(rabbitTemplate, authenticationManager, artifactManagement,
|
||||
downloadIdCache, hostnameResolver, controllerManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,6 +334,23 @@ public class AmqpConfiguration {
|
||||
return new ConfigurableRabbitListenerContainerFactory(amqpProperties, rabbitConnectionFactory, errorHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* create the authentication bean for controller over amqp.
|
||||
*
|
||||
* @param systemManagement
|
||||
* the systemManagement
|
||||
* @param controllerManagement
|
||||
* the controllerManagement
|
||||
* @param tenantConfigurationManagement
|
||||
* the tenantConfigurationManagement
|
||||
* @param tenantAware
|
||||
* the tenantAware
|
||||
* @param ddiSecruityProperties
|
||||
* the ddiSecruityProperties
|
||||
* @param systemSecurityContext
|
||||
* the systemSecurityContext
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AmqpControllerAuthentication.class)
|
||||
public AmqpControllerAuthentication amqpControllerAuthentication(final SystemManagement systemManagement,
|
||||
@@ -340,13 +361,31 @@ public class AmqpConfiguration {
|
||||
tenantAware, ddiSecruityProperties, systemSecurityContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the dispatcher bean.
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
* the rabbitTemplate
|
||||
* @param amqpSenderService
|
||||
* to send AMQP message
|
||||
* @param artifactUrlHandler
|
||||
* for generating download URLs
|
||||
* @param systemSecurityContext
|
||||
* for execution with system permissions
|
||||
* @param systemManagement
|
||||
* the systemManagement
|
||||
* @param targetManagement
|
||||
* to access target information
|
||||
* @return the bean
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(AmqpMessageDispatcherService.class)
|
||||
public AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate,
|
||||
final AmqpSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
|
||||
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement) {
|
||||
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
|
||||
final TargetManagement targetManagement) {
|
||||
return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,
|
||||
systemSecurityContext, systemManagement);
|
||||
systemSecurityContext, systemManagement, targetManagement, serviceMatcher);
|
||||
}
|
||||
|
||||
private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() {
|
||||
|
||||
@@ -25,38 +25,40 @@ import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.dmf.json.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
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 com.google.common.eventbus.Subscribe;
|
||||
import org.springframework.cloud.bus.ServiceMatcher;
|
||||
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
|
||||
/**
|
||||
* {@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 extends BaseAmqpService {
|
||||
|
||||
private final ArtifactUrlHandler artifactUrlHandler;
|
||||
private final AmqpSenderService amqpSenderService;
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
private final SystemManagement systemManagement;
|
||||
private final TargetManagement targetManagement;
|
||||
private final ServiceMatcher serviceMatcher;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
* the rabbitTemplate
|
||||
* @param amqpSenderService
|
||||
@@ -66,51 +68,68 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
* @param systemSecurityContext
|
||||
* for execution with system permissions
|
||||
* @param systemManagement
|
||||
* to access to tenant metadata
|
||||
* the systemManagement
|
||||
* @param targetManagement
|
||||
* to access target information
|
||||
* @param serviceMatcher
|
||||
* to check in cluster case if the message is from the same
|
||||
* cluster node
|
||||
*/
|
||||
public AmqpMessageDispatcherService(final RabbitTemplate rabbitTemplate, final AmqpSenderService amqpSenderService,
|
||||
final ArtifactUrlHandler artifactUrlHandler, final SystemSecurityContext systemSecurityContext,
|
||||
final SystemManagement systemManagement) {
|
||||
final SystemManagement systemManagement, final TargetManagement targetManagement,
|
||||
final ServiceMatcher serviceMatcher) {
|
||||
super(rabbitTemplate);
|
||||
this.artifactUrlHandler = artifactUrlHandler;
|
||||
this.amqpSenderService = amqpSenderService;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
this.systemManagement = systemManagement;
|
||||
this.targetManagement = targetManagement;
|
||||
this.serviceMatcher = serviceMatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to send a message to a RabbitMQ Exchange after the Distribution
|
||||
* set has been assign to a Target.
|
||||
*
|
||||
* @param targetAssignDistributionSetEvent
|
||||
* @param assignedEvent
|
||||
* the object to be send.
|
||||
*/
|
||||
@Subscribe
|
||||
public void targetAssignDistributionSet(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) {
|
||||
final URI targetAdress = targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress();
|
||||
@EventListener(classes = TargetAssignDistributionSetEvent.class)
|
||||
public void targetAssignDistributionSet(final TargetAssignDistributionSetEvent assignedEvent) {
|
||||
if (isFromSelf(assignedEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendUpdateMessageToTarget(assignedEvent.getTenant(),
|
||||
targetManagement.findTargetByControllerID(assignedEvent.getControllerId()), assignedEvent.getActionId(),
|
||||
assignedEvent.getModules());
|
||||
}
|
||||
|
||||
void sendUpdateMessageToTarget(final String tenant, final Target target, final Long actionId,
|
||||
final Collection<org.eclipse.hawkbit.repository.model.SoftwareModule> modules) {
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final URI targetAdress = target.getTargetInfo().getAddress();
|
||||
if (!IpUtil.isAmqpUri(targetAdress)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String controllerId = targetAssignDistributionSetEvent.getTarget().getControllerId();
|
||||
final Collection<org.eclipse.hawkbit.repository.model.SoftwareModule> modules = targetAssignDistributionSetEvent
|
||||
.getSoftwareModules();
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = new DownloadAndUpdateRequest();
|
||||
downloadAndUpdateRequest.setActionId(targetAssignDistributionSetEvent.getActionId());
|
||||
downloadAndUpdateRequest.setActionId(actionId);
|
||||
|
||||
final String targetSecurityToken = systemSecurityContext
|
||||
.runAsSystem(targetAssignDistributionSetEvent.getTarget()::getSecurityToken);
|
||||
final String targetSecurityToken = systemSecurityContext.runAsSystem(target::getSecurityToken);
|
||||
downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken);
|
||||
|
||||
for (final org.eclipse.hawkbit.repository.model.SoftwareModule softwareModule : modules) {
|
||||
final SoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(
|
||||
targetAssignDistributionSetEvent.getTarget(), softwareModule);
|
||||
final SoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, softwareModule);
|
||||
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
|
||||
}
|
||||
|
||||
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
|
||||
createConnectorMessageProperties(targetAssignDistributionSetEvent.getTenant(), controllerId,
|
||||
EventTopic.DOWNLOAD_AND_INSTALL));
|
||||
createConnectorMessageProperties(tenant, target.getControllerId(), EventTopic.DOWNLOAD_AND_INSTALL));
|
||||
amqpSenderService.sendMessage(message, targetAdress);
|
||||
}
|
||||
|
||||
@@ -118,19 +137,29 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
* Method to send a message to a RabbitMQ Exchange after the assignment of
|
||||
* the Distribution set to a Target has been canceled.
|
||||
*
|
||||
* @param cancelTargetAssignmentDistributionSetEvent
|
||||
* @param cancelEvent
|
||||
* the object to be send.
|
||||
*/
|
||||
@Subscribe
|
||||
public void targetCancelAssignmentToDistributionSet(
|
||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent) {
|
||||
final String controllerId = cancelTargetAssignmentDistributionSetEvent.getTarget().getControllerId();
|
||||
final Long actionId = cancelTargetAssignmentDistributionSetEvent.getActionId();
|
||||
final Message message = getMessageConverter().toMessage(actionId, createConnectorMessageProperties(
|
||||
cancelTargetAssignmentDistributionSetEvent.getTenant(), controllerId, EventTopic.CANCEL_DOWNLOAD));
|
||||
@EventListener(classes = CancelTargetAssignmentEvent.class)
|
||||
public void targetCancelAssignmentToDistributionSet(final CancelTargetAssignmentEvent cancelEvent) {
|
||||
if (isFromSelf(cancelEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
amqpSenderService.sendMessage(message,
|
||||
cancelTargetAssignmentDistributionSetEvent.getTarget().getTargetInfo().getAddress());
|
||||
sendCancelMessageToTarget(cancelEvent.getTenant(), cancelEvent.getEntity().getControllerId(),
|
||||
cancelEvent.getActionId(), cancelEvent.getEntity().getTargetInfo().getAddress());
|
||||
}
|
||||
|
||||
private boolean isFromSelf(final RemoteApplicationEvent event) {
|
||||
return serviceMatcher != null && !serviceMatcher.isFromSelf(event);
|
||||
}
|
||||
|
||||
void sendCancelMessageToTarget(final String tenant, final String controllerId, final Long actionId,
|
||||
final URI address) {
|
||||
final Message message = getMessageConverter().toMessage(actionId,
|
||||
createConnectorMessageProperties(tenant, controllerId, EventTopic.CANCEL_DOWNLOAD));
|
||||
|
||||
amqpSenderService.sendMessage(message, address);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.amqp;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@@ -26,15 +25,11 @@ import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
|
||||
import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.slf4j.Logger;
|
||||
@@ -176,7 +171,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
final String replyTo = message.getMessageProperties().getReplyTo();
|
||||
|
||||
if (StringUtils.isEmpty(replyTo)) {
|
||||
logAndThrowMessageError(message, "No ReplyTo was set for the createThing Event.");
|
||||
logAndThrowMessageError(message, "No ReplyTo was set for the createThing TenantAwareEvent.");
|
||||
}
|
||||
|
||||
final URI amqpUri = IpUtil.createAmqpUri(virtualHost, replyTo);
|
||||
@@ -187,23 +182,20 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
}
|
||||
|
||||
private void lookIfUpdateAvailable(final Target target) {
|
||||
final Optional<Action> action = controllerManagement.findOldestActiveActionByTarget(target);
|
||||
if (!action.isPresent()) {
|
||||
final Optional<Action> actionOptional = controllerManagement.findOldestActiveActionByTarget(target);
|
||||
if (!actionOptional.isPresent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (action.get().isCancelingOrCanceled()) {
|
||||
amqpMessageDispatcherService.targetCancelAssignmentToDistributionSet(
|
||||
new CancelTargetAssignmentEvent(target, action.get().getId()));
|
||||
final Action action = actionOptional.get();
|
||||
if (action.isCancelingOrCanceled()) {
|
||||
amqpMessageDispatcherService.sendCancelMessageToTarget(target.getTenant(), target.getControllerId(),
|
||||
action.getId(), target.getTargetInfo().getAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
final DistributionSet distributionSet = action.get().getDistributionSet();
|
||||
final List<SoftwareModule> softwareModuleList = controllerManagement
|
||||
.findSoftwareModulesByDistributionSet(distributionSet);
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(new TargetAssignDistributionSetEvent(
|
||||
target.getOptLockRevision(), target.getTenant(), target, action.get().getId(), softwareModuleList));
|
||||
|
||||
amqpMessageDispatcherService.sendUpdateMessageToTarget(action.getTenant(), action.getTarget(), action.getId(),
|
||||
action.getDistributionSet().getModules());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,5 +324,4 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
|
||||
"Cancel recjected message is not allowed, if action is on state: " + action.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.net.URL;
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse;
|
||||
@@ -54,7 +55,6 @@ import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@@ -95,7 +95,7 @@ public class AmqpControllerAuthenticationTest {
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
@Mock
|
||||
private Cache cacheMock;
|
||||
private DownloadIdCache cacheMock;
|
||||
|
||||
@Mock
|
||||
private HostnameResolver hostnameResolverMock;
|
||||
|
||||
@@ -19,9 +19,9 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.eclipse.hawkbit.api.ArtifactUrl;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
@@ -31,8 +31,12 @@ import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
|
||||
import org.eclipse.hawkbit.repository.jpa.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -48,6 +52,7 @@ import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
|
||||
@@ -82,11 +87,15 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
private Target testTarget;
|
||||
|
||||
@Autowired
|
||||
protected ActionRepository actionRepository;
|
||||
|
||||
@Override
|
||||
public void before() throws Exception {
|
||||
super.before();
|
||||
testTarget = entityFactory.generateTarget(CONTROLLER_ID, TEST_TOKEN);
|
||||
testTarget.getTargetInfo().setAddress(AMQP_URI.toString());
|
||||
final Target generateTarget = entityFactory.generateTarget(CONTROLLER_ID, TEST_TOKEN);
|
||||
generateTarget.getTargetInfo().setAddress(AMQP_URI.toString());
|
||||
testTarget = targetManagement.createTarget(generateTarget);
|
||||
|
||||
this.rabbitTemplate = Mockito.mock(RabbitTemplate.class);
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter());
|
||||
@@ -105,41 +114,62 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
when(systemManagement.getTenantMetadata()).thenReturn(tenantMetaData);
|
||||
|
||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
|
||||
artifactUrlHandlerMock, systemSecurityContext, systemManagement);
|
||||
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that download and install event with no software modul works")
|
||||
public void testSendDownloadRequesWithEmptySoftwareModules() {
|
||||
final Action action = createAction(
|
||||
testdataFactory.createDistributionSetWithNoSoftwareModules(UUID.randomUUID().toString(), "1.0"));
|
||||
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, TENANT, testTarget, 1L, Collections.emptyList());
|
||||
action, serviceMatcher.getServiceId());
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(
|
||||
targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
|
||||
final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action);
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
|
||||
assertTrue("No softwaremmodule should be contained in the request",
|
||||
downloadAndUpdateRequest.getSoftwareModules().isEmpty());
|
||||
}
|
||||
|
||||
private Message getCaptureAdressEvent(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) {
|
||||
final Target target = targetManagement
|
||||
.findTargetByControllerID(targetAssignDistributionSetEvent.getControllerId());
|
||||
final Message sendMessage = createArgumentCapture(target.getTargetInfo().getAddress());
|
||||
return sendMessage;
|
||||
}
|
||||
|
||||
private JpaAction createAction(final DistributionSet testDs) {
|
||||
final Action action = entityFactory.generateAction();
|
||||
final JpaAction jpaAction = (JpaAction) action;
|
||||
action.setDistributionSet(testDs);
|
||||
action.setTarget(testTarget);
|
||||
jpaAction.setActionType(ActionType.FORCED);
|
||||
|
||||
return actionRepository.save(jpaAction);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that download and install event with 3 software moduls and no artifacts works")
|
||||
public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
final DistributionSet createDistributionSet = testdataFactory
|
||||
.createDistributionSet(UUID.randomUUID().toString());
|
||||
final Action action = createAction(createDistributionSet);
|
||||
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, TENANT, testTarget, 1L, dsA.getModules());
|
||||
action, serviceMatcher.getServiceId());
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(
|
||||
targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
assertEquals("Expecting a size of 3 software modules in the reuqest", 3,
|
||||
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||
final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action);
|
||||
assertThat(createDistributionSet.getModules()).hasSameSizeAs(downloadAndUpdateRequest.getSoftwareModules());
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
|
||||
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
|
||||
.getSoftwareModules()) {
|
||||
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty());
|
||||
for (final SoftwareModule softwareModule2 : dsA.getModules()) {
|
||||
for (final SoftwareModule softwareModule2 : action.getDistributionSet().getModules()) {
|
||||
assertNotNull("Sofware module ID should be set", softwareModule.getModuleId());
|
||||
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
|
||||
continue;
|
||||
@@ -157,7 +187,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
@Test
|
||||
@Description("Verfies that download and install event with software moduls and artifacts works")
|
||||
public void testSendDownloadRequest() {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
final SoftwareModule module = dsA.getModules().iterator().next();
|
||||
final List<DbArtifact> receivedList = new ArrayList<>();
|
||||
for (final Artifact artifact : testdataFactory.createArtifacts(module.getId())) {
|
||||
@@ -165,14 +195,16 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
receivedList.add(new DbArtifact());
|
||||
}
|
||||
|
||||
final Action action = createAction(dsA);
|
||||
|
||||
Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList);
|
||||
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
|
||||
1L, TENANT, testTarget, 1L, dsA.getModules());
|
||||
action, serviceMatcher.getServiceId());
|
||||
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(
|
||||
targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress());
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
|
||||
final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action);
|
||||
|
||||
assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3,
|
||||
downloadAndUpdateRequest.getSoftwareModules().size());
|
||||
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
|
||||
@@ -201,11 +233,11 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
@Description("Verfies that send cancel event works")
|
||||
public void testSendCancelRequest() {
|
||||
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
|
||||
testTarget, 1L);
|
||||
testTarget, 1L, serviceMatcher.getServiceId());
|
||||
amqpMessageDispatcherService
|
||||
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
|
||||
final Message sendMessage = createArgumentCapture(
|
||||
cancelTargetAssignmentDistributionSetEvent.getTarget().getTargetInfo().getAddress());
|
||||
cancelTargetAssignmentDistributionSetEvent.getEntity().getTargetInfo().getAddress());
|
||||
assertCancelMessage(sendMessage);
|
||||
|
||||
}
|
||||
@@ -219,12 +251,11 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
|
||||
}
|
||||
|
||||
private DownloadAndUpdateRequest assertDownloadAndInstallMessage(final Message sendMessage) {
|
||||
private DownloadAndUpdateRequest assertDownloadAndInstallMessage(final Message sendMessage, final Action action) {
|
||||
assertEventMessage(sendMessage);
|
||||
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage,
|
||||
DownloadAndUpdateRequest.class);
|
||||
assertEquals("The action ID of the downloadAndUpdateRequest event shuold be 1",
|
||||
downloadAndUpdateRequest.getActionId(), Long.valueOf(1));
|
||||
assertEquals(downloadAndUpdateRequest.getActionId(), action.getId());
|
||||
assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL,
|
||||
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
|
||||
assertEquals("Security token of target", downloadAndUpdateRequest.getTargetSecurityToken(), TEST_TOKEN);
|
||||
|
||||
@@ -21,14 +21,14 @@ import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.api.HostnameResolver;
|
||||
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.EventTopic;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
|
||||
import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
|
||||
@@ -40,17 +40,16 @@ import org.eclipse.hawkbit.dmf.json.model.TenantSecurityToken.FileResource;
|
||||
import org.eclipse.hawkbit.repository.ArtifactManagement;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
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.security.SecurityTokenGenerator;
|
||||
@@ -67,7 +66,6 @@ import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
@@ -108,7 +106,7 @@ public class AmqpMessageHandlerServiceTest {
|
||||
private ArtifactRepository artifactRepositoryMock;
|
||||
|
||||
@Mock
|
||||
private Cache cacheMock;
|
||||
private DownloadIdCache downloadIdCache;
|
||||
|
||||
@Mock
|
||||
private HostnameResolver hostnameResolverMock;
|
||||
@@ -120,11 +118,13 @@ public class AmqpMessageHandlerServiceTest {
|
||||
public void before() throws Exception {
|
||||
messageConverter = new Jackson2JsonMessageConverter();
|
||||
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
|
||||
controllerManagementMock, entityFactoryMock);
|
||||
|
||||
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
|
||||
controllerManagementMock, entityFactoryMock);
|
||||
amqpAuthenticationMessageHandlerService = new AmqpAuthenticationMessageHandler(rabbitTemplate,
|
||||
authenticationManagerMock, artifactManagementMock, cacheMock, hostnameResolverMock,
|
||||
authenticationManagerMock, artifactManagementMock, downloadIdCache, hostnameResolverMock,
|
||||
controllerManagementMock);
|
||||
}
|
||||
|
||||
@@ -363,10 +363,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
// for the test the same action can be used
|
||||
when(controllerManagementMock.findOldestActiveActionByTarget(Matchers.any())).thenReturn(Optional.of(action));
|
||||
|
||||
final List<SoftwareModule> softwareModuleList = createSoftwareModuleList();
|
||||
when(controllerManagementMock.findSoftwareModulesByDistributionSet(Matchers.any()))
|
||||
.thenReturn(softwareModuleList);
|
||||
|
||||
final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
|
||||
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
|
||||
final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L);
|
||||
@@ -380,20 +376,19 @@ public class AmqpMessageHandlerServiceTest {
|
||||
verify(controllerManagementMock).updateTargetStatus(Matchers.any(TargetInfo.class),
|
||||
Matchers.isNull(TargetUpdateStatus.class), Matchers.isNotNull(Long.class), Matchers.isNull(URI.class));
|
||||
|
||||
final ArgumentCaptor<TargetAssignDistributionSetEvent> captorTargetAssignDistributionSetEvent = ArgumentCaptor
|
||||
.forClass(TargetAssignDistributionSetEvent.class);
|
||||
verify(amqpMessageDispatcherServiceMock, times(1))
|
||||
.targetAssignDistributionSet(captorTargetAssignDistributionSetEvent.capture());
|
||||
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = captorTargetAssignDistributionSetEvent
|
||||
.getValue();
|
||||
final ArgumentCaptor<String> tenantCaptor = ArgumentCaptor.forClass(String.class);
|
||||
final ArgumentCaptor<Target> targetCaptor = ArgumentCaptor.forClass(Target.class);
|
||||
final ArgumentCaptor<Long> actionIdCaptor = ArgumentCaptor.forClass(Long.class);
|
||||
|
||||
assertThat(targetAssignDistributionSetEvent.getTarget().getControllerId()).as("event has wrong controller id")
|
||||
.isEqualTo("target1");
|
||||
assertThat(targetAssignDistributionSetEvent.getTarget().getSecurityToken())
|
||||
.as("targetoken not filled correctly").isEqualTo(action.getTarget().getSecurityToken());
|
||||
assertThat(targetAssignDistributionSetEvent.getActionId()).as("event has wrong action id").isEqualTo(22L);
|
||||
assertThat(targetAssignDistributionSetEvent.getSoftwareModules()).as("event has wrong sofware modules")
|
||||
.isEqualTo(softwareModuleList);
|
||||
verify(amqpMessageDispatcherServiceMock, times(1)).sendUpdateMessageToTarget(tenantCaptor.capture(),
|
||||
targetCaptor.capture(), actionIdCaptor.capture(), Matchers.any(Collection.class));
|
||||
final String tenant = tenantCaptor.getValue();
|
||||
final String controllerId = targetCaptor.getValue().getControllerId();
|
||||
final Long actionId = actionIdCaptor.getValue();
|
||||
|
||||
assertThat(tenant).as("event has tenant").isEqualTo("DEFAULT");
|
||||
assertThat(controllerId).as("event has wrong controller id").isEqualTo("target1");
|
||||
assertThat(actionId).as("event has wrong action id").isEqualTo(22L);
|
||||
|
||||
}
|
||||
|
||||
@@ -424,14 +419,6 @@ public class AmqpMessageHandlerServiceTest {
|
||||
return messageProperties;
|
||||
}
|
||||
|
||||
private List<SoftwareModule> createSoftwareModuleList() {
|
||||
final List<SoftwareModule> softwareModuleList = new ArrayList<>();
|
||||
final JpaSoftwareModule softwareModule = new JpaSoftwareModule();
|
||||
softwareModule.setId(777L);
|
||||
softwareModuleList.add(softwareModule);
|
||||
return softwareModuleList;
|
||||
}
|
||||
|
||||
private Action createActionWithTarget(final Long targetId, final Status status) throws IllegalAccessException {
|
||||
// is needed for the creation of targets
|
||||
initalizeSecurityTokenGenerator();
|
||||
@@ -440,6 +427,10 @@ public class AmqpMessageHandlerServiceTest {
|
||||
final JpaAction actionMock = mock(JpaAction.class);
|
||||
final JpaTarget targetMock = mock(JpaTarget.class);
|
||||
final TargetInfo targetInfoMock = mock(TargetInfo.class);
|
||||
final DistributionSet distributionSetMock = mock(DistributionSet.class);
|
||||
|
||||
when(distributionSetMock.getId()).thenReturn(1L);
|
||||
when(actionMock.getDistributionSet()).thenReturn(distributionSetMock);
|
||||
when(actionMock.getId()).thenReturn(targetId);
|
||||
when(actionMock.getStatus()).thenReturn(status);
|
||||
when(actionMock.getTenant()).thenReturn("DEFAULT");
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
|
||||
|
||||
# supported: H2, MYSQL
|
||||
hawkbit.server.database=H2
|
||||
|
||||
@@ -35,4 +33,4 @@ H2.spring.datasource.password=sa
|
||||
MYSQL.spring.datasource.url=jdbc:mysql://localhost:3306/sp_test
|
||||
MYSQL.spring.datasource.driverClassName=org.mariadb.jdbc.Driver
|
||||
MYSQL.spring.datasource.username=root
|
||||
MYSQL.spring.datasource.password=
|
||||
MYSQL.spring.datasource.password=
|
||||
@@ -25,9 +25,5 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -13,9 +13,9 @@ import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
|
||||
|
||||
/**
|
||||
@@ -31,16 +31,16 @@ public class HttpDownloadAuthenticationFilter extends AbstractPreAuthenticatedPr
|
||||
private static final Logger LOG = LoggerFactory.getLogger(HttpDownloadAuthenticationFilter.class);
|
||||
|
||||
private final Pattern pattern;
|
||||
private final Cache cache;
|
||||
private final DownloadIdCache downloadIdCache;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param cache
|
||||
* @param downloadIdCache
|
||||
* the cache
|
||||
*/
|
||||
public HttpDownloadAuthenticationFilter(final Cache cache) {
|
||||
this.cache = cache;
|
||||
public HttpDownloadAuthenticationFilter(final DownloadIdCache downloadIdCache) {
|
||||
this.downloadIdCache = downloadIdCache;
|
||||
this.pattern = Pattern.compile(REQUEST_ID_REGEX_PATTERN);
|
||||
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public class HttpDownloadAuthenticationFilter extends AbstractPreAuthenticatedPr
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
return cache.get(id).get();
|
||||
return downloadIdCache.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -32,11 +32,6 @@
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.system;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
@@ -21,13 +23,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
public class MgmtSystemTenantConfigurationValueRequest {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private Object value;
|
||||
private Serializable value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the value of the MgmtSystemTenantConfigurationValueRequest
|
||||
*/
|
||||
public Object getValue() {
|
||||
public Serializable getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -37,7 +39,10 @@ public class MgmtSystemTenantConfigurationValueRequest {
|
||||
* @param value
|
||||
*/
|
||||
public void setValue(final Object value) {
|
||||
this.value = value;
|
||||
if (!(value instanceof Serializable)) {
|
||||
throw new IllegalArgumentException("The value muste be a instance of " + Serializable.class.getName());
|
||||
}
|
||||
this.value = (Serializable) value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-mgmt-api</artifactId>
|
||||
@@ -36,15 +36,14 @@
|
||||
<artifactId>hawkbit-rest-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.plugin</groupId>
|
||||
<artifactId>spring-plugin-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
@@ -66,22 +65,6 @@
|
||||
<classifier>tests</classifier>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
@@ -158,10 +141,10 @@
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -24,12 +24,12 @@ import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtTargetAssignmentR
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.SoftwareManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQuery;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||
@@ -38,6 +37,7 @@ import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
|
||||
@@ -10,20 +10,16 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.cache.DownloadArtifactCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadType;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi;
|
||||
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
|
||||
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.cache.Cache;
|
||||
import org.springframework.cache.Cache.ValueWrapper;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -32,6 +28,8 @@ import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
/**
|
||||
* A resource for download artifacts.
|
||||
*
|
||||
@@ -48,8 +46,7 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
|
||||
private ArtifactRepository artifactRepository;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
private Cache cache;
|
||||
private DownloadIdCache downloadIdCache;
|
||||
|
||||
@Autowired
|
||||
private RequestResponseContextHolder requestResponseContextHolder;
|
||||
@@ -66,13 +63,12 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
|
||||
@ResponseBody
|
||||
public ResponseEntity<Void> downloadArtifactByDownloadId(@PathVariable("downloadId") final String downloadId) {
|
||||
try {
|
||||
final ValueWrapper cacheWrapper = cache.get(downloadId);
|
||||
if (cacheWrapper == null) {
|
||||
final DownloadArtifactCache artifactCache = downloadIdCache.get(downloadId);
|
||||
if (artifactCache == null) {
|
||||
LOGGER.warn("Download Id {} could not be found", downloadId);
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
final DownloadArtifactCache artifactCache = (DownloadArtifactCache) cacheWrapper.get();
|
||||
DbArtifact artifact = null;
|
||||
|
||||
if (DownloadType.BY_SHA1.equals(artifactCache.getDownloadType())) {
|
||||
@@ -87,14 +83,14 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
|
||||
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
try {
|
||||
IOUtils.copy(artifact.getFileInputStream(),
|
||||
ByteStreams.copy(artifact.getFileInputStream(),
|
||||
requestResponseContextHolder.getHttpServletResponse().getOutputStream());
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error("Cannot copy streams", e);
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
||||
}
|
||||
} finally {
|
||||
cache.evict(downloadId);
|
||||
downloadIdCache.evict(downloadId);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
|
||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationValue;
|
||||
@@ -116,11 +117,9 @@ public class MgmtSystemResource implements MgmtSystemRestApi {
|
||||
|
||||
final TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
|
||||
|
||||
final TenantConfigurationValue<Object> updatedValue = tenantConfigurationManagement
|
||||
|
||||
final TenantConfigurationValue<? extends Serializable> updatedValue = tenantConfigurationManagement
|
||||
.addOrUpdateConfiguration(configKey, configurationValueRest.getValue());
|
||||
return new ResponseEntity<>(MgmtSystemMapper.toResponse(keyName, updatedValue), HttpStatus.OK);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -438,7 +438,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
|
||||
// perform request
|
||||
mvc.perform(get("/rest/v1/distributionsets").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[0]._links.self.href",
|
||||
equalTo("http://localhost/rest/v1/distributionsets/" + set.getId())))
|
||||
.andExpect(jsonPath("$.content.[0].id", equalTo(set.getId().intValue())))
|
||||
@@ -469,7 +469,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
|
||||
// perform request
|
||||
mvc.perform(get("/rest/v1/distributionsets/{dsId}", set.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$._links.self.href",
|
||||
equalTo("http://localhost/rest/v1/distributionsets/" + set.getId())))
|
||||
.andExpect(jsonPath("$.id", equalTo(set.getId().intValue())))
|
||||
@@ -522,7 +522,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
|
||||
.perform(post("/rest/v1/distributionsets/").content(JsonBuilder.distributionSets(sets))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0]name", equalTo(one.getName())))
|
||||
.andExpect(jsonPath("[0]description", equalTo(one.getDescription())))
|
||||
.andExpect(jsonPath("[0]type", equalTo(standardDsType.getKey())))
|
||||
@@ -757,7 +757,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId())
|
||||
.contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[1]key", equalTo(knownKey2)))
|
||||
.andExpect(jsonPath("[1]value", equalTo(knownValue2)));
|
||||
@@ -786,7 +786,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
|
||||
mvc.perform(put("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
|
||||
|
||||
final DistributionSetMetadata assertDS = distributionSetManagement.findOne(testDS, knownKey);
|
||||
|
||||
@@ -68,7 +68,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
// generated in this test)
|
||||
mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.key==" + standardDsType.getKey() + ")]$..name",
|
||||
contains(standardDsType.getName())))
|
||||
.andExpect(jsonPath("$.content.[?(@.key==" + standardDsType.getKey() + ")]$..description",
|
||||
@@ -107,7 +107,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
// descending
|
||||
mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON)
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "KEY:DESC")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[0].id", equalTo(testType.getId().intValue())))
|
||||
.andExpect(jsonPath("$.content.[0].name", equalTo("TestName123")))
|
||||
.andExpect(jsonPath("$.content.[0].description", equalTo("Desc1234")))
|
||||
@@ -121,7 +121,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
// ascending
|
||||
mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON)
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "KEY:ASC")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[3].id", equalTo(testType.getId().intValue())))
|
||||
.andExpect(jsonPath("$.content.[3].name", equalTo("TestName123")))
|
||||
.andExpect(jsonPath("$.content.[3].description", equalTo("Desc1234")))
|
||||
@@ -152,7 +152,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
.perform(post("/rest/v1/distributionsettypes/").content(JsonBuilder.distributionSetTypes(types))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo("TestName1"))).andExpect(jsonPath("[0].key", equalTo("test1")))
|
||||
.andExpect(jsonPath("[0].description", equalTo("Desc1")))
|
||||
.andExpect(jsonPath("[0].createdBy", equalTo("uploadTester")))
|
||||
@@ -258,7 +258,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
|
||||
mvc.perform(get("/rest/v1/distributionsettypes/{dstID}/mandatorymoduletypes", testType.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo(osType.getName())))
|
||||
.andExpect(jsonPath("[0].description", equalTo(osType.getDescription())))
|
||||
.andExpect(jsonPath("[0].maxAssignments", equalTo(1))).andExpect(jsonPath("[0].key", equalTo("os")));
|
||||
@@ -277,7 +277,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
|
||||
mvc.perform(get("/rest/v1/distributionsettypes/{dstID}/optionalmoduletypes", testType.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo(appType.getName())))
|
||||
.andExpect(jsonPath("[0].description", equalTo(appType.getDescription())))
|
||||
.andExpect(jsonPath("[0].maxAssignments", equalTo(Integer.MAX_VALUE)))
|
||||
@@ -384,7 +384,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
|
||||
|
||||
mvc.perform(get("/rest/v1/distributionsettypes/{dstId}", testType.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.name", equalTo("TestName123")))
|
||||
.andExpect(jsonPath("$.description", equalTo("Desc1234")))
|
||||
.andExpect(jsonPath("$.createdBy", equalTo("uploadTester")))
|
||||
|
||||
@@ -11,8 +11,8 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.eclipse.hawkbit.cache.CacheConstants;
|
||||
import org.eclipse.hawkbit.cache.DownloadArtifactCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadIdCache;
|
||||
import org.eclipse.hawkbit.cache.DownloadType;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
@@ -23,8 +23,6 @@ import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.annotation.Description;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
@@ -35,8 +33,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
public class MgmtDownloadResourceTest extends AbstractRestIntegrationTestWithMongoDB {
|
||||
|
||||
@Autowired
|
||||
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE)
|
||||
private Cache downloadIdCache;
|
||||
private DownloadIdCache downloadIdCache;
|
||||
|
||||
private final String downloadIdSha1 = "downloadIdSha1";
|
||||
|
||||
@@ -47,7 +44,7 @@ public class MgmtDownloadResourceTest extends AbstractRestIntegrationTestWithMon
|
||||
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("Test");
|
||||
final SoftwareModule softwareModule = distributionSet.getModules().stream().findFirst().get();
|
||||
final Artifact artifact = testdataFactory.createArtifacts(softwareModule.getId()).stream().findFirst().get();
|
||||
final Artifact artifact = testdataFactory.createArtifacts(softwareModule.getId()).stream().findFirst().get();
|
||||
|
||||
downloadIdCache.put(downloadIdSha1, new DownloadArtifactCache(DownloadType.BY_SHA1, artifact.getSha1Hash()));
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
@Description("Testing the empty list is returned if no rollout exists")
|
||||
public void noRolloutReturnsEmptyList() throws Exception {
|
||||
mvc.perform(get("/rest/v1/rollouts")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(0))).andExpect(jsonPath("$.total", equalTo(0)));
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
postRollout("rollout2", 5, dsA.getId(), "name==target2");
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)))
|
||||
.andExpect(jsonPath("content[0].name", equalTo("rollout1")))
|
||||
.andExpect(jsonPath("content[0].status", equalTo("ready")))
|
||||
@@ -159,7 +159,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
postRollout("rollout2", 5, dsA.getId(), "name==target2");
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts?limit=1")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(1))).andExpect(jsonPath("$.total", equalTo(2)));
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
// retrieve rollout groups from created rollout
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(4))).andExpect(jsonPath("$.total", equalTo(4)))
|
||||
.andExpect(jsonPath("$.content[0].status", equalTo("ready")))
|
||||
.andExpect(jsonPath("$.content[1].status", equalTo("ready")))
|
||||
@@ -202,7 +202,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
|
||||
// check rollout is in running state
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("id", equalTo(rollout.getId().intValue())))
|
||||
.andExpect(jsonPath("status", equalTo("running")));
|
||||
}
|
||||
@@ -228,7 +228,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
|
||||
// check rollout is in running state
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("id", equalTo(rollout.getId().intValue())))
|
||||
.andExpect(jsonPath("status", equalTo("paused")));
|
||||
}
|
||||
@@ -258,7 +258,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
|
||||
// check rollout is in running state
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("id", equalTo(rollout.getId().intValue())))
|
||||
.andExpect(jsonPath("status", equalTo("running")));
|
||||
}
|
||||
@@ -320,7 +320,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
// (amountTargets / groupSize = 2)
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups?sort=ID:ASC", rollout.getId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)))
|
||||
.andExpect(jsonPath("$.content[0].status", equalTo("running")))
|
||||
.andExpect(jsonPath("$.content[1].status", equalTo("scheduled")));
|
||||
@@ -344,7 +344,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
// retrieve single rollout group with known ID
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}", rollout.getId(), firstGroup.getId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("id", equalTo(firstGroup.getId().intValue())))
|
||||
.andExpect(jsonPath("status", equalTo("ready"))).andExpect(jsonPath("name", notNullValue()));
|
||||
}
|
||||
@@ -367,7 +367,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
// retrieve targets from the first rollout group with known ID
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(),
|
||||
firstGroup.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(5))).andExpect(jsonPath("$.total", equalTo(5)));
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(), firstGroup.getId())
|
||||
.param("q", "controllerId==" + targets.get(0).getControllerId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(1))).andExpect(jsonPath("$.total", equalTo(1)));
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
// retrieve targets from the first rollout group with known ID
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(),
|
||||
firstGroup.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(5))).andExpect(jsonPath("$.total", equalTo(5)));
|
||||
}
|
||||
|
||||
@@ -462,18 +462,18 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==*2"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(1))).andExpect(jsonPath("$.total", equalTo(1)))
|
||||
.andExpect(jsonPath("$.content[0].name", equalTo(rollout2.getName())));
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==rollout*"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(3))).andExpect(jsonPath("$.total", equalTo(3)));
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==*1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)));
|
||||
|
||||
}
|
||||
@@ -492,19 +492,19 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
// retrieve rollout groups from created rollout
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group-1")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(1))).andExpect(jsonPath("$.total", equalTo(1)))
|
||||
.andExpect(jsonPath("$.content[0].name", equalTo("group-1")));
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group*")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(4))).andExpect(jsonPath("$.total", equalTo(4)));
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group-1,name==group-2"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)));
|
||||
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
|
||||
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
|
||||
.andExpect(jsonPath("$.size", equalTo(random.length)))
|
||||
@@ -213,7 +213,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
|
||||
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
|
||||
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("orig"))).andExpect(status().isCreated());
|
||||
@@ -237,7 +237,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.param("filename", "customFilename").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("customFilename"))).andExpect(status().isCreated());
|
||||
|
||||
// check result in db...
|
||||
@@ -341,7 +341,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
// perform test
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(artifact.getId().intValue())))
|
||||
.andExpect(jsonPath("$.size", equalTo(random.length)))
|
||||
.andExpect(jsonPath("$.hashes.md5", equalTo(artifact.getMd5Hash())))
|
||||
@@ -369,7 +369,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.[0].id", equalTo(artifact.getId().intValue())))
|
||||
.andExpect(jsonPath("$.[0].size", equalTo(random.length)))
|
||||
.andExpect(jsonPath("$.[0].hashes.md5", equalTo(artifact.getMd5Hash())))
|
||||
@@ -538,7 +538,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].name", contains("name1")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].version", contains("version1")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].description", contains("description1")))
|
||||
@@ -623,7 +623,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
// only by name, only one exists per name
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=name==osName1").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].name", contains("osName1")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].version", contains("1.0.0")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].description", contains("description1")))
|
||||
@@ -634,7 +634,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
// by type, 2 software modules per type exists
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=type==application").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + ah1.getId() + ")].name", contains("appName1")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + ah1.getId() + ")].version", contains("3.0.0")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + ah1.getId() + ")].description", contains("description1")))
|
||||
@@ -650,7 +650,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
// by type and version=2.0.0 -> only one result
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=type==runtime;version==2.0.0").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].name", contains("runtimeName1")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].version", contains("2.0.0")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].description", contains("description1")))
|
||||
@@ -660,7 +660,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
// by type and version range >=2.0.0 -> 2 result
|
||||
mvc.perform(get("/rest/v1/softwaremodules?q=type==runtime;version=ge=2.0.0").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].name", contains("runtimeName1")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].version", contains("2.0.0")))
|
||||
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].description", contains("description1")))
|
||||
@@ -691,14 +691,14 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Tests GET request on /rest/v1/softwaremodules/{smId}.")
|
||||
public void getSoftareModule() throws Exception {
|
||||
public void getSoftwareModule() throws Exception {
|
||||
SoftwareModule os = entityFactory.generateSoftwareModule(osType, "name1", "version1", "description1",
|
||||
"vendor1");
|
||||
os = softwareManagement.createSoftwareModule(os);
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}", os.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.name", equalTo("name1"))).andExpect(jsonPath("$.version", equalTo("version1")))
|
||||
.andExpect(jsonPath("$.description", equalTo("description1")))
|
||||
.andExpect(jsonPath("$.vendor", equalTo("vendor1"))).andExpect(jsonPath("$.type", equalTo("os")))
|
||||
@@ -718,7 +718,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}", jvm.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.name", equalTo("name1"))).andExpect(jsonPath("$.version", equalTo("version1")))
|
||||
.andExpect(jsonPath("$.description", equalTo("description1")))
|
||||
.andExpect(jsonPath("$.vendor", equalTo("vendor1"))).andExpect(jsonPath("$.type", equalTo("runtime")))
|
||||
@@ -738,7 +738,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}", ah.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.name", equalTo("name1"))).andExpect(jsonPath("$.version", equalTo("version1")))
|
||||
.andExpect(jsonPath("$.description", equalTo("description1")))
|
||||
.andExpect(jsonPath("$.vendor", equalTo("vendor1")))
|
||||
@@ -778,7 +778,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
.perform(post("/rest/v1/softwaremodules/").content(JsonBuilder.softwareModules(modules))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo("name1")))
|
||||
.andExpect(jsonPath("[0].version", equalTo("version1")))
|
||||
.andExpect(jsonPath("[0].description", equalTo("description1")))
|
||||
@@ -941,7 +941,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
|
||||
mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).contentType(MediaType.APPLICATION_JSON)
|
||||
.content(jsonArray.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
.andExpect(jsonPath("[1]key", equalTo(knownKey2)))
|
||||
.andExpect(jsonPath("[1]value", equalTo(knownValue2)));
|
||||
@@ -971,7 +971,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
|
||||
mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
|
||||
|
||||
final SoftwareModuleMetadata assertDS = softwareManagement.findSoftwareModuleMetadata(sm.getId(), knownKey);
|
||||
|
||||
@@ -64,7 +64,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[?(@.key==" + osType.getKey() + ")].name", contains(osType.getName())))
|
||||
.andExpect(jsonPath("$.content.[?(@.key==" + osType.getKey() + ")].description",
|
||||
contains(osType.getDescription())))
|
||||
@@ -108,7 +108,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
|
||||
mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON)
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "MAXASSIGNMENTS:DESC"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[1].id", equalTo(testType.getId().intValue())))
|
||||
.andExpect(jsonPath("$.content.[1].name", equalTo("TestName123")))
|
||||
.andExpect(jsonPath("$.content.[1].description", equalTo("Desc1234")))
|
||||
@@ -124,7 +124,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
|
||||
mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON)
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "MAXASSIGNMENTS:ASC"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.content.[2].id", equalTo(testType.getId().intValue())))
|
||||
.andExpect(jsonPath("$.content.[2].name", equalTo("TestName123")))
|
||||
.andExpect(jsonPath("$.content.[2].description", equalTo("Desc1234")))
|
||||
@@ -171,7 +171,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
|
||||
.perform(post("/rest/v1/softwaremoduletypes/").content(JsonBuilder.softwareModuleTypes(types))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo("TestName1"))).andExpect(jsonPath("[0].key", equalTo("test1")))
|
||||
.andExpect(jsonPath("[0].description", equalTo("Desc1")))
|
||||
.andExpect(jsonPath("[0].createdBy", equalTo("uploadTester")))
|
||||
@@ -214,7 +214,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremoduletypes/{smtId}", testType.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.name", equalTo("TestName123")))
|
||||
.andExpect(jsonPath("$.description", equalTo("Desc1234")))
|
||||
.andExpect(jsonPath("$.maxAssignments", equalTo(5)))
|
||||
|
||||
@@ -8,37 +8,30 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static org.fest.assertions.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.model.*;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||
import org.eclipse.hawkbit.rest.exception.MessageNotReadableException;
|
||||
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Slice;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
@@ -51,8 +44,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
@Stories("Target Filter Query Resource")
|
||||
public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTest {
|
||||
|
||||
private static final String TARGET_DESCRIPTION_TEST = "created in test";
|
||||
|
||||
private static final String JSON_PATH_ROOT = "$";
|
||||
|
||||
// fields, attributes
|
||||
@@ -75,17 +66,16 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
private static final String JSON_PATH_QUERY = JSON_PATH_ROOT + JSON_PATH_FIELD_QUERY;
|
||||
private static final String JSON_PATH_AUTO_ASSIGN_DS = JSON_PATH_ROOT + JSON_PATH_FIELD_AUTO_ASSIGN_DS;
|
||||
|
||||
|
||||
@Test
|
||||
@Description("Ensures that deletion is executed if permitted.")
|
||||
public void deleteTargetFilterQueryReturnsOK() throws Exception {
|
||||
final String filterName = "filter_01";
|
||||
TargetFilterQuery filterQuery = createSingleTargetFilterQuery(filterName, "name=test_01");
|
||||
final TargetFilterQuery filterQuery = createSingleTargetFilterQuery(filterName, "name=test_01");
|
||||
|
||||
mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId()))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
TargetFilterQuery tfq = targetFilterQueryManagement.findTargetFilterQueryById(filterQuery.getId());
|
||||
final TargetFilterQuery tfq = targetFilterQueryManagement.findTargetFilterQueryById(filterQuery.getId());
|
||||
assertThat(tfq).isNull();
|
||||
}
|
||||
|
||||
@@ -116,7 +106,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
final String body = new JSONObject().put("query", filterQuery2).toString();
|
||||
|
||||
// prepare
|
||||
TargetFilterQuery tfq = createSingleTargetFilterQuery(filterName, filterQuery);
|
||||
final TargetFilterQuery tfq = createSingleTargetFilterQuery(filterName, filterQuery);
|
||||
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -124,7 +114,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
.andExpect(jsonPath("$.query", equalTo(filterQuery2)))
|
||||
.andExpect(jsonPath("$.name", equalTo(filterName)));
|
||||
|
||||
TargetFilterQuery tfqCheck = targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId());
|
||||
final TargetFilterQuery tfqCheck = targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId());
|
||||
assertThat(tfqCheck.getQuery()).isEqualTo(filterQuery2);
|
||||
assertThat(tfqCheck.getName()).isEqualTo(filterName);
|
||||
}
|
||||
@@ -149,12 +139,11 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
.andExpect(jsonPath("$.query", equalTo(filterQuery)))
|
||||
.andExpect(jsonPath("$.name", equalTo(filterName2)));
|
||||
|
||||
TargetFilterQuery tfqCheck = targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId());
|
||||
final TargetFilterQuery tfqCheck = targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId());
|
||||
assertThat(tfqCheck.getQuery()).isEqualTo(filterQuery);
|
||||
assertThat(tfqCheck.getName()).isEqualTo(filterName2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Description("Ensures that request returns list of filters in defined format.")
|
||||
public void getTargetFilterQueryWithoutAdditionalRequestParameters() throws Exception {
|
||||
@@ -250,7 +239,8 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
final String knownQuery = "name=test01";
|
||||
final String knownName = "someName";
|
||||
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery);
|
||||
final String hrefPrefix = "http://localhost"+MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING+"/" + tfq.getId();
|
||||
final String hrefPrefix = "http://localhost" + MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"
|
||||
+ tfq.getId();
|
||||
// test
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -302,13 +292,15 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery);
|
||||
|
||||
mvc.perform(post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"+tfq.getId()+"/autoAssignDS")
|
||||
mvc.perform(post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS")
|
||||
.content("{\"id\":" + set.getId() + "}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet()).isEqualTo(set);
|
||||
assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet())
|
||||
.isEqualTo(set);
|
||||
|
||||
final String hrefPrefix = "http://localhost"+MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING+"/" + tfq.getId();
|
||||
final String hrefPrefix = "http://localhost" + MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"
|
||||
+ tfq.getId();
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -336,20 +328,18 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
|
||||
assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet())
|
||||
.isEqualTo(set);
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"+tfq.getId()+"/autoAssignDS"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath(JSON_PATH_NAME, equalTo(dsName)));
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS"))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath(JSON_PATH_NAME, equalTo(dsName)));
|
||||
|
||||
mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"+tfq.getId()+"/autoAssignDS"))
|
||||
mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet())
|
||||
.isNull();
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"+tfq.getId()+"/autoAssignDS"))
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
|
||||
}
|
||||
|
||||
private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) {
|
||||
|
||||
@@ -735,7 +735,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
|
||||
.perform(post("/rest/v1/targets/").content(JsonBuilder.targets(targets, true))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0].name", equalTo("testname1")))
|
||||
.andExpect(jsonPath("[0].controllerId", equalTo("id1")))
|
||||
.andExpect(jsonPath("[0].description", equalTo("testid1")))
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
logging.level.=INFO
|
||||
logging.level.org.eclipse.persistence=ERROR
|
||||
|
||||
# supported: H2, MYSQL
|
||||
hawkbit.server.database=H2
|
||||
|
||||
@@ -46,4 +49,4 @@ MYSQL.spring.datasource.password=
|
||||
|
||||
# SP Controller configuration
|
||||
hawkbit.controller.pollingTime=00:01:00
|
||||
hawkbit.controller.pollingOverdueTime=00:01:00
|
||||
hawkbit.controller.pollingOverdueTime=00:01:00
|
||||
@@ -1,35 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
which accompanies this distribution, and is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
<configuration>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||
|
||||
<logger name="org.eclipse.hawkbit.eventbus.DeadEventListener" level="WARN" />
|
||||
<Logger name="org.springframework.boot.actuate.audit.listener.AuditListener" level="WARN" />
|
||||
|
||||
<Logger name="org.hibernate.validator.internal.util.Version" level="WARN" />
|
||||
|
||||
<Logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN" />
|
||||
<Logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN" />
|
||||
<Logger name="org.apache.tomcat.jdbc.pool.ConnectionPool" level="DEBUG" />
|
||||
<Logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR" />
|
||||
|
||||
|
||||
<!-- <Logger name="org.eclipse.hawkbit.rest.util.MockMvcResultPrinter" level="DEBUG" /> -->
|
||||
|
||||
<!-- Security Log with hints on potential attacks -->
|
||||
<logger name="server-security" level="INFO" />
|
||||
|
||||
<Root level="INFO">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</Root>
|
||||
|
||||
</configuration>
|
||||
@@ -8,7 +8,8 @@
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
@@ -36,6 +37,10 @@
|
||||
<groupId>org.springframework.hateoas</groupId>
|
||||
<artifactId>spring-hateoas</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-bus</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Optional -->
|
||||
<dependency>
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Optional;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException;
|
||||
@@ -25,7 +25,6 @@ import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetInfo;
|
||||
@@ -34,8 +33,6 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
/**
|
||||
* Service layer for all operations of the DDI API (with access permissions only
|
||||
* for the controller).
|
||||
@@ -59,7 +56,7 @@ public interface ControllerManagement {
|
||||
Action addCancelActionStatus(@NotNull ActionStatus actionStatus);
|
||||
|
||||
/**
|
||||
* Sends the download progress and notifies the {@link EventBus} with a
|
||||
* Sends the download progress and notifies the event publisher with a
|
||||
* {@link DownloadProgressEvent}.
|
||||
*
|
||||
* @param statusId
|
||||
@@ -148,19 +145,6 @@ public interface ControllerManagement {
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
Target findOrRegisterTargetIfItDoesNotexist(@NotEmpty String controllerId, URI address);
|
||||
|
||||
/**
|
||||
* Retrieves all {@link SoftwareModule}s which are assigned to the given
|
||||
* {@link DistributionSet}.
|
||||
*
|
||||
* @param distributionSet
|
||||
* the distribution set which should be assigned to the returned
|
||||
* {@link SoftwareModule}s
|
||||
* @return a list of {@link SoftwareModule}s assigned to given
|
||||
* {@code distributionSet}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
List<SoftwareModule> findSoftwareModulesByDistributionSet(@NotNull DistributionSet distributionSet);
|
||||
|
||||
/**
|
||||
* Retrieves last {@link Action} for a download of an artifact of given
|
||||
* module and target.
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
|
||||
@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.repository;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.eventbus.event.RolloutGroupCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutGroupCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfiguration;
|
||||
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
|
||||
@@ -40,7 +42,8 @@ public interface TenantConfigurationManagement {
|
||||
* if the property cannot be converted to the given
|
||||
*/
|
||||
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
|
||||
<T> TenantConfigurationValue<T> addOrUpdateConfiguration(TenantConfigurationKey configurationKey, T value);
|
||||
<T extends Serializable> TenantConfigurationValue<T> addOrUpdateConfiguration(
|
||||
TenantConfigurationKey configurationKey, T value);
|
||||
|
||||
/**
|
||||
* Build the tenant configuration by the given key
|
||||
@@ -55,8 +58,8 @@ public interface TenantConfigurationManagement {
|
||||
* or returns the tenant configuration value
|
||||
*/
|
||||
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
|
||||
<T> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(TenantConfigurationKey configurationKey,
|
||||
Class<T> propertyType, TenantConfiguration tenantConfiguration);
|
||||
<T extends Serializable> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(
|
||||
TenantConfigurationKey configurationKey, Class<T> propertyType, TenantConfiguration tenantConfiguration);
|
||||
|
||||
/**
|
||||
* Deletes a specific configuration for the current tenant. Does nothing in
|
||||
@@ -87,7 +90,7 @@ public interface TenantConfigurationManagement {
|
||||
* {@code propertyType}
|
||||
*/
|
||||
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
|
||||
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey);
|
||||
<T extends Serializable> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey);
|
||||
|
||||
/**
|
||||
* Retrieves a configuration value from the e.g. tenant overwritten
|
||||
@@ -113,7 +116,7 @@ public interface TenantConfigurationManagement {
|
||||
* {@code propertyType}
|
||||
*/
|
||||
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
|
||||
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey,
|
||||
<T extends Serializable> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey,
|
||||
Class<T> propertyType);
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.eventbus.event;
|
||||
package org.eclipse.hawkbit.repository.event;
|
||||
|
||||
/**
|
||||
* Events to be published to refresh data on UI.
|
||||
@@ -6,22 +6,18 @@
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.cache;
|
||||
package org.eclipse.hawkbit.repository.event;
|
||||
|
||||
/**
|
||||
* Cache Constants.
|
||||
*
|
||||
*
|
||||
* An event declaration which holds an revision for each event so consumers have
|
||||
* the chance to know if they might already retrieved a newer event.
|
||||
*
|
||||
*/
|
||||
public final class CacheConstants {
|
||||
@FunctionalInterface
|
||||
public interface TenantAwareEvent {
|
||||
|
||||
/**
|
||||
* Constant for download cache id.
|
||||
* @return the tenant of the event.
|
||||
*/
|
||||
public static final String DOWNLOAD_ID_CACHE = "DowonloadIdCache";
|
||||
|
||||
private CacheConstants() {
|
||||
}
|
||||
|
||||
String getTenant();
|
||||
}
|
||||
@@ -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.repository.event.remote;
|
||||
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
|
||||
/**
|
||||
* Defines the remote event for deletion of {@link DistributionSet}.
|
||||
*/
|
||||
public class DistributionSetDeletedEvent extends RemoteIdEvent {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public DistributionSetDeletedEvent() {
|
||||
// for serialization libs like jackson
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant
|
||||
* @param entityId
|
||||
* the entity id
|
||||
* @param applicationId
|
||||
* the origin application id
|
||||
*/
|
||||
public DistributionSetDeletedEvent(final String tenant, final Long entityId, final String applicationId) {
|
||||
super(entityId, tenant, applicationId);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user