Feature horizontal scalability (#305)

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Dennis Melzer
2016-11-03 15:53:53 +01:00
committed by Kai Zimmermann
parent 07cb62a3dd
commit 866bc72114
287 changed files with 4219 additions and 5046 deletions

View File

@@ -63,7 +63,6 @@ $ java -jar ./examples/hawkbit-example-mgmt-simulator/target/hawkbit-example-mgm
* `examples` : hawkBit examples * `examples` : hawkBit examples
* `hawkbit-artifact-repository-mongo` : Artifact repository implementation to mongoDB. * `hawkbit-artifact-repository-mongo` : Artifact repository implementation to mongoDB.
* `hawkbit-autoconfigure` : Spring-boot auto-configuration. * `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-core` : Core elements for internal interfaces and utility classes.
* `hawkbit-ddi-api` : The hawkBit DDI API. * `hawkbit-ddi-api` : The hawkBit DDI API.
* `hawkbit-ddi-dl-api` : The hawkBit DDI Download API. * `hawkbit-ddi-dl-api` : The hawkBit DDI Download API.

View File

@@ -9,4 +9,3 @@ Example projects that show how _hawkBit_ can be used to create, run or access an
- `hawkbit-example-ddi-feign-client` : Example _hawkBit_ DDI client based on the _hawkBit_ DDI API. - `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-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.

View File

@@ -93,16 +93,6 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId> <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>
<dependency> <dependency>
<groupId>org.springframework.security</groupId> <groupId>org.springframework.security</groupId>

View File

@@ -8,14 +8,10 @@ package org.eclipse.hawkbit.app;
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
*/ */
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.hawkbit.ui.HawkbitUI; import org.eclipse.hawkbit.ui.HawkbitUI;
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy; import org.eclipse.hawkbit.ui.push.EventPushStrategy;
import org.eclipse.hawkbit.ui.push.UIEventProvider; import org.vaadin.spring.events.EventBus.SessionEventBus;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.eventbus.EventBus;
import com.vaadin.annotations.Push; import com.vaadin.annotations.Push;
import com.vaadin.annotations.Theme; import com.vaadin.annotations.Theme;
import com.vaadin.annotations.Title; import com.vaadin.annotations.Title;
@@ -39,9 +35,15 @@ public class MyUI extends HawkbitUI {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Autowired /**
public MyUI(final ScheduledExecutorService executorService, final EventBus systemEventBus, * Constructor
final org.vaadin.spring.events.EventBus.SessionEventBus eventBus, final UIEventProvider provider) { *
super(new DelayedEventBusPushStrategy(executorService, eventBus, systemEventBus, provider)); * @param pushStrategy
* the push strategy
* @param eventBus
* the event bus
*/
public MyUI(final EventPushStrategy pushStrategy, final SessionEventBus eventBus) {
super(pushStrategy, eventBus);
} }
} }

View File

@@ -105,11 +105,11 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId> <artifactId>feign-jackson</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId> <artifactId>feign-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -12,9 +12,6 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
/** /**
* Event description which indicates the initialization of an update. * Event description which indicates the initialization of an update.
*
* @author Michael Hirsch
*
*/ */
public class InitUpdate { public class InitUpdate {

View File

@@ -13,10 +13,7 @@ import java.util.Collection;
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice; import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
/** /**
* Event description which indicates an poll time update. * Event description which indicates a poll time update.
*
* @author Michael Hirsch
*
*/ */
public class NextPollCounterUpdate { public class NextPollCounterUpdate {

View File

@@ -18,7 +18,6 @@ import org.eclipse.hawkbit.simulator.DeviceSimulatorRepository;
import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory; import org.eclipse.hawkbit.simulator.SimulatedDeviceFactory;
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus; import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
import org.eclipse.hawkbit.simulator.amqp.AmqpProperties; 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.InitUpdate;
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate; import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
import org.eclipse.hawkbit.simulator.event.ProgressUpdate; import org.eclipse.hawkbit.simulator.event.ProgressUpdate;
@@ -58,9 +57,6 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
@SuppressWarnings("squid:MaximumInheritanceDepth") @SuppressWarnings("squid:MaximumInheritanceDepth")
public class SimulatorView extends VerticalLayout implements View { public class SimulatorView extends VerticalLayout implements View {
/**
*
*/
private static final String HTML_SPAN = ";</span>"; private static final String HTML_SPAN = ";</span>";
private static final String NEXT_POLL_COUNTER_SEC_COL = "nextPollCounterSec"; 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; private static final long serialVersionUID = 1L;
@Autowired
private transient SpSenderService spSenderService;
@Autowired @Autowired
private transient DeviceSimulatorRepository repository; private transient DeviceSimulatorRepository repository;
@Autowired @Autowired
private transient SimulatedDeviceFactory deviceFactory; private transient SimulatedDeviceFactory deviceFactory;

View File

@@ -14,7 +14,6 @@ security.user.password=${BASIC_PASSWORD:admin}
security.user.role=USER security.user.role=USER
security.require-ssl=false security.require-ssl=false
security.enable-csrf=false security.enable-csrf=false
security.basic.enabled=true
security.basic.realm=DeviceSimulator security.basic.realm=DeviceSimulator
security.basic.path= /** security.basic.path= /**
security.basic.authorize-mode=ROLE security.basic.authorize-mode=ROLE

View File

@@ -12,16 +12,7 @@
<configuration> <configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" /> <include resource="org/springframework/boot/logging/logback/base.xml" />
<logger name="org.eclipse.hawkbit.eventbus.DeadEventListener" level="WARN" /> <Root level="ERROR">
<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">
<appender-ref ref="CONSOLE" /> <appender-ref ref="CONSOLE" />
</Root> </Root>

View File

@@ -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-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). - **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. - 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>
```

View File

@@ -97,7 +97,6 @@
<artifactId>hawkbit-repository-jpa</artifactId> <artifactId>hawkbit-repository-jpa</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<!-- Spring --> <!-- Spring -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@@ -8,14 +8,10 @@
*/ */
package org.eclipse.hawkbit.app; package org.eclipse.hawkbit.app;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.hawkbit.ui.HawkbitUI; import org.eclipse.hawkbit.ui.HawkbitUI;
import org.eclipse.hawkbit.ui.push.DelayedEventBusPushStrategy; import org.eclipse.hawkbit.ui.push.EventPushStrategy;
import org.eclipse.hawkbit.ui.push.UIEventProvider; import org.vaadin.spring.events.EventBus.SessionEventBus;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.eventbus.EventBus;
import com.vaadin.annotations.Push; import com.vaadin.annotations.Push;
import com.vaadin.shared.communication.PushMode; import com.vaadin.shared.communication.PushMode;
import com.vaadin.shared.ui.ui.Transport; import com.vaadin.shared.ui.ui.Transport;
@@ -35,12 +31,18 @@ import com.vaadin.spring.annotation.SpringUI;
// Vaadin. // Vaadin.
@SuppressWarnings({ "squid:MaximumInheritanceDepth" }) @SuppressWarnings({ "squid:MaximumInheritanceDepth" })
public class MyUI extends HawkbitUI { public class MyUI extends HawkbitUI {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@Autowired /**
public MyUI(final ScheduledExecutorService scheduledExecutorService, final EventBus systemEventBus, * Constructor
final org.vaadin.spring.events.EventBus.SessionEventBus eventBus, final UIEventProvider provider) { *
super(new DelayedEventBusPushStrategy(scheduledExecutorService, eventBus, systemEventBus, provider)); * @param pushStrategy
* the push strategy
* @param eventBus
* the event bus
*/
public MyUI(final EventPushStrategy pushStrategy, final SessionEventBus eventBus) {
super(pushStrategy, eventBus);
} }
} }

View File

@@ -22,7 +22,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId> <artifactId>feign-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>
@@ -46,7 +46,7 @@
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId> <artifactId>feign-slf4j</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -41,11 +41,11 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId> <artifactId>feign-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId> <artifactId>feign-jackson</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -36,12 +36,11 @@
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId> <artifactId>feign-core</artifactId>
<!-- need to overwrite for the interface inheritance feature of feign-core -->
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.netflix.feign</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>feign-jackson</artifactId> <artifactId>feign-jackson</artifactId>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -42,22 +42,4 @@
<module>hawkbit-example-mgmt-feign-client</module> <module>hawkbit-example-mgmt-feign-client</module>
<module>hawkbit-example-mgmt-simulator</module> <module>hawkbit-example-mgmt-simulator</module>
</modules> </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> </project>

View File

@@ -26,13 +26,7 @@
<version>${project.version}</version> <version>${project.version}</version>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-cache-redis</artifactId>
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-dmf-amqp</artifactId> <artifactId>hawkbit-dmf-amqp</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
@@ -83,5 +77,15 @@
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </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> </dependencies>
</project> </project>

View File

@@ -8,17 +8,21 @@
*/ */
package org.eclipse.hawkbit.autoconfigure.cache; package org.eclipse.hawkbit.autoconfigure.cache;
import static com.google.common.cache.CacheBuilder.newBuilder;
import java.util.Collection; import java.util.Collection;
import java.util.concurrent.Callable;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.hawkbit.cache.TenancyCacheManager; import org.eclipse.hawkbit.cache.TenancyCacheManager;
import org.eclipse.hawkbit.cache.TenantAwareCacheManager; import org.eclipse.hawkbit.cache.TenantAwareCacheManager;
import org.eclipse.hawkbit.tenancy.TenantAware; import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired; 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.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache; import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.guava.GuavaCacheManager; import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.cache.interceptor.CacheOperationInvocationContext; 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.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import com.google.common.cache.CacheBuilder;
/** /**
* A configuration for configuring the spring {@link CacheManager} for specific * A configuration for configuring the spring {@link CacheManager} for specific
* multi-tenancy caching. The caches between tenants must not interfere each * multi-tenancy caching. The caches between tenants must not interfere each
@@ -37,33 +43,58 @@ import org.springframework.context.annotation.Primary;
*/ */
@Configuration @Configuration
@EnableCaching @EnableCaching
public class CacheAutoConfiguration extends CachingConfigurerSupport { public class CacheAutoConfiguration {
@Autowired @Autowired
private TenantAware tenantAware; private TenantAware tenantAware;
@Autowired
@Qualifier("directCacheManager")
private CacheManager directCacheManager;
/** /**
* @return the default cache manager bean if none other cache manager is * @return the default cache manager bean if none other cache manager is
* existing. * existing.
*/ */
@Override
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
@Primary @Primary
public TenancyCacheManager cacheManager() { public TenancyCacheManager cacheManager() {
return new TenantAwareCacheManager(directCacheManager(), tenantAware); return new TenantAwareCacheManager(directCacheManager, tenantAware);
} }
/** /**
* @return the direct cache manager to access without tenant aware check, * A separate configuration of the direct cache manager for the
* cause in sometimes it's necessary to access the cache directly * {@link TenantAwareCacheManager} that it can get overridden by another
* without having the current tenant, e.g. initial creation of * configuration.
* tenant
*/ */
@Bean(name = "directCacheManager") @Configuration
@ConditionalOnMissingBean(name = "directCacheManager") @EnableConfigurationProperties(CacheProperties.class)
public CacheManager directCacheManager() { static class DirectCacheManagerConfiguration {
return new GuavaCacheManager();
@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(); delegate.clear();
} }
@Override
public <T> T get(final Object key, final Callable<T> valueLoader) {
return delegate.get(key, valueLoader);
}
} }
} }

View 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;
}
}

View File

@@ -8,10 +8,10 @@
*/ */
package org.eclipse.hawkbit.autoconfigure.cache; package org.eclipse.hawkbit.autoconfigure.cache;
import org.eclipse.hawkbit.cache.CacheConstants; import org.eclipse.hawkbit.cache.DefaultDownloadIdCache;
import org.eclipse.hawkbit.cache.TenancyCacheManager; import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.springframework.beans.factory.annotation.Autowired; 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.cache.CacheManager;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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. * A configuration for configuring a cache for the download id's.
* *
* This is done by providing a named cache. * This is done by providing a named cache.
*
*
*
*/ */
@Configuration @Configuration
public class DownloadIdCacheAutoConfiguration { public class DownloadIdCacheAutoConfiguration {
@@ -31,16 +28,18 @@ public class DownloadIdCacheAutoConfiguration {
private CacheManager cacheManager; 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) @Bean
public Cache downloadIdCache() { @ConditionalOnMissingBean
if (cacheManager instanceof TenancyCacheManager) { public DownloadIdCache downloadIdCache() {
return ((TenancyCacheManager) cacheManager).getDirectCache(CacheConstants.DOWNLOAD_ID_CACHE); return new DefaultDownloadIdCache(cacheManager);
}
return cacheManager.getCache(CacheConstants.DOWNLOAD_ID_CACHE);
} }
} }

View File

@@ -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 {
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}

View File

@@ -10,7 +10,7 @@ package org.eclipse.hawkbit.autoconfigure.repository;
import org.eclipse.hawkbit.EnableJpaRepository; import org.eclipse.hawkbit.EnableJpaRepository;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; 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.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;

View File

@@ -23,7 +23,7 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import javax.servlet.ServletResponse;
import org.eclipse.hawkbit.ExcludePathAwareShallowETagFilter; 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;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken; import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
@@ -47,12 +47,10 @@ import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; 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.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean; import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
import org.springframework.cache.Cache;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
@@ -436,8 +434,7 @@ public class SecurityManagedConfiguration {
private DdiSecurityProperties ddiSecurityConfiguration; private DdiSecurityProperties ddiSecurityConfiguration;
@Autowired @Autowired
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE) private DownloadIdCache downloadIdCache;
private Cache downloadIdCache;
@Override @Override
protected void configure(final HttpSecurity http) throws Exception { protected void configure(final HttpSecurity http) throws Exception {

View File

@@ -9,15 +9,20 @@
package org.eclipse.hawkbit.autoconfigure.ui; package org.eclipse.hawkbit.autoconfigure.ui;
import org.eclipse.hawkbit.DistributedResourceBundleMessageSource; 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.HawkbitEventProvider;
import org.eclipse.hawkbit.ui.push.UIEventProvider; import org.eclipse.hawkbit.ui.push.UIEventProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.vaadin.spring.annotation.EnableVaadinExtensions; import org.vaadin.spring.annotation.EnableVaadinExtensions;
import org.vaadin.spring.events.annotation.EnableEventBus; import org.vaadin.spring.events.annotation.EnableEventBus;
import org.vaadin.spring.security.annotation.EnableVaadinSecurity; import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
import com.vaadin.spring.annotation.UIScope;
/** /**
* The hawkbit-ui autoconfiguration. * The hawkbit-ui autoconfiguration.
*/ */
@@ -48,4 +53,22 @@ public class UIAutoConfiguration {
return new HawkbitEventProvider(); 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;
}
} }

View File

@@ -24,28 +24,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
@Configuration @Configuration
public class WebMvcAutoConfiguration extends WebMvcConfigurerAdapter { public class WebMvcAutoConfiguration extends WebMvcConfigurerAdapter {
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
* #configurePathMatch
* (org.springframework.web.servlet.config.annotation.PathMatchConfigurer)
*/
@Override @Override
public void configurePathMatch(final PathMatchConfigurer configurer) { public void configurePathMatch(final PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false); configurer.setUseSuffixPatternMatch(false);
configurer.setUseRegisteredSuffixPatternMatch(false); configurer.setUseRegisteredSuffixPatternMatch(false);
} }
/*
* (non-Javadoc)
*
* @see org.springframework.web.servlet.config.annotation.
* WebMvcConfigurerAdapter# configureContentNegotiation
* (org.springframework.web.servlet.config.annotation.
* ContentNegotiationConfigurer)
*/
@Override @Override
public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false); configurer.favorPathExtension(false);

View File

@@ -7,9 +7,8 @@ org.eclipse.hawkbit.autoconfigure.url.PropertyHostnameResolverAutoConfiguration,
org.eclipse.hawkbit.autoconfigure.web.WebMvcAutoConfiguration,\ org.eclipse.hawkbit.autoconfigure.web.WebMvcAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration,\ org.eclipse.hawkbit.autoconfigure.cache.CacheAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.DownloadIdCacheAutoConfiguration,\ 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.scheduling.AsyncConfigurerAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\ org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration,\ org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration,\
org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementConfiguration org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementConfiguration

View File

@@ -14,6 +14,19 @@ security.basic.realm=HawkBit
security.user.name=admin security.user.name=admin
security.user.password=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 ### JPA / Datasource - START
spring.jpa.database=H2 spring.jpa.database=H2
spring.jpa.show-sql=false spring.jpa.show-sql=false

View File

@@ -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>

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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);
}
}

View File

@@ -53,6 +53,16 @@
<artifactId>allure-junit-adaptor</artifactId> <artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </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> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>

View 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);
}
}

View File

@@ -9,10 +9,7 @@
package org.eclipse.hawkbit.cache; package org.eclipse.hawkbit.cache;
/** /**
* Cache Object for download a Artifact. * Cache Object for downloading an artifact.
*
*
*
*/ */
public class DownloadArtifactCache { public class DownloadArtifactCache {

View 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);
}

View File

@@ -10,9 +10,6 @@ package org.eclipse.hawkbit.cache;
/** /**
* The type of the id which is saved. * The type of the id which is saved.
*
*
*
*/ */
public enum DownloadType { public enum DownloadType {
BY_SHA1 BY_SHA1

View File

@@ -12,7 +12,6 @@ import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
/** /**
*
* A cache interface which handles multi tenancy. * A cache interface which handles multi tenancy.
*/ */
public interface TenancyCacheManager extends CacheManager { public interface TenancyCacheManager extends CacheManager {
@@ -36,5 +35,4 @@ public interface TenancyCacheManager extends CacheManager {
* the tenant to evict caches * the tenant to evict caches
*/ */
void evictCaches(final String tenant); void evictCaches(final String tenant);
} }

View File

@@ -8,8 +8,9 @@
*/ */
package org.eclipse.hawkbit.cache; package org.eclipse.hawkbit.cache;
import static java.util.Collections.emptyList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.hawkbit.tenancy.TenantAware; 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 * Additionally it also provide functionality to retrieve all caches overall
* tenants at once, for monitoring and system access. * tenants at once, for monitoring and system access.
*
*
*
*
*/ */
public class TenantAwareCacheManager implements TenancyCacheManager { public class TenantAwareCacheManager implements TenancyCacheManager {
@@ -39,41 +36,39 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
private final TenantAware tenantAware; private final TenantAware tenantAware;
/** /**
* Constructor.
*
* @param delegate * @param delegate
* the {@link CacheManager} to delegate to. * the {@link CacheManager} to delegate to.
* @param tenantAware * @param tenantAware
* the tenant aware to retrieve the current tenant * the tenant aware to retrieve the current tenant
*/ */
public TenantAwareCacheManager(final CacheManager delegate, final TenantAware tenantAware) { public TenantAwareCacheManager(final CacheManager delegate, final TenantAware tenantAware) {
this.delegate = delegate;
this.tenantAware = tenantAware; this.tenantAware = tenantAware;
this.delegate = delegate;
} }
@Override @Override
public Cache getCache(final String name) { public Cache getCache(final String name) {
String currentTenant = tenantAware.getCurrentTenant(); String currentTenant = tenantAware.getCurrentTenant();
if (currentTenant == null) { if (isTenantInvalid(currentTenant)) {
return null; return null;
} }
currentTenant = currentTenant.toUpperCase(); currentTenant = currentTenant.toUpperCase();
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
return null; return delegate.getCache(buildKey(currentTenant, name));
}
return delegate.getCache(currentTenant + TENANT_CACHE_DELIMITER + name);
} }
@Override @Override
public Collection<String> getCacheNames() { public Collection<String> getCacheNames() {
String currentTenant = tenantAware.getCurrentTenant(); String currentTenant = tenantAware.getCurrentTenant();
if (currentTenant == null) { if (isTenantInvalid(currentTenant)) {
return Collections.emptyList(); return emptyList();
} }
currentTenant = currentTenant.toUpperCase(); currentTenant = currentTenant.toUpperCase();
if (currentTenant.contains(TENANT_CACHE_DELIMITER)) {
return Collections.emptyList();
}
return getCacheNames(currentTenant); return getCacheNames(currentTenant);
} }
@@ -91,17 +86,17 @@ public class TenantAwareCacheManager implements TenancyCacheManager {
return delegate.getCache(name); return delegate.getCache(name);
} }
/*
* (non-Javadoc)
*
* @see
* org.eclipse.hawkbit.server.cache.TenancyCacheManager#evictCaches(java.
* lang. String)
*/
@Override @Override
public void evictCaches(final String tenant) { public void evictCaches(final String tenant) {
getCacheNames(tenant) getCacheNames(tenant).forEach(cachename -> delegate.getCache(buildKey(tenant, cachename)).clear());
.forEach(cachename -> delegate.getCache(tenant + TENANT_CACHE_DELIMITER + 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) { private Collection<String> getCacheNames(final String tenant) {

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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>
* &#064;EventSubscriber
* public class MySubscriber {
* &#064;Subscribe
* public void listen(MyEvent event) {
* System.out.println(&quot;event received: &quot; + event);
* }
* }
* </pre>
*
*
*
*
*/
@Target({ TYPE })
@Retention(RUNTIME)
public @interface EventSubscriber {
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 {
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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);
}

View 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);
}
}

View File

@@ -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) {
}
}
}

View File

@@ -37,9 +37,5 @@
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId> <artifactId>hibernate-validator</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -67,22 +67,6 @@
<classifier>tests</classifier> <classifier>tests</classifier>
<scope>test</scope> <scope>test</scope>
</dependency> </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> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
@@ -103,13 +87,6 @@
<artifactId>spring-security-config</artifactId> <artifactId>spring-security-config</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository-jpa</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-http-security</artifactId> <artifactId>hawkbit-http-security</artifactId>

View File

@@ -30,7 +30,8 @@ import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.apache.commons.lang3.RandomUtils; 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;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
@@ -41,15 +42,15 @@ import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.slf4j.LoggerFactory; 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.PageRequest;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import com.google.common.base.Charsets; 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 com.google.common.net.HttpHeaders;
import ru.yandex.qatools.allure.annotations.Description; 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") @Features("Component Tests - Direct Device Integration API")
@Stories("Artifact Download Resource") @Stories("Artifact Download Resource")
@SpringApplicationConfiguration(classes = DownloadTestConfiguration.class)
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB { public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB {
private static final int ARTIFACT_SIZE = 5 * 1024 * 1024; private static final int ARTIFACT_SIZE = 5 * 1024 * 1024;
@@ -69,9 +71,8 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class); LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class);
} }
private volatile int downLoadProgress = 0; private volatile static int downLoadProgress = 0;
private volatile long shippedBytes = 0; private volatile static long shippedBytes = 0;
private volatile long shippedBytesTotal = 0;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH); 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")); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
} }
@Autowired
private EventBus eventBus;
@Test @Test
@Description("Tests non allowed requests on the artifact ressource, e.g. invalid URI, wrong if-match, wrong command.") @Description("Tests non allowed requests on the artifact ressource, e.g. invalid URI, wrong if-match, wrong command.")
public void invalidRequestsOnArtifactResource() throws Exception { public void invalidRequestsOnArtifactResource() throws Exception {
@@ -252,8 +250,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
public void downloadArtifactThroughFileName() throws Exception { public void downloadArtifactThroughFileName() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0; shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
// create target // create target
@@ -293,7 +289,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// download complete // download complete
assertThat(downLoadProgress).isEqualTo(10); assertThat(downLoadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE); assertThat(shippedBytes).isEqualTo(ARTIFACT_SIZE);
} }
@Test @Test
@@ -332,8 +328,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception { public void downloadArtifactByNameFailsIfNotAuthenticated() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0; shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -357,7 +351,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
assertThat(downLoadProgress).isEqualTo(1); assertThat(downLoadProgress).isEqualTo(1);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(0L); assertThat(shippedBytes).isEqualTo(0L);
} }
@Test @Test
@@ -366,8 +360,6 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
public void downloadArtifactByNameByNamedController() throws Exception { public void downloadArtifactByNameByNamedController() throws Exception {
downLoadProgress = 1; downLoadProgress = 1;
shippedBytes = 0; shippedBytes = 0;
shippedBytesTotal = 0;
eventBus.register(this);
assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0); assertThat(softwareManagement.findSoftwareModulesAll(pageReq)).hasSize(0);
@@ -414,7 +406,7 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
// download complete // download complete
assertThat(downLoadProgress).isEqualTo(10); assertThat(downLoadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(shippedBytesTotal).isEqualTo(ARTIFACT_SIZE); assertThat(shippedBytes).isEqualTo(ARTIFACT_SIZE);
} }
@Test @Test
@@ -573,11 +565,23 @@ public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMong
.isEqualTo(new String(artifact.getMd5Hash() + " file1.tar.bz2").getBytes(Charsets.US_ASCII)); .isEqualTo(new String(artifact.getMd5Hash() + " file1.tar.bz2").getBytes(Charsets.US_ASCII));
} }
@Subscribe public static class DownloadTestConfiguration {
public void listen(final DownloadProgressEvent event) {
downLoadProgress++; @Bean
shippedBytes += event.getShippedBytesSinceLast(); public Listener cancelEventHandlerStubBean() {
shippedBytesTotal = event.getShippedBytesOverall(); return new Listener();
}
} }
private static class Listener {
@EventListener(classes = DownloadProgressEvent.class)
public void listen(final DownloadProgressEvent event) {
downLoadProgress++;
shippedBytes += event.getShippedBytesSinceLast();
}
}
} }

View File

@@ -31,7 +31,6 @@ import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
import org.eclipse.hawkbit.rest.util.JsonBuilder; import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.junit.Test; import org.junit.Test;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Description;
@@ -74,7 +73,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
// get update action anyway // get update action anyway
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/" + updateAction.getId(), mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/" + updateAction.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) 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("$.id", equalTo(String.valueOf(updateAction.getId()))))
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
.andExpect(jsonPath("$.deployment.update", equalTo("forced"))) .andExpect(jsonPath("$.deployment.update", equalTo("forced")))
@@ -118,7 +117,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
long current = System.currentTimeMillis(); long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith("http://localhost/" + tenantAware.getCurrentTenant() startsWith("http://localhost/" + tenantAware.getCurrentTenant()
@@ -150,7 +149,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
current = System.currentTimeMillis(); current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant() equalTo("http://localhost/" + tenantAware.getCurrentTenant()
@@ -170,7 +169,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction.getId(), tenantAware.getCurrentTenant()) get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction.getId(), tenantAware.getCurrentTenant())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.id", equalTo(String.valueOf(cancelAction.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction.getId())))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction.getId()))));
assertThat(targetManagement.findTargetByControllerID("4712").getTargetInfo().getLastTargetQuery()) 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()) get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction.getId(), tenantAware.getCurrentTenant())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.id", equalTo(String.valueOf(cancelAction.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction.getId())))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction.getId()))));
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6); assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant() equalTo("http://localhost/" + tenantAware.getCurrentTenant()
@@ -386,14 +385,14 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
assertThat(deploymentManagement.findActionsByTarget(savedTarget)).hasSize(3); assertThat(deploymentManagement.findActionsByTarget(savedTarget)).hasSize(3);
mvc.perform(get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction2.getId(), mvc.perform(get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction2.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) 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("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction2.getId())))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction2.getId()))));
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8); assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8);
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant() equalTo("http://localhost/" + tenantAware.getCurrentTenant()
@@ -426,7 +425,7 @@ public class DdiCancelActionTest extends AbstractRestIntegrationTest {
mvc.perform(get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction3.getId(), mvc.perform(get("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction3.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) 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("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction3.getId())))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(updateAction3.getId()))));
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(12); 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", mvc.perform(post("/{tenant}/controller/v1/4712/cancelAction/" + cancelAction3.getId() + "/feedback",
tenantAware.getCurrentTenant()) tenantAware.getCurrentTenant())
.content(JsonBuilder.cancelActionFeedback(cancelAction3.getId().toString(), "closed")) .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()); .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(13); assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(13);

View File

@@ -52,7 +52,7 @@ public class DdiConfigDataTest extends AbstractRestIntegrationTest {
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.configData.href", equalTo( .andExpect(jsonPath("$._links.configData.href", equalTo(
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData"))); "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())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.configData.href").doesNotExist()); .andExpect(jsonPath("$._links.configData.href").doesNotExist());
} }

View File

@@ -27,13 +27,13 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.RandomUtils; 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;
import org.eclipse.hawkbit.repository.model.Action.ActionType; import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.RepositoryModelConstants;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
@@ -44,7 +44,6 @@ import org.fest.assertions.core.Condition;
import org.junit.Test; import org.junit.Test;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction; import org.springframework.data.domain.Sort.Direction;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
@@ -136,7 +135,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
long current = System.currentTimeMillis(); long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/" .andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId()))); + 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()) get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.id", equalTo(String.valueOf(action.getId()))))
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
.andExpect(jsonPath("$.deployment.update", 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())) MvcResult mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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") final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
.read(mvcResult.getResponse().getContentAsString()).toString(); .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 // Time is not yet over, so we should see the same URL
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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()) assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
.toString()).isEqualTo(urlBeforeSwitch) .toString()).isEqualTo(urlBeforeSwitch)
.startsWith("http://localhost/" + tenantAware.getCurrentTenant() .startsWith("http://localhost/" + tenantAware.getCurrentTenant()
@@ -255,7 +254,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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()) assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
.toString()).isNotEqualTo(urlBeforeSwitch); .toString()).isNotEqualTo(urlBeforeSwitch);
@@ -300,7 +299,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
long current = System.currentTimeMillis(); long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/" .andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId()))); + 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()) get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.id", equalTo(String.valueOf(action.getId()))))
.andExpect(jsonPath("$.deployment.download", equalTo("attempt"))) .andExpect(jsonPath("$.deployment.download", equalTo("attempt")))
.andExpect(jsonPath("$.deployment.update", equalTo("attempt"))) .andExpect(jsonPath("$.deployment.update", equalTo("attempt")))
@@ -424,7 +423,7 @@ public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoD
long current = System.currentTimeMillis(); long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/" .andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId()))); + 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(), mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/{actionId}", tenantAware.getCurrentTenant(),
uaction.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) 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("$.id", equalTo(String.valueOf(action.getId()))))
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
.andExpect(jsonPath("$.deployment.update", equalTo("forced"))) .andExpect(jsonPath("$.deployment.update", equalTo("forced")))

View File

@@ -122,7 +122,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform(get("/default-tenant/controller/v1/4711")).andDo(MockMvcResultPrinter.print()) 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"))); .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery()) assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery())
.isGreaterThanOrEqualTo(current); .isGreaterThanOrEqualTo(current);
@@ -154,7 +154,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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"))); .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
return null; return null;
}); });
@@ -165,7 +165,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
public void rootRsNotModified() throws Exception { public void rootRsNotModified() throws Exception {
final String etag = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) final String etag = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))).andReturn().getResponse()
.getHeader("ETag"); .getHeader("ETag");
@@ -182,7 +182,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) .perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON)) .header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith("http://localhost/" + tenantAware.getCurrentTenant() startsWith("http://localhost/" + tenantAware.getCurrentTenant()
@@ -215,7 +215,7 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
.header("If-None-Match", etagWithFirstUpdate).accept(MediaType.APPLICATION_JSON)) .header("If-None-Match", etagWithFirstUpdate).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith("http://localhost/" + tenantAware.getCurrentTenant() startsWith("http://localhost/" + tenantAware.getCurrentTenant()
@@ -236,8 +236,9 @@ public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoD
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())) mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.config.polling.sleep", equalTo("00:01:00")));
assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery()) assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery()) assertThat(targetManagement.findTargetByControllerID("4711").getTargetInfo().getLastTargetQuery())

View File

@@ -7,6 +7,9 @@
# http://www.eclipse.org/legal/epl-v10.html # 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.uri=mongodb://localhost/spArtifactRepository${random.value}
spring.data.mongodb.port=28017 spring.data.mongodb.port=28017

View File

@@ -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>

View File

@@ -57,10 +57,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot</artifactId> <artifactId>spring-boot</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
@@ -69,6 +65,8 @@
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</dependency> </dependency>
<!-- Optional -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId> <artifactId>spring-boot-configuration-processor</artifactId>

View File

@@ -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.DbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
import org.eclipse.hawkbit.cache.DownloadArtifactCache; import org.eclipse.hawkbit.cache.DownloadArtifactCache;
import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.eclipse.hawkbit.cache.DownloadType; import org.eclipse.hawkbit.cache.DownloadType;
import org.eclipse.hawkbit.dmf.json.model.Artifact; import org.eclipse.hawkbit.dmf.json.model.Artifact;
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash; 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.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cache.Cache;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
@@ -56,7 +56,7 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService {
private final ArtifactManagement artifactManagement; private final ArtifactManagement artifactManagement;
private final Cache cache; private final DownloadIdCache cache;
private final HostnameResolver hostnameResolver; private final HostnameResolver hostnameResolver;
@@ -78,7 +78,7 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService {
*/ */
public AmqpAuthenticationMessageHandler(final RabbitTemplate rabbitTemplate, public AmqpAuthenticationMessageHandler(final RabbitTemplate rabbitTemplate,
final AmqpControllerAuthentication authenticationManager, final ArtifactManagement artifactManagement, final AmqpControllerAuthentication authenticationManager, final ArtifactManagement artifactManagement,
final Cache cache, final HostnameResolver hostnameResolver, final DownloadIdCache cache, final HostnameResolver hostnameResolver,
final ControllerManagement controllerManagement) { final ControllerManagement controllerManagement) {
super(rabbitTemplate); super(rabbitTemplate);
this.authenticationManager = authenticationManager; this.authenticationManager = authenticationManager;
@@ -89,7 +89,7 @@ public class AmqpAuthenticationMessageHandler extends BaseAmqpService {
} }
/** /**
* Executed on a authentication request. * Executed on an authentication request.
* *
* @param message * @param message
* the amqp message * the amqp message

View File

@@ -15,12 +15,13 @@ import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.hawkbit.api.ArtifactUrlHandler; import org.eclipse.hawkbit.api.ArtifactUrlHandler;
import org.eclipse.hawkbit.api.HostnameResolver; 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.dmf.amqp.api.AmqpSettings;
import org.eclipse.hawkbit.repository.ArtifactManagement; import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.security.DdiSecurityProperties; import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.SystemSecurityContext; 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.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties; 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.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.retry.backoff.ExponentialBackOffPolicy; import org.springframework.retry.backoff.ExponentialBackOffPolicy;
@@ -74,6 +75,9 @@ public class AmqpConfiguration {
@Autowired @Autowired
private ConnectionFactory rabbitConnectionFactory; private ConnectionFactory rabbitConnectionFactory;
@Autowired(required = false)
private ServiceMatcher serviceMatcher;
@Configuration @Configuration
@ConditionalOnMissingBean(ConnectionFactory.class) @ConditionalOnMissingBean(ConnectionFactory.class)
@ConditionalOnProperty(prefix = "hawkbit.dmf.rabbitmq", name = "enabled", matchIfMissing = true) @ConditionalOnProperty(prefix = "hawkbit.dmf.rabbitmq", name = "enabled", matchIfMissing = true)
@@ -288,7 +292,7 @@ public class AmqpConfiguration {
* for target authentication * for target authentication
* @param artifactManagement * @param artifactManagement
* for artifact URI generation * for artifact URI generation
* @param cache * @param downloadIdCache
* for download IDs * for download IDs
* @param hostnameResolver * @param hostnameResolver
* for resolving the host for downloads * for resolving the host for downloads
@@ -299,10 +303,10 @@ public class AmqpConfiguration {
@Bean @Bean
public AmqpAuthenticationMessageHandler amqpAuthenticationMessageHandler(final RabbitTemplate rabbitTemplate, public AmqpAuthenticationMessageHandler amqpAuthenticationMessageHandler(final RabbitTemplate rabbitTemplate,
final AmqpControllerAuthentication authenticationManager, final ArtifactManagement artifactManagement, 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) { final ControllerManagement controllerManagement) {
return new AmqpAuthenticationMessageHandler(rabbitTemplate, authenticationManager, artifactManagement, cache, return new AmqpAuthenticationMessageHandler(rabbitTemplate, authenticationManager, artifactManagement,
hostnameResolver, controllerManagement); downloadIdCache, hostnameResolver, controllerManagement);
} }
/** /**
@@ -330,6 +334,23 @@ public class AmqpConfiguration {
return new ConfigurableRabbitListenerContainerFactory(amqpProperties, rabbitConnectionFactory, errorHandler); 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 @Bean
@ConditionalOnMissingBean(AmqpControllerAuthentication.class) @ConditionalOnMissingBean(AmqpControllerAuthentication.class)
public AmqpControllerAuthentication amqpControllerAuthentication(final SystemManagement systemManagement, public AmqpControllerAuthentication amqpControllerAuthentication(final SystemManagement systemManagement,
@@ -340,13 +361,31 @@ public class AmqpConfiguration {
tenantAware, ddiSecruityProperties, systemSecurityContext); 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 @Bean
@ConditionalOnMissingBean(AmqpMessageDispatcherService.class) @ConditionalOnMissingBean(AmqpMessageDispatcherService.class)
public AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate, public AmqpMessageDispatcherService amqpMessageDispatcherService(final RabbitTemplate rabbitTemplate,
final AmqpSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler, 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, return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,
systemSecurityContext, systemManagement); systemSecurityContext, systemManagement, targetManagement, serviceMatcher);
} }
private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() { private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() {

View File

@@ -25,18 +25,19 @@ import org.eclipse.hawkbit.dmf.json.model.Artifact;
import org.eclipse.hawkbit.dmf.json.model.ArtifactHash; import org.eclipse.hawkbit.dmf.json.model.ArtifactHash;
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest; import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
import org.eclipse.hawkbit.dmf.json.model.SoftwareModule; 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.SystemManagement;
import org.eclipse.hawkbit.repository.eventbus.event.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.TargetManagement;
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.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.util.IpUtil;
import org.springframework.amqp.core.Message; import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties; import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cloud.bus.ServiceMatcher;
import com.google.common.eventbus.Subscribe; import org.springframework.cloud.bus.event.RemoteApplicationEvent;
import org.springframework.context.event.EventListener;
/** /**
* {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and * {@link AmqpMessageDispatcherService} create all outgoing AMQP messages and
@@ -46,13 +47,14 @@ import com.google.common.eventbus.Subscribe;
* assignment. * assignment.
* *
*/ */
@EventSubscriber
public class AmqpMessageDispatcherService extends BaseAmqpService { public class AmqpMessageDispatcherService extends BaseAmqpService {
private final ArtifactUrlHandler artifactUrlHandler; private final ArtifactUrlHandler artifactUrlHandler;
private final AmqpSenderService amqpSenderService; private final AmqpSenderService amqpSenderService;
private final SystemSecurityContext systemSecurityContext; private final SystemSecurityContext systemSecurityContext;
private final SystemManagement systemManagement; private final SystemManagement systemManagement;
private final TargetManagement targetManagement;
private final ServiceMatcher serviceMatcher;
/** /**
* Constructor. * Constructor.
@@ -66,51 +68,68 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
* @param systemSecurityContext * @param systemSecurityContext
* for execution with system permissions * for execution with system permissions
* @param systemManagement * @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, public AmqpMessageDispatcherService(final RabbitTemplate rabbitTemplate, final AmqpSenderService amqpSenderService,
final ArtifactUrlHandler artifactUrlHandler, final SystemSecurityContext systemSecurityContext, final ArtifactUrlHandler artifactUrlHandler, final SystemSecurityContext systemSecurityContext,
final SystemManagement systemManagement) { final SystemManagement systemManagement, final TargetManagement targetManagement,
final ServiceMatcher serviceMatcher) {
super(rabbitTemplate); super(rabbitTemplate);
this.artifactUrlHandler = artifactUrlHandler; this.artifactUrlHandler = artifactUrlHandler;
this.amqpSenderService = amqpSenderService; this.amqpSenderService = amqpSenderService;
this.systemSecurityContext = systemSecurityContext; this.systemSecurityContext = systemSecurityContext;
this.systemManagement = systemManagement; this.systemManagement = systemManagement;
this.targetManagement = targetManagement;
this.serviceMatcher = serviceMatcher;
} }
/** /**
* Method to send a message to a RabbitMQ Exchange after the Distribution * Method to send a message to a RabbitMQ Exchange after the Distribution
* set has been assign to a Target. * set has been assign to a Target.
* *
* @param targetAssignDistributionSetEvent * @param assignedEvent
* the object to be send. * the object to be send.
*/ */
@Subscribe @EventListener(classes = TargetAssignDistributionSetEvent.class)
public void targetAssignDistributionSet(final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent) { public void targetAssignDistributionSet(final TargetAssignDistributionSetEvent assignedEvent) {
final URI targetAdress = targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress(); 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)) { if (!IpUtil.isAmqpUri(targetAdress)) {
return; return;
} }
final String controllerId = targetAssignDistributionSetEvent.getTarget().getControllerId();
final Collection<org.eclipse.hawkbit.repository.model.SoftwareModule> modules = targetAssignDistributionSetEvent
.getSoftwareModules();
final DownloadAndUpdateRequest downloadAndUpdateRequest = new DownloadAndUpdateRequest(); final DownloadAndUpdateRequest downloadAndUpdateRequest = new DownloadAndUpdateRequest();
downloadAndUpdateRequest.setActionId(targetAssignDistributionSetEvent.getActionId()); downloadAndUpdateRequest.setActionId(actionId);
final String targetSecurityToken = systemSecurityContext final String targetSecurityToken = systemSecurityContext.runAsSystem(target::getSecurityToken);
.runAsSystem(targetAssignDistributionSetEvent.getTarget()::getSecurityToken);
downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken); downloadAndUpdateRequest.setTargetSecurityToken(targetSecurityToken);
for (final org.eclipse.hawkbit.repository.model.SoftwareModule softwareModule : modules) { for (final org.eclipse.hawkbit.repository.model.SoftwareModule softwareModule : modules) {
final SoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule( final SoftwareModule amqpSoftwareModule = convertToAmqpSoftwareModule(target, softwareModule);
targetAssignDistributionSetEvent.getTarget(), softwareModule);
downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule); downloadAndUpdateRequest.addSoftwareModule(amqpSoftwareModule);
} }
final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest, final Message message = getMessageConverter().toMessage(downloadAndUpdateRequest,
createConnectorMessageProperties(targetAssignDistributionSetEvent.getTenant(), controllerId, createConnectorMessageProperties(tenant, target.getControllerId(), EventTopic.DOWNLOAD_AND_INSTALL));
EventTopic.DOWNLOAD_AND_INSTALL));
amqpSenderService.sendMessage(message, targetAdress); 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 * Method to send a message to a RabbitMQ Exchange after the assignment of
* the Distribution set to a Target has been canceled. * the Distribution set to a Target has been canceled.
* *
* @param cancelTargetAssignmentDistributionSetEvent * @param cancelEvent
* the object to be send. * the object to be send.
*/ */
@Subscribe @EventListener(classes = CancelTargetAssignmentEvent.class)
public void targetCancelAssignmentToDistributionSet( public void targetCancelAssignmentToDistributionSet(final CancelTargetAssignmentEvent cancelEvent) {
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent) { if (isFromSelf(cancelEvent)) {
final String controllerId = cancelTargetAssignmentDistributionSetEvent.getTarget().getControllerId(); return;
final Long actionId = cancelTargetAssignmentDistributionSetEvent.getActionId(); }
final Message message = getMessageConverter().toMessage(actionId, createConnectorMessageProperties(
cancelTargetAssignmentDistributionSetEvent.getTenant(), controllerId, EventTopic.CANCEL_DOWNLOAD));
amqpSenderService.sendMessage(message, sendCancelMessageToTarget(cancelEvent.getTenant(), cancelEvent.getEntity().getControllerId(),
cancelTargetAssignmentDistributionSetEvent.getTarget().getTargetInfo().getAddress()); 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);
} }

View File

@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.amqp;
import java.net.URI; import java.net.URI;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; 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.ControllerManagement;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.RepositoryConstants; 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.TenantNotExistException;
import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException; import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; 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.repository.model.Target;
import org.eclipse.hawkbit.util.IpUtil; import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -176,7 +171,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
final String replyTo = message.getMessageProperties().getReplyTo(); final String replyTo = message.getMessageProperties().getReplyTo();
if (StringUtils.isEmpty(replyTo)) { 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); final URI amqpUri = IpUtil.createAmqpUri(virtualHost, replyTo);
@@ -187,23 +182,20 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
} }
private void lookIfUpdateAvailable(final Target target) { private void lookIfUpdateAvailable(final Target target) {
final Optional<Action> action = controllerManagement.findOldestActiveActionByTarget(target); final Optional<Action> actionOptional = controllerManagement.findOldestActiveActionByTarget(target);
if (!action.isPresent()) { if (!actionOptional.isPresent()) {
return; return;
} }
if (action.get().isCancelingOrCanceled()) { final Action action = actionOptional.get();
amqpMessageDispatcherService.targetCancelAssignmentToDistributionSet( if (action.isCancelingOrCanceled()) {
new CancelTargetAssignmentEvent(target, action.get().getId())); amqpMessageDispatcherService.sendCancelMessageToTarget(target.getTenant(), target.getControllerId(),
action.getId(), target.getTargetInfo().getAddress());
return; return;
} }
final DistributionSet distributionSet = action.get().getDistributionSet(); amqpMessageDispatcherService.sendUpdateMessageToTarget(action.getTenant(), action.getTarget(), action.getId(),
final List<SoftwareModule> softwareModuleList = controllerManagement action.getDistributionSet().getModules());
.findSoftwareModulesByDistributionSet(distributionSet);
amqpMessageDispatcherService.targetAssignDistributionSet(new TargetAssignDistributionSetEvent(
target.getOptLockRevision(), target.getTenant(), target, action.get().getId(), softwareModuleList));
} }
/** /**
@@ -332,5 +324,4 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
"Cancel recjected message is not allowed, if action is on state: " + action.getStatus()); "Cancel recjected message is not allowed, if action is on state: " + action.getStatus());
} }
} }
} }

View File

@@ -21,6 +21,7 @@ import java.net.URL;
import org.eclipse.hawkbit.api.HostnameResolver; import org.eclipse.hawkbit.api.HostnameResolver;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; 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.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType; import org.eclipse.hawkbit.dmf.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.DownloadResponse; 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.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.cache.Cache;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@@ -95,7 +95,7 @@ public class AmqpControllerAuthenticationTest {
private SystemManagement systemManagement; private SystemManagement systemManagement;
@Mock @Mock
private Cache cacheMock; private DownloadIdCache cacheMock;
@Mock @Mock
private HostnameResolver hostnameResolverMock; private HostnameResolver hostnameResolverMock;

View File

@@ -19,9 +19,9 @@ import static org.mockito.Mockito.when;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
import org.eclipse.hawkbit.api.ArtifactUrl; import org.eclipse.hawkbit.api.ArtifactUrl;
import org.eclipse.hawkbit.api.ArtifactUrlHandler; 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.amqp.api.MessageType;
import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest; import org.eclipse.hawkbit.dmf.json.model.DownloadAndUpdateRequest;
import org.eclipse.hawkbit.repository.SystemManagement; import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.eventbus.event.CancelTargetAssignmentEvent; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.eventbus.event.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.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.SoftwareModule; 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.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper; import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration; import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
@@ -82,11 +87,15 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
private Target testTarget; private Target testTarget;
@Autowired
protected ActionRepository actionRepository;
@Override @Override
public void before() throws Exception { public void before() throws Exception {
super.before(); super.before();
testTarget = entityFactory.generateTarget(CONTROLLER_ID, TEST_TOKEN); final Target generateTarget = entityFactory.generateTarget(CONTROLLER_ID, TEST_TOKEN);
testTarget.getTargetInfo().setAddress(AMQP_URI.toString()); generateTarget.getTargetInfo().setAddress(AMQP_URI.toString());
testTarget = targetManagement.createTarget(generateTarget);
this.rabbitTemplate = Mockito.mock(RabbitTemplate.class); this.rabbitTemplate = Mockito.mock(RabbitTemplate.class);
when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter()); when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter());
@@ -105,41 +114,62 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
when(systemManagement.getTenantMetadata()).thenReturn(tenantMetaData); when(systemManagement.getTenantMetadata()).thenReturn(tenantMetaData);
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService, amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
artifactUrlHandlerMock, systemSecurityContext, systemManagement); artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher);
} }
@Test @Test
@Description("Verfies that download and install event with no software modul works") @Description("Verfies that download and install event with no software modul works")
public void testSendDownloadRequesWithEmptySoftwareModules() { public void testSendDownloadRequesWithEmptySoftwareModules() {
final Action action = createAction(
testdataFactory.createDistributionSetWithNoSoftwareModules(UUID.randomUUID().toString(), "1.0"));
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent( final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
1L, TENANT, testTarget, 1L, Collections.emptyList()); action, serviceMatcher.getServiceId());
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent); amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
final Message sendMessage = createArgumentCapture(
targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress()); final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage); final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action);
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN); assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
assertTrue("No softwaremmodule should be contained in the request", assertTrue("No softwaremmodule should be contained in the request",
downloadAndUpdateRequest.getSoftwareModules().isEmpty()); 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 @Test
@Description("Verfies that download and install event with 3 software moduls and no artifacts works") @Description("Verfies that download and install event with 3 software moduls and no artifacts works")
public void testSendDownloadRequesWithSoftwareModulesAndNoArtifacts() { 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( final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
1L, TENANT, testTarget, 1L, dsA.getModules()); action, serviceMatcher.getServiceId());
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent); amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
final Message sendMessage = createArgumentCapture( final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress()); final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action);
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage); assertThat(createDistributionSet.getModules()).hasSameSizeAs(downloadAndUpdateRequest.getSoftwareModules());
assertEquals("Expecting a size of 3 software modules in the reuqest", 3,
downloadAndUpdateRequest.getSoftwareModules().size());
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN); assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
.getSoftwareModules()) { .getSoftwareModules()) {
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty()); 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()); assertNotNull("Sofware module ID should be set", softwareModule.getModuleId());
if (!softwareModule.getModuleId().equals(softwareModule2.getId())) { if (!softwareModule.getModuleId().equals(softwareModule2.getId())) {
continue; continue;
@@ -157,7 +187,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
@Test @Test
@Description("Verfies that download and install event with software moduls and artifacts works") @Description("Verfies that download and install event with software moduls and artifacts works")
public void testSendDownloadRequest() { public void testSendDownloadRequest() {
final DistributionSet dsA = testdataFactory.createDistributionSet(""); final DistributionSet dsA = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
final SoftwareModule module = dsA.getModules().iterator().next(); final SoftwareModule module = dsA.getModules().iterator().next();
final List<DbArtifact> receivedList = new ArrayList<>(); final List<DbArtifact> receivedList = new ArrayList<>();
for (final Artifact artifact : testdataFactory.createArtifacts(module.getId())) { for (final Artifact artifact : testdataFactory.createArtifacts(module.getId())) {
@@ -165,14 +195,16 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
receivedList.add(new DbArtifact()); receivedList.add(new DbArtifact());
} }
final Action action = createAction(dsA);
Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList); Mockito.when(rabbitTemplate.convertSendAndReceive(any())).thenReturn(receivedList);
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent( final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = new TargetAssignDistributionSetEvent(
1L, TENANT, testTarget, 1L, dsA.getModules()); action, serviceMatcher.getServiceId());
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent); amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
final Message sendMessage = createArgumentCapture( final Message sendMessage = getCaptureAdressEvent(targetAssignDistributionSetEvent);
targetAssignDistributionSetEvent.getTarget().getTargetInfo().getAddress()); final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage, action);
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3, assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3,
downloadAndUpdateRequest.getSoftwareModules().size()); downloadAndUpdateRequest.getSoftwareModules().size());
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN); assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
@@ -201,11 +233,11 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
@Description("Verfies that send cancel event works") @Description("Verfies that send cancel event works")
public void testSendCancelRequest() { public void testSendCancelRequest() {
final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent( final CancelTargetAssignmentEvent cancelTargetAssignmentDistributionSetEvent = new CancelTargetAssignmentEvent(
testTarget, 1L); testTarget, 1L, serviceMatcher.getServiceId());
amqpMessageDispatcherService amqpMessageDispatcherService
.targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent); .targetCancelAssignmentToDistributionSet(cancelTargetAssignmentDistributionSetEvent);
final Message sendMessage = createArgumentCapture( final Message sendMessage = createArgumentCapture(
cancelTargetAssignmentDistributionSetEvent.getTarget().getTargetInfo().getAddress()); cancelTargetAssignmentDistributionSetEvent.getEntity().getTargetInfo().getAddress());
assertCancelMessage(sendMessage); 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); assertEventMessage(sendMessage);
final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage, final DownloadAndUpdateRequest downloadAndUpdateRequest = convertMessage(sendMessage,
DownloadAndUpdateRequest.class); DownloadAndUpdateRequest.class);
assertEquals("The action ID of the downloadAndUpdateRequest event shuold be 1", assertEquals(downloadAndUpdateRequest.getActionId(), action.getId());
downloadAndUpdateRequest.getActionId(), Long.valueOf(1));
assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL, assertEquals("The topic of the event shuold contain DOWNLOAD_AND_INSTALL", EventTopic.DOWNLOAD_AND_INSTALL,
sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC)); sendMessage.getMessageProperties().getHeaders().get(MessageHeaderKey.TOPIC));
assertEquals("Security token of target", downloadAndUpdateRequest.getTargetSecurityToken(), TEST_TOKEN); assertEquals("Security token of target", downloadAndUpdateRequest.getTargetSecurityToken(), TEST_TOKEN);

View File

@@ -21,14 +21,14 @@ import java.lang.reflect.Field;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.Collection;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.eclipse.hawkbit.api.HostnameResolver; import org.eclipse.hawkbit.api.HostnameResolver;
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository; import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash; 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.EventTopic;
import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey; import org.eclipse.hawkbit.dmf.amqp.api.MessageHeaderKey;
import org.eclipse.hawkbit.dmf.amqp.api.MessageType; 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.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement; import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.EntityFactory; 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.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction; import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus; 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.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHolder;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.Artifact; 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.TargetInfo;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.security.SecurityTokenGenerator; 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.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.cache.Cache;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import ru.yandex.qatools.allure.annotations.Description; import ru.yandex.qatools.allure.annotations.Description;
@@ -108,7 +106,7 @@ public class AmqpMessageHandlerServiceTest {
private ArtifactRepository artifactRepositoryMock; private ArtifactRepository artifactRepositoryMock;
@Mock @Mock
private Cache cacheMock; private DownloadIdCache downloadIdCache;
@Mock @Mock
private HostnameResolver hostnameResolverMock; private HostnameResolver hostnameResolverMock;
@@ -120,11 +118,13 @@ public class AmqpMessageHandlerServiceTest {
public void before() throws Exception { public void before() throws Exception {
messageConverter = new Jackson2JsonMessageConverter(); messageConverter = new Jackson2JsonMessageConverter();
when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter); when(rabbitTemplate.getMessageConverter()).thenReturn(messageConverter);
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
controllerManagementMock, entityFactoryMock);
amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock, amqpMessageHandlerService = new AmqpMessageHandlerService(rabbitTemplate, amqpMessageDispatcherServiceMock,
controllerManagementMock, entityFactoryMock); controllerManagementMock, entityFactoryMock);
amqpAuthenticationMessageHandlerService = new AmqpAuthenticationMessageHandler(rabbitTemplate, amqpAuthenticationMessageHandlerService = new AmqpAuthenticationMessageHandler(rabbitTemplate,
authenticationManagerMock, artifactManagementMock, cacheMock, hostnameResolverMock, authenticationManagerMock, artifactManagementMock, downloadIdCache, hostnameResolverMock,
controllerManagementMock); controllerManagementMock);
} }
@@ -363,10 +363,6 @@ public class AmqpMessageHandlerServiceTest {
// for the test the same action can be used // for the test the same action can be used
when(controllerManagementMock.findOldestActiveActionByTarget(Matchers.any())).thenReturn(Optional.of(action)); 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); final MessageProperties messageProperties = createMessageProperties(MessageType.EVENT);
messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name()); messageProperties.setHeader(MessageHeaderKey.TOPIC, EventTopic.UPDATE_ACTION_STATUS.name());
final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L); final ActionUpdateStatus actionUpdateStatus = createActionUpdateStatus(ActionStatus.FINISHED, 23L);
@@ -380,20 +376,19 @@ public class AmqpMessageHandlerServiceTest {
verify(controllerManagementMock).updateTargetStatus(Matchers.any(TargetInfo.class), verify(controllerManagementMock).updateTargetStatus(Matchers.any(TargetInfo.class),
Matchers.isNull(TargetUpdateStatus.class), Matchers.isNotNull(Long.class), Matchers.isNull(URI.class)); Matchers.isNull(TargetUpdateStatus.class), Matchers.isNotNull(Long.class), Matchers.isNull(URI.class));
final ArgumentCaptor<TargetAssignDistributionSetEvent> captorTargetAssignDistributionSetEvent = ArgumentCaptor final ArgumentCaptor<String> tenantCaptor = ArgumentCaptor.forClass(String.class);
.forClass(TargetAssignDistributionSetEvent.class); final ArgumentCaptor<Target> targetCaptor = ArgumentCaptor.forClass(Target.class);
verify(amqpMessageDispatcherServiceMock, times(1)) final ArgumentCaptor<Long> actionIdCaptor = ArgumentCaptor.forClass(Long.class);
.targetAssignDistributionSet(captorTargetAssignDistributionSetEvent.capture());
final TargetAssignDistributionSetEvent targetAssignDistributionSetEvent = captorTargetAssignDistributionSetEvent
.getValue();
assertThat(targetAssignDistributionSetEvent.getTarget().getControllerId()).as("event has wrong controller id") verify(amqpMessageDispatcherServiceMock, times(1)).sendUpdateMessageToTarget(tenantCaptor.capture(),
.isEqualTo("target1"); targetCaptor.capture(), actionIdCaptor.capture(), Matchers.any(Collection.class));
assertThat(targetAssignDistributionSetEvent.getTarget().getSecurityToken()) final String tenant = tenantCaptor.getValue();
.as("targetoken not filled correctly").isEqualTo(action.getTarget().getSecurityToken()); final String controllerId = targetCaptor.getValue().getControllerId();
assertThat(targetAssignDistributionSetEvent.getActionId()).as("event has wrong action id").isEqualTo(22L); final Long actionId = actionIdCaptor.getValue();
assertThat(targetAssignDistributionSetEvent.getSoftwareModules()).as("event has wrong sofware modules")
.isEqualTo(softwareModuleList); 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; 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 { private Action createActionWithTarget(final Long targetId, final Status status) throws IllegalAccessException {
// is needed for the creation of targets // is needed for the creation of targets
initalizeSecurityTokenGenerator(); initalizeSecurityTokenGenerator();
@@ -440,6 +427,10 @@ public class AmqpMessageHandlerServiceTest {
final JpaAction actionMock = mock(JpaAction.class); final JpaAction actionMock = mock(JpaAction.class);
final JpaTarget targetMock = mock(JpaTarget.class); final JpaTarget targetMock = mock(JpaTarget.class);
final TargetInfo targetInfoMock = mock(TargetInfo.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.getId()).thenReturn(targetId);
when(actionMock.getStatus()).thenReturn(status); when(actionMock.getStatus()).thenReturn(status);
when(actionMock.getTenant()).thenReturn("DEFAULT"); when(actionMock.getTenant()).thenReturn("DEFAULT");

View File

@@ -7,8 +7,6 @@
# http://www.eclipse.org/legal/epl-v10.html # http://www.eclipse.org/legal/epl-v10.html
# #
# supported: H2, MYSQL # supported: H2, MYSQL
hawkbit.server.database=H2 hawkbit.server.database=H2

View File

@@ -25,9 +25,5 @@
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>jackson-annotations</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -13,9 +13,9 @@ import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; 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 static final Logger LOG = LoggerFactory.getLogger(HttpDownloadAuthenticationFilter.class);
private final Pattern pattern; private final Pattern pattern;
private final Cache cache; private final DownloadIdCache downloadIdCache;
/** /**
* Constructor. * Constructor.
* *
* @param cache * @param downloadIdCache
* the cache * the cache
*/ */
public HttpDownloadAuthenticationFilter(final Cache cache) { public HttpDownloadAuthenticationFilter(final DownloadIdCache downloadIdCache) {
this.cache = cache; this.downloadIdCache = downloadIdCache;
this.pattern = Pattern.compile(REQUEST_ID_REGEX_PATTERN); this.pattern = Pattern.compile(REQUEST_ID_REGEX_PATTERN);
} }
@@ -56,7 +56,7 @@ public class HttpDownloadAuthenticationFilter extends AbstractPreAuthenticatedPr
if (id == null) { if (id == null) {
return null; return null;
} }
return cache.get(id).get(); return downloadIdCache.get(id);
} }
@Override @Override

View File

@@ -32,11 +32,6 @@
<groupId>javax.validation</groupId> <groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId> <artifactId>validation-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Test --> <!-- Test -->
<dependency> <dependency>

View File

@@ -8,6 +8,8 @@
*/ */
package org.eclipse.hawkbit.mgmt.json.model.system; package org.eclipse.hawkbit.mgmt.json.model.system;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include; import com.fasterxml.jackson.annotation.JsonInclude.Include;
@@ -21,13 +23,13 @@ import com.fasterxml.jackson.annotation.JsonProperty;
public class MgmtSystemTenantConfigurationValueRequest { public class MgmtSystemTenantConfigurationValueRequest {
@JsonProperty(required = true) @JsonProperty(required = true)
private Object value; private Serializable value;
/** /**
* *
* @return the value of the MgmtSystemTenantConfigurationValueRequest * @return the value of the MgmtSystemTenantConfigurationValueRequest
*/ */
public Object getValue() { public Serializable getValue() {
return value; return value;
} }
@@ -37,7 +39,10 @@ public class MgmtSystemTenantConfigurationValueRequest {
* @param value * @param value
*/ */
public void setValue(final Object 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;
} }
} }

View File

@@ -36,15 +36,14 @@
<artifactId>hawkbit-rest-core</artifactId> <artifactId>hawkbit-rest-core</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.plugin</groupId> <groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId> <artifactId>spring-plugin-core</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!-- Test --> <!-- Test -->
<dependency> <dependency>
@@ -66,22 +65,6 @@
<classifier>tests</classifier> <classifier>tests</classifier>
<scope>test</scope> <scope>test</scope>
</dependency> </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> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>
<artifactId>h2</artifactId> <artifactId>h2</artifactId>
@@ -158,7 +141,7 @@
<artifactId>allure-junit-adaptor</artifactId> <artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
<scope>test</scope> <scope>test</scope>

View File

@@ -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.MgmtDistributionSetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; 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.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareManagement; import org.eclipse.hawkbit.repository.SoftwareManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.DistributionSetType; import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;

View File

@@ -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.MgmtDistributionSetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.DistributionSetManagement; import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.EntityFactory; import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest; 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.TargetManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;

View File

@@ -10,20 +10,16 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
import java.io.IOException; import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.eclipse.hawkbit.artifact.repository.ArtifactRepository; import org.eclipse.hawkbit.artifact.repository.ArtifactRepository;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact; 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.DownloadArtifactCache;
import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.eclipse.hawkbit.cache.DownloadType; import org.eclipse.hawkbit.cache.DownloadType;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi; import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder; import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; 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.context.annotation.Scope;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; 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.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
import com.google.common.io.ByteStreams;
/** /**
* A resource for download artifacts. * A resource for download artifacts.
* *
@@ -48,8 +46,7 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
private ArtifactRepository artifactRepository; private ArtifactRepository artifactRepository;
@Autowired @Autowired
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE) private DownloadIdCache downloadIdCache;
private Cache cache;
@Autowired @Autowired
private RequestResponseContextHolder requestResponseContextHolder; private RequestResponseContextHolder requestResponseContextHolder;
@@ -66,13 +63,12 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
@ResponseBody @ResponseBody
public ResponseEntity<Void> downloadArtifactByDownloadId(@PathVariable("downloadId") final String downloadId) { public ResponseEntity<Void> downloadArtifactByDownloadId(@PathVariable("downloadId") final String downloadId) {
try { try {
final ValueWrapper cacheWrapper = cache.get(downloadId); final DownloadArtifactCache artifactCache = downloadIdCache.get(downloadId);
if (cacheWrapper == null) { if (artifactCache == null) {
LOGGER.warn("Download Id {} could not be found", downloadId); LOGGER.warn("Download Id {} could not be found", downloadId);
return new ResponseEntity<>(HttpStatus.NOT_FOUND); return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} }
final DownloadArtifactCache artifactCache = (DownloadArtifactCache) cacheWrapper.get();
DbArtifact artifact = null; DbArtifact artifact = null;
if (DownloadType.BY_SHA1.equals(artifactCache.getDownloadType())) { if (DownloadType.BY_SHA1.equals(artifactCache.getDownloadType())) {
@@ -87,14 +83,14 @@ public class MgmtDownloadResource implements MgmtDownloadRestApi {
return new ResponseEntity<>(HttpStatus.NOT_FOUND); return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} }
try { try {
IOUtils.copy(artifact.getFileInputStream(), ByteStreams.copy(artifact.getFileInputStream(),
requestResponseContextHolder.getHttpServletResponse().getOutputStream()); requestResponseContextHolder.getHttpServletResponse().getOutputStream());
} catch (final IOException e) { } catch (final IOException e) {
LOGGER.error("Cannot copy streams", e); LOGGER.error("Cannot copy streams", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build(); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
} }
} finally { } finally {
cache.evict(downloadId); downloadIdCache.evict(downloadId);
} }
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();

View File

@@ -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.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn; import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.io.Serializable;
import java.util.Map; import java.util.Map;
import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationValue; 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 TenantConfigurationKey configKey = TenantConfigurationKey.fromKeyName(keyName);
final TenantConfigurationValue<Object> updatedValue = tenantConfigurationManagement final TenantConfigurationValue<? extends Serializable> updatedValue = tenantConfigurationManagement
.addOrUpdateConfiguration(configKey, configurationValueRest.getValue()); .addOrUpdateConfiguration(configKey, configurationValueRest.getValue());
return new ResponseEntity<>(MgmtSystemMapper.toResponse(keyName, updatedValue), HttpStatus.OK); return new ResponseEntity<>(MgmtSystemMapper.toResponse(keyName, updatedValue), HttpStatus.OK);
} }
} }

View File

@@ -438,7 +438,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
// perform request // perform request
mvc.perform(get("/rest/v1/distributionsets").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/distributionsets").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", .andExpect(jsonPath("$.content.[0]._links.self.href",
equalTo("http://localhost/rest/v1/distributionsets/" + set.getId()))) equalTo("http://localhost/rest/v1/distributionsets/" + set.getId())))
.andExpect(jsonPath("$.content.[0].id", equalTo(set.getId().intValue()))) .andExpect(jsonPath("$.content.[0].id", equalTo(set.getId().intValue())))
@@ -469,7 +469,7 @@ public class MgmtDistributionSetResourceTest extends AbstractRestIntegrationTest
// perform request // perform request
mvc.perform(get("/rest/v1/distributionsets/{dsId}", set.getId()).accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/distributionsets/{dsId}", set.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", .andExpect(jsonPath("$._links.self.href",
equalTo("http://localhost/rest/v1/distributionsets/" + set.getId()))) equalTo("http://localhost/rest/v1/distributionsets/" + set.getId())))
.andExpect(jsonPath("$.id", equalTo(set.getId().intValue()))) .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)) .perform(post("/rest/v1/distributionsets/").content(JsonBuilder.distributionSets(sets))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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]name", equalTo(one.getName())))
.andExpect(jsonPath("[0]description", equalTo(one.getDescription()))) .andExpect(jsonPath("[0]description", equalTo(one.getDescription())))
.andExpect(jsonPath("[0]type", equalTo(standardDsType.getKey()))) .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()) mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId())
.contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString())) .contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
.andExpect(jsonPath("[1]key", equalTo(knownKey2))) .andExpect(jsonPath("[1]key", equalTo(knownKey2)))
.andExpect(jsonPath("[1]value", equalTo(knownValue2))); .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) mvc.perform(put("/rest/v1/distributionsets/{dsId}/metadata/{key}", testDS.getId(), knownKey)
.contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString())) .contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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))); .andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
final DistributionSetMetadata assertDS = distributionSetManagement.findOne(testDS, knownKey); final DistributionSetMetadata assertDS = distributionSetManagement.findOne(testDS, knownKey);

View File

@@ -68,7 +68,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
// generated in this test) // generated in this test)
mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", .andExpect(jsonPath("$.content.[?(@.key==" + standardDsType.getKey() + ")]$..name",
contains(standardDsType.getName()))) contains(standardDsType.getName())))
.andExpect(jsonPath("$.content.[?(@.key==" + standardDsType.getKey() + ")]$..description", .andExpect(jsonPath("$.content.[?(@.key==" + standardDsType.getKey() + ")]$..description",
@@ -107,7 +107,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
// descending // descending
mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON) mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON)
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "KEY:DESC")).andDo(MockMvcResultPrinter.print()) .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].id", equalTo(testType.getId().intValue())))
.andExpect(jsonPath("$.content.[0].name", equalTo("TestName123"))) .andExpect(jsonPath("$.content.[0].name", equalTo("TestName123")))
.andExpect(jsonPath("$.content.[0].description", equalTo("Desc1234"))) .andExpect(jsonPath("$.content.[0].description", equalTo("Desc1234")))
@@ -121,7 +121,7 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractRestIntegration
// ascending // ascending
mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON) mvc.perform(get("/rest/v1/distributionsettypes").accept(MediaType.APPLICATION_JSON)
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "KEY:ASC")).andDo(MockMvcResultPrinter.print()) .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].id", equalTo(testType.getId().intValue())))
.andExpect(jsonPath("$.content.[3].name", equalTo("TestName123"))) .andExpect(jsonPath("$.content.[3].name", equalTo("TestName123")))
.andExpect(jsonPath("$.content.[3].description", equalTo("Desc1234"))) .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)) .perform(post("/rest/v1/distributionsettypes/").content(JsonBuilder.distributionSetTypes(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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].name", equalTo("TestName1"))).andExpect(jsonPath("[0].key", equalTo("test1")))
.andExpect(jsonPath("[0].description", equalTo("Desc1"))) .andExpect(jsonPath("[0].description", equalTo("Desc1")))
.andExpect(jsonPath("[0].createdBy", equalTo("uploadTester"))) .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()) mvc.perform(get("/rest/v1/distributionsettypes/{dstID}/mandatorymoduletypes", testType.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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].name", equalTo(osType.getName())))
.andExpect(jsonPath("[0].description", equalTo(osType.getDescription()))) .andExpect(jsonPath("[0].description", equalTo(osType.getDescription())))
.andExpect(jsonPath("[0].maxAssignments", equalTo(1))).andExpect(jsonPath("[0].key", equalTo("os"))); .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()) mvc.perform(get("/rest/v1/distributionsettypes/{dstID}/optionalmoduletypes", testType.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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].name", equalTo(appType.getName())))
.andExpect(jsonPath("[0].description", equalTo(appType.getDescription()))) .andExpect(jsonPath("[0].description", equalTo(appType.getDescription())))
.andExpect(jsonPath("[0].maxAssignments", equalTo(Integer.MAX_VALUE))) .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)) mvc.perform(get("/rest/v1/distributionsettypes/{dstId}", testType.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.name", equalTo("TestName123")))
.andExpect(jsonPath("$.description", equalTo("Desc1234"))) .andExpect(jsonPath("$.description", equalTo("Desc1234")))
.andExpect(jsonPath("$.createdBy", equalTo("uploadTester"))) .andExpect(jsonPath("$.createdBy", equalTo("uploadTester")))

View File

@@ -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.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; 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.DownloadArtifactCache;
import org.eclipse.hawkbit.cache.DownloadIdCache;
import org.eclipse.hawkbit.cache.DownloadType; import org.eclipse.hawkbit.cache.DownloadType;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.model.Artifact; 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.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired; 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 org.springframework.context.annotation.Description;
import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Features;
@@ -35,8 +33,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
public class MgmtDownloadResourceTest extends AbstractRestIntegrationTestWithMongoDB { public class MgmtDownloadResourceTest extends AbstractRestIntegrationTestWithMongoDB {
@Autowired @Autowired
@Qualifier(CacheConstants.DOWNLOAD_ID_CACHE) private DownloadIdCache downloadIdCache;
private Cache downloadIdCache;
private final String downloadIdSha1 = "downloadIdSha1"; private final String downloadIdSha1 = "downloadIdSha1";
@@ -47,7 +44,7 @@ public class MgmtDownloadResourceTest extends AbstractRestIntegrationTestWithMon
final DistributionSet distributionSet = testdataFactory.createDistributionSet("Test"); final DistributionSet distributionSet = testdataFactory.createDistributionSet("Test");
final SoftwareModule softwareModule = distributionSet.getModules().stream().findFirst().get(); 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())); downloadIdCache.put(downloadIdSha1, new DownloadArtifactCache(DownloadType.BY_SHA1, artifact.getSha1Hash()));
} }

View File

@@ -125,7 +125,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
@Description("Testing the empty list is returned if no rollout exists") @Description("Testing the empty list is returned if no rollout exists")
public void noRolloutReturnsEmptyList() throws Exception { public void noRolloutReturnsEmptyList() throws Exception {
mvc.perform(get("/rest/v1/rollouts")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) 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))); .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"); postRollout("rollout2", 5, dsA.getId(), "name==target2");
mvc.perform(get("/rest/v1/rollouts")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) 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", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)))
.andExpect(jsonPath("content[0].name", equalTo("rollout1"))) .andExpect(jsonPath("content[0].name", equalTo("rollout1")))
.andExpect(jsonPath("content[0].status", equalTo("ready"))) .andExpect(jsonPath("content[0].status", equalTo("ready")))
@@ -159,7 +159,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
postRollout("rollout2", 5, dsA.getId(), "name==target2"); postRollout("rollout2", 5, dsA.getId(), "name==target2");
mvc.perform(get("/rest/v1/rollouts?limit=1")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) 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))); .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 // retrieve rollout groups from created rollout
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())) mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", hasSize(4))).andExpect(jsonPath("$.total", equalTo(4)))
.andExpect(jsonPath("$.content[0].status", equalTo("ready"))) .andExpect(jsonPath("$.content[0].status", equalTo("ready")))
.andExpect(jsonPath("$.content[1].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 // check rollout is in running state
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print()) 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("id", equalTo(rollout.getId().intValue())))
.andExpect(jsonPath("status", equalTo("running"))); .andExpect(jsonPath("status", equalTo("running")));
} }
@@ -228,7 +228,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
// check rollout is in running state // check rollout is in running state
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print()) 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("id", equalTo(rollout.getId().intValue())))
.andExpect(jsonPath("status", equalTo("paused"))); .andExpect(jsonPath("status", equalTo("paused")));
} }
@@ -258,7 +258,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
// check rollout is in running state // check rollout is in running state
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print()) 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("id", equalTo(rollout.getId().intValue())))
.andExpect(jsonPath("status", equalTo("running"))); .andExpect(jsonPath("status", equalTo("running")));
} }
@@ -320,7 +320,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
// (amountTargets / groupSize = 2) // (amountTargets / groupSize = 2)
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups?sort=ID:ASC", rollout.getId())) mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups?sort=ID:ASC", rollout.getId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)))
.andExpect(jsonPath("$.content[0].status", equalTo("running"))) .andExpect(jsonPath("$.content[0].status", equalTo("running")))
.andExpect(jsonPath("$.content[1].status", equalTo("scheduled"))); .andExpect(jsonPath("$.content[1].status", equalTo("scheduled")));
@@ -344,7 +344,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
// retrieve single rollout group with known ID // retrieve single rollout group with known ID
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}", rollout.getId(), firstGroup.getId())) mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}", rollout.getId(), firstGroup.getId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("id", equalTo(firstGroup.getId().intValue())))
.andExpect(jsonPath("status", equalTo("ready"))).andExpect(jsonPath("name", notNullValue())); .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 // retrieve targets from the first rollout group with known ID
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(), mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(),
firstGroup.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) 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))); .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()) get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(), firstGroup.getId())
.param("q", "controllerId==" + targets.get(0).getControllerId())) .param("q", "controllerId==" + targets.get(0).getControllerId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", 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 // retrieve targets from the first rollout group with known ID
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(), mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups/{groupId}/targets", rollout.getId(),
firstGroup.getId())).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) 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))); .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")) mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==*2"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", hasSize(1))).andExpect(jsonPath("$.total", equalTo(1)))
.andExpect(jsonPath("$.content[0].name", equalTo(rollout2.getName()))); .andExpect(jsonPath("$.content[0].name", equalTo(rollout2.getName())));
mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==rollout*")) mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==rollout*"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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))); .andExpect(jsonPath("$.content", hasSize(3))).andExpect(jsonPath("$.total", equalTo(3)));
mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==*1")) mvc.perform(get("/rest/v1/rollouts").param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==*1"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)));
} }
@@ -492,19 +492,19 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
// retrieve rollout groups from created rollout // retrieve rollout groups from created rollout
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId()) mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())
.param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group-1")).andDo(MockMvcResultPrinter.print()) .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", hasSize(1))).andExpect(jsonPath("$.total", equalTo(1)))
.andExpect(jsonPath("$.content[0].name", equalTo("group-1"))); .andExpect(jsonPath("$.content[0].name", equalTo("group-1")));
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId()) mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())
.param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group*")).andDo(MockMvcResultPrinter.print()) .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))); .andExpect(jsonPath("$.content", hasSize(4))).andExpect(jsonPath("$.total", equalTo(4)));
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId()) mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups", rollout.getId())
.param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group-1,name==group-2")) .param(MgmtRestConstants.REQUEST_PARAMETER_SEARCH, "name==group-1,name==group-2"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)));
} }

View File

@@ -138,7 +138,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file) .perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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.md5", equalTo(md5sum)))
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
.andExpect(jsonPath("$.size", equalTo(random.length))) .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) mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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.md5", equalTo(md5sum)))
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum))) .andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
.andExpect(jsonPath("$.providedFilename", equalTo("orig"))).andExpect(status().isCreated()); .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) mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
.param("filename", "customFilename").accept(MediaType.APPLICATION_JSON)) .param("filename", "customFilename").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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()); .andExpect(jsonPath("$.providedFilename", equalTo("customFilename"))).andExpect(status().isCreated());
// check result in db... // check result in db...
@@ -341,7 +341,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
// perform test // perform test
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()) mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.id", equalTo(artifact.getId().intValue())))
.andExpect(jsonPath("$.size", equalTo(random.length))) .andExpect(jsonPath("$.size", equalTo(random.length)))
.andExpect(jsonPath("$.hashes.md5", equalTo(artifact.getMd5Hash()))) .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)) mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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].id", equalTo(artifact.getId().intValue())))
.andExpect(jsonPath("$.[0].size", equalTo(random.length))) .andExpect(jsonPath("$.[0].size", equalTo(random.length)))
.andExpect(jsonPath("$.[0].hashes.md5", equalTo(artifact.getMd5Hash()))) .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)) mvc.perform(get("/rest/v1/softwaremodules").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() + ")].name", contains("name1")))
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].version", contains("version1"))) .andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].version", contains("version1")))
.andExpect(jsonPath("$.content.[?(@.id==" + os.getId() + ")].description", contains("description1"))) .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 // only by name, only one exists per name
mvc.perform(get("/rest/v1/softwaremodules?q=name==osName1").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/softwaremodules?q=name==osName1").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() + ")].name", contains("osName1")))
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].version", contains("1.0.0"))) .andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].version", contains("1.0.0")))
.andExpect(jsonPath("$.content.[?(@.id==" + os1.getId() + ")].description", contains("description1"))) .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 // by type, 2 software modules per type exists
mvc.perform(get("/rest/v1/softwaremodules?q=type==application").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/softwaremodules?q=type==application").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() + ")].name", contains("appName1")))
.andExpect(jsonPath("$.content.[?(@.id==" + ah1.getId() + ")].version", contains("3.0.0"))) .andExpect(jsonPath("$.content.[?(@.id==" + ah1.getId() + ")].version", contains("3.0.0")))
.andExpect(jsonPath("$.content.[?(@.id==" + ah1.getId() + ")].description", contains("description1"))) .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 // 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)) mvc.perform(get("/rest/v1/softwaremodules?q=type==runtime;version==2.0.0").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() + ")].name", contains("runtimeName1")))
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].version", contains("2.0.0"))) .andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].version", contains("2.0.0")))
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].description", contains("description1"))) .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 // 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)) mvc.perform(get("/rest/v1/softwaremodules?q=type==runtime;version=ge=2.0.0").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() + ")].name", contains("runtimeName1")))
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].version", contains("2.0.0"))) .andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].version", contains("2.0.0")))
.andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].description", contains("description1"))) .andExpect(jsonPath("$.content.[?(@.id==" + jvm1.getId() + ")].description", contains("description1")))
@@ -691,14 +691,14 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
@Test @Test
@WithUser(principal = "uploadTester", allSpPermissions = true) @WithUser(principal = "uploadTester", allSpPermissions = true)
@Description("Tests GET request on /rest/v1/softwaremodules/{smId}.") @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", SoftwareModule os = entityFactory.generateSoftwareModule(osType, "name1", "version1", "description1",
"vendor1"); "vendor1");
os = softwareManagement.createSoftwareModule(os); os = softwareManagement.createSoftwareModule(os);
mvc.perform(get("/rest/v1/softwaremodules/{smId}", os.getId()).accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/softwaremodules/{smId}", os.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.name", equalTo("name1"))).andExpect(jsonPath("$.version", equalTo("version1")))
.andExpect(jsonPath("$.description", equalTo("description1"))) .andExpect(jsonPath("$.description", equalTo("description1")))
.andExpect(jsonPath("$.vendor", equalTo("vendor1"))).andExpect(jsonPath("$.type", equalTo("os"))) .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)) mvc.perform(get("/rest/v1/softwaremodules/{smId}", jvm.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.name", equalTo("name1"))).andExpect(jsonPath("$.version", equalTo("version1")))
.andExpect(jsonPath("$.description", equalTo("description1"))) .andExpect(jsonPath("$.description", equalTo("description1")))
.andExpect(jsonPath("$.vendor", equalTo("vendor1"))).andExpect(jsonPath("$.type", equalTo("runtime"))) .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)) mvc.perform(get("/rest/v1/softwaremodules/{smId}", ah.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.name", equalTo("name1"))).andExpect(jsonPath("$.version", equalTo("version1")))
.andExpect(jsonPath("$.description", equalTo("description1"))) .andExpect(jsonPath("$.description", equalTo("description1")))
.andExpect(jsonPath("$.vendor", equalTo("vendor1"))) .andExpect(jsonPath("$.vendor", equalTo("vendor1")))
@@ -778,7 +778,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractRestIntegrationTestW
.perform(post("/rest/v1/softwaremodules/").content(JsonBuilder.softwareModules(modules)) .perform(post("/rest/v1/softwaremodules/").content(JsonBuilder.softwareModules(modules))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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].name", equalTo("name1")))
.andExpect(jsonPath("[0].version", equalTo("version1"))) .andExpect(jsonPath("[0].version", equalTo("version1")))
.andExpect(jsonPath("[0].description", equalTo("description1"))) .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) mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).contentType(MediaType.APPLICATION_JSON)
.content(jsonArray.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
.andExpect(jsonPath("[1]key", equalTo(knownKey2))) .andExpect(jsonPath("[1]key", equalTo(knownKey2)))
.andExpect(jsonPath("[1]value", equalTo(knownValue2))); .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) mvc.perform(put("/rest/v1/softwaremodules/{swId}/metadata/{key}", sm.getId(), knownKey)
.contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString())) .contentType(MediaType.APPLICATION_JSON).content(jsonObject.toString()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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))); .andExpect(jsonPath("key", equalTo(knownKey))).andExpect(jsonPath("value", equalTo(updateValue)));
final SoftwareModuleMetadata assertDS = softwareManagement.findSoftwareModuleMetadata(sm.getId(), knownKey); final SoftwareModuleMetadata assertDS = softwareManagement.findSoftwareModuleMetadata(sm.getId(), knownKey);

View File

@@ -64,7 +64,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON)) mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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() + ")].name", contains(osType.getName())))
.andExpect(jsonPath("$.content.[?(@.key==" + osType.getKey() + ")].description", .andExpect(jsonPath("$.content.[?(@.key==" + osType.getKey() + ")].description",
contains(osType.getDescription()))) contains(osType.getDescription())))
@@ -108,7 +108,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractRestIntegrationT
mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON) mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON)
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "MAXASSIGNMENTS:DESC")) .param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "MAXASSIGNMENTS:DESC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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].id", equalTo(testType.getId().intValue())))
.andExpect(jsonPath("$.content.[1].name", equalTo("TestName123"))) .andExpect(jsonPath("$.content.[1].name", equalTo("TestName123")))
.andExpect(jsonPath("$.content.[1].description", equalTo("Desc1234"))) .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) mvc.perform(get("/rest/v1/softwaremoduletypes").accept(MediaType.APPLICATION_JSON)
.param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "MAXASSIGNMENTS:ASC")) .param(MgmtRestConstants.REQUEST_PARAMETER_SORTING, "MAXASSIGNMENTS:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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].id", equalTo(testType.getId().intValue())))
.andExpect(jsonPath("$.content.[2].name", equalTo("TestName123"))) .andExpect(jsonPath("$.content.[2].name", equalTo("TestName123")))
.andExpect(jsonPath("$.content.[2].description", equalTo("Desc1234"))) .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)) .perform(post("/rest/v1/softwaremoduletypes/").content(JsonBuilder.softwareModuleTypes(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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].name", equalTo("TestName1"))).andExpect(jsonPath("[0].key", equalTo("test1")))
.andExpect(jsonPath("[0].description", equalTo("Desc1"))) .andExpect(jsonPath("[0].description", equalTo("Desc1")))
.andExpect(jsonPath("[0].createdBy", equalTo("uploadTester"))) .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)) mvc.perform(get("/rest/v1/softwaremoduletypes/{smtId}", testType.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.name", equalTo("TestName123")))
.andExpect(jsonPath("$.description", equalTo("Desc1234"))) .andExpect(jsonPath("$.description", equalTo("Desc1234")))
.andExpect(jsonPath("$.maxAssignments", equalTo(5))) .andExpect(jsonPath("$.maxAssignments", equalTo(5)))

View File

@@ -8,37 +8,30 @@
*/ */
package org.eclipse.hawkbit.mgmt.rest.resource; 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.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.*; import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import java.util.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import java.util.stream.Collectors; 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.exception.SpServerError;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants; import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.*; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest; import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
import org.eclipse.hawkbit.rest.exception.MessageNotReadableException; import org.eclipse.hawkbit.rest.exception.MessageNotReadableException;
import org.eclipse.hawkbit.rest.json.model.ExceptionInfo; import org.eclipse.hawkbit.rest.json.model.ExceptionInfo;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter; import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.json.JSONObject; import org.json.JSONObject;
import org.junit.Test; 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.http.MediaType;
import org.springframework.test.web.servlet.MvcResult; 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.Description;
import ru.yandex.qatools.allure.annotations.Features; import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories; import ru.yandex.qatools.allure.annotations.Stories;
@@ -51,8 +44,6 @@ import ru.yandex.qatools.allure.annotations.Stories;
@Stories("Target Filter Query Resource") @Stories("Target Filter Query Resource")
public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTest { public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTest {
private static final String TARGET_DESCRIPTION_TEST = "created in test";
private static final String JSON_PATH_ROOT = "$"; private static final String JSON_PATH_ROOT = "$";
// fields, attributes // 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_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; private static final String JSON_PATH_AUTO_ASSIGN_DS = JSON_PATH_ROOT + JSON_PATH_FIELD_AUTO_ASSIGN_DS;
@Test @Test
@Description("Ensures that deletion is executed if permitted.") @Description("Ensures that deletion is executed if permitted.")
public void deleteTargetFilterQueryReturnsOK() throws Exception { public void deleteTargetFilterQueryReturnsOK() throws Exception {
final String filterName = "filter_01"; 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())) mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId()))
.andExpect(status().isOk()); .andExpect(status().isOk());
TargetFilterQuery tfq = targetFilterQueryManagement.findTargetFilterQueryById(filterQuery.getId()); final TargetFilterQuery tfq = targetFilterQueryManagement.findTargetFilterQueryById(filterQuery.getId());
assertThat(tfq).isNull(); assertThat(tfq).isNull();
} }
@@ -116,7 +106,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
final String body = new JSONObject().put("query", filterQuery2).toString(); final String body = new JSONObject().put("query", filterQuery2).toString();
// prepare // 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) mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()).content(body)
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .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("$.query", equalTo(filterQuery2)))
.andExpect(jsonPath("$.name", equalTo(filterName))); .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.getQuery()).isEqualTo(filterQuery2);
assertThat(tfqCheck.getName()).isEqualTo(filterName); assertThat(tfqCheck.getName()).isEqualTo(filterName);
} }
@@ -149,12 +139,11 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
.andExpect(jsonPath("$.query", equalTo(filterQuery))) .andExpect(jsonPath("$.query", equalTo(filterQuery)))
.andExpect(jsonPath("$.name", equalTo(filterName2))); .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.getQuery()).isEqualTo(filterQuery);
assertThat(tfqCheck.getName()).isEqualTo(filterName2); assertThat(tfqCheck.getName()).isEqualTo(filterName2);
} }
@Test @Test
@Description("Ensures that request returns list of filters in defined format.") @Description("Ensures that request returns list of filters in defined format.")
public void getTargetFilterQueryWithoutAdditionalRequestParameters() throws Exception { public void getTargetFilterQueryWithoutAdditionalRequestParameters() throws Exception {
@@ -250,7 +239,8 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
final String knownQuery = "name=test01"; final String knownQuery = "name=test01";
final String knownName = "someName"; final String knownName = "someName";
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery); 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 // test
mvc.perform(get(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()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
@@ -302,13 +292,15 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
final DistributionSet set = testdataFactory.createDistributionSet("one"); final DistributionSet set = testdataFactory.createDistributionSet("one");
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery); 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)) .content("{\"id\":" + set.getId() + "}").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .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())) mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
@@ -336,20 +328,18 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractRestIntegrationTe
assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet()) assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet())
.isEqualTo(set); .isEqualTo(set);
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().isOk()) .andExpect(status().isOk()).andExpect(jsonPath(JSON_PATH_NAME, equalTo(dsName)));
.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()); .andExpect(status().isNoContent());
assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet()) assertThat(targetFilterQueryManagement.findTargetFilterQueryById(tfq.getId()).getAutoAssignDistributionSet())
.isNull(); .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()); .andExpect(status().isNoContent());
} }
private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) { private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) {

View File

@@ -735,7 +735,7 @@ public class MgmtTargetResourceTest extends AbstractRestIntegrationTest {
.perform(post("/rest/v1/targets/").content(JsonBuilder.targets(targets, true)) .perform(post("/rest/v1/targets/").content(JsonBuilder.targets(targets, true))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .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].name", equalTo("testname1")))
.andExpect(jsonPath("[0].controllerId", equalTo("id1"))) .andExpect(jsonPath("[0].controllerId", equalTo("id1")))
.andExpect(jsonPath("[0].description", equalTo("testid1"))) .andExpect(jsonPath("[0].description", equalTo("testid1")))

View File

@@ -7,6 +7,9 @@
# http://www.eclipse.org/legal/epl-v10.html # http://www.eclipse.org/legal/epl-v10.html
# #
logging.level.=INFO
logging.level.org.eclipse.persistence=ERROR
# supported: H2, MYSQL # supported: H2, MYSQL
hawkbit.server.database=H2 hawkbit.server.database=H2

View File

@@ -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>

View File

@@ -8,7 +8,8 @@
http://www.eclipse.org/legal/epl-v10.html 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> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>org.eclipse.hawkbit</groupId> <groupId>org.eclipse.hawkbit</groupId>
@@ -36,6 +37,10 @@
<groupId>org.springframework.hateoas</groupId> <groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId> <artifactId>spring-hateoas</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-bus</artifactId>
</dependency>
<!-- Optional --> <!-- Optional -->
<dependency> <dependency>

View File

@@ -16,7 +16,7 @@ import java.util.Optional;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; 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.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException; 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.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus; import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.Artifact; 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.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetInfo; 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.hibernate.validator.constraints.NotEmpty;
import org.springframework.security.access.prepost.PreAuthorize; 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 * Service layer for all operations of the DDI API (with access permissions only
* for the controller). * for the controller).
@@ -59,7 +56,7 @@ public interface ControllerManagement {
Action addCancelActionStatus(@NotNull ActionStatus actionStatus); 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}. * {@link DownloadProgressEvent}.
* *
* @param statusId * @param statusId
@@ -148,19 +145,6 @@ public interface ControllerManagement {
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER) @PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
Target findOrRegisterTargetIfItDoesNotexist(@NotEmpty String controllerId, URI address); 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 * Retrieves last {@link Action} for a download of an artifact of given
* module and target. * module and target.

View File

@@ -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.ActionStatus;
import org.eclipse.hawkbit.repository.model.ActionWithStatusCount; import org.eclipse.hawkbit.repository.model.ActionWithStatusCount;
import org.eclipse.hawkbit.repository.model.DistributionSet; 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.DistributionSetType;
import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.RolloutGroup;

View File

@@ -11,7 +11,7 @@ package org.eclipse.hawkbit.repository;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; 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.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException; import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException; import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;

View File

@@ -8,6 +8,8 @@
*/ */
package org.eclipse.hawkbit.repository; package org.eclipse.hawkbit.repository;
import java.io.Serializable;
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions; import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfiguration;
import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue;
@@ -40,7 +42,8 @@ public interface TenantConfigurationManagement {
* if the property cannot be converted to the given * if the property cannot be converted to the given
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) @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 * Build the tenant configuration by the given key
@@ -55,8 +58,8 @@ public interface TenantConfigurationManagement {
* or returns the tenant configuration value * or returns the tenant configuration value
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
<T> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(TenantConfigurationKey configurationKey, <T extends Serializable> TenantConfigurationValue<T> buildTenantConfigurationValueByKey(
Class<T> propertyType, TenantConfiguration tenantConfiguration); TenantConfigurationKey configurationKey, Class<T> propertyType, TenantConfiguration tenantConfiguration);
/** /**
* Deletes a specific configuration for the current tenant. Does nothing in * Deletes a specific configuration for the current tenant. Does nothing in
@@ -87,7 +90,7 @@ public interface TenantConfigurationManagement {
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) @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 * Retrieves a configuration value from the e.g. tenant overwritten
@@ -113,7 +116,7 @@ public interface TenantConfigurationManagement {
* {@code propertyType} * {@code propertyType}
*/ */
@PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION) @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION)
<T> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey, <T extends Serializable> TenantConfigurationValue<T> getConfigurationValue(TenantConfigurationKey configurationKey,
Class<T> propertyType); Class<T> propertyType);
/** /**

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * 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. * Events to be published to refresh data on UI.

View File

@@ -6,22 +6,18 @@
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html * 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"; String getTenant();
private CacheConstants() {
}
} }

View File

@@ -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