Merge branch 'master' into Feature_Improve_Code_Quality
Conflicts: hawkbit-core/src/main/java/org/eclipse/hawkbit/api/ArtifactUrlHandlerProperties.java hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerServiceTest.java hawkbit-repository/src/main/java/org/eclipse/hawkbit/eventbus/CacheFieldEntityListener.java hawkbit-security-core/src/main/java/org/eclipse/hawkbit/security/SystemSecurityContext.java hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/artifacts/details/ArtifactBeanQuery.java Signed-off-by: Michael Hirsch <michael.hirsch@bosch-si.com>
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -53,3 +53,5 @@ local.properties
|
||||
# Maven
|
||||
maven.properties
|
||||
/*/maven.properties
|
||||
|
||||
hawkbit-repository/hawkbit-repository-jpa/.springBeans
|
||||
|
||||
@@ -11,3 +11,10 @@
|
||||
### REST API model changes for clients
|
||||
- ENTITYPagedList classes have been removed; generic PagedList used instead (e.g. PagedList<TargetRest> instead of TargetPagedList).
|
||||
- ENTITYsrest classes have been removed; List<ENTITYrest> used instead (e.g. List<TargetRest> instead of TargetsRest)
|
||||
|
||||
### Renamed api annotations
|
||||
- Annotation `org.eclipse.hawkbit.rest.resource.EnableRestResources` have changed to `org.eclipse.hawkbit.mgmt.annotation.EnableMgmtApi`
|
||||
- Annotation `org.eclipse.hawkbit.ddi.resource.EnableDirectDeviceApi` have changed to `org.eclipse.hawkbit.ddi.annotation.EnableDdiApi`
|
||||
|
||||
### Renamed maven modules
|
||||
- Module hawkbit-mgmt-api-client have changed to hawkbit-example-mgmt-simulator
|
||||
38
README.md
38
README.md
@@ -1,5 +1,7 @@
|
||||
Build: [](https://circleci.com/gh/eclipse/hawkbit)
|
||||
|
||||
<img src=hawkbit_logo.png width=533 height=246 />
|
||||
|
||||
# Eclipse.IoT hawkBit - Update Server
|
||||
|
||||
[hawkBit](https://projects.eclipse.org/projects/iot.hawkbit) is an domain independent back end solution for rolling out software updates to constrained edge devices as well as more powerful controllers and gateways connected to IP based networking infrastructure.
|
||||
@@ -41,9 +43,9 @@ $ java -jar ./examples/hawkbit-example-app/target/hawkbit-example-app-#version#.
|
||||
$ java -jar ./examples/hawkbit-device-simulator/target/hawkbit-device-simulator-#version#.jar
|
||||
```
|
||||
#### Generate Getting Started data
|
||||
[Example Management API Client](examples/hawkbit-mgmt-api-client)
|
||||
[Example Management API Client](examples/hawkbit-example-mgmt-simulator)
|
||||
```
|
||||
$ java -jar ./examples/hawkbit-mgmt-api-client/target/hawkbit-mgmt-api-client-#version#.jar
|
||||
$ java -jar ./examples/hawkbit-example-mgmt-simulator/target/hawkbit-example-mgmt-simulator-#version#.jar
|
||||
```
|
||||
|
||||
# Releases and Roadmap
|
||||
@@ -57,16 +59,22 @@ $ java -jar ./examples/hawkbit-mgmt-api-client/target/hawkbit-mgmt-api-client-#v
|
||||
|
||||
|
||||
# Modules
|
||||
`hawkbit-core` : internal interfaces and utility classes..
|
||||
`hawkbit-security-core` : authentication and authorization.
|
||||
`hawkbit-security-integration` : authentication and authorization integrated with the APIs.
|
||||
`hawkbit-artifact-repository-mongo` : artifact repository implementation to MongoDB.
|
||||
`hawkbit-autoconfigure` : spring-boot auto-configuration.
|
||||
`hawkbit-dmf-api` : API for the Device Management Integration.
|
||||
`hawkbit-dmf-amqp` : AMQP endpoint implementation for the DMF API.
|
||||
`hawkbit-repository` : repository implementation based on SQL for all meta-data.
|
||||
`hawkbit-http-security` : implementation for security filters for HTTP.
|
||||
`hawkbit-rest-api` : API classes for the REST Management API.
|
||||
`hawkbit-rest-resource` : HTTP REST endpoints for the Management and the Direct Device API.
|
||||
`hawkbit-ui` : Vaadin UI.
|
||||
`hawkbit-cache-redis` : spring cache manager configuration and implementation with redis, distributed cache and distributed events.
|
||||
* `examples` : hawkBit examples
|
||||
* `hawkbit-artifact-repository-mongo` : Artifact repository implementation to mongoDB.
|
||||
* `hawkbit-autoconfigure` : Spring-boot auto-configuration.
|
||||
* `hawkbit-cache-redis` : Spring cache manager configuration and implementation with redis, distributed cache and distributed events.
|
||||
* `hawkbit-core` : Core elements for internal interfaces and utility classes.
|
||||
* `hawkbit-ddi-api` : The hawkBit DDI API.
|
||||
* `hawkbit-ddi-dl-api` : The hawkBit DDI Download API.
|
||||
* `hawkbit-ddi-resource` : Implementation of the hawkBit DDI API
|
||||
* `hawkbit-dmf-amqp` : AMQP endpoint implementation for the DMF API.
|
||||
* `hawkbit-dmf-api` : API for the Device Management Integration.
|
||||
* `hawkbit-http-security` : Implementation for security filters for HTTP.
|
||||
* `hawkbit-mgmt-api` : The hawkBit Management API
|
||||
* `hawkbit-mgmt-resource` : Implementation of the hawkBit Management API
|
||||
* `hawkbit-repository` : Repository implementation based on SQL for all meta-data.
|
||||
* `hawkbit-rest-core` : Core elements for the rest modules.
|
||||
* `hawkbit-security-core` : Core security elements.
|
||||
* `hawkbit-security-integration` : Security integration elements to integrate security into hawkBit.
|
||||
* `hawkbit-test-report` : Test reports
|
||||
* `hawkbit-ui` : Vaadin UI.
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
Example projects that show how _hawkBit_ can be used to create, run or access an _hawkBit_ empowered update server.
|
||||
|
||||
- `hawkbit-device-simulator` : Simulates device software updates, leveraging the hawkBit device integration options.
|
||||
- `hawkbit-example-app` : Allows you to run a Spring Boot and hawkBit based update server. Includes all _hawkBit_ interfaces, i.e. DDI, DMF, Mgmt-API, Mgmt-UI.
|
||||
- `hawkbit-custom-theme-example` : Example for a customized theme for Management UI.
|
||||
- `hawkbit-mgmt-api-client` : Example client for the _hawkBit_ Management API.
|
||||
- `hawkbit-device-simulator` : Simulates device software updates, leveraging the hawkBit device integration options.
|
||||
- `hawkbit-example-app` : Allows you to run the Spring Boot hawkBit app. Includes all _hawkBit_ interfaces, i.e. DDI, DMF, Mgmt-API, Mgmt-UI.
|
||||
- `hawkbit-example-core-feign-client` : Core resources for the client examples.
|
||||
- `hawkbit-example-ddi-feign-client` : Example _hawkBit_ DDI client based on the _hawkBit_ DDI API.
|
||||
- `hawkbit-example-mgmt-feign-client` : Example _hawkBit_ Management client based on the _hawkBit_ Management API
|
||||
- `hawkbit-example-mgmt-simulator` : Example client simulation for the _hawkBit_ Management API based on Spring Boot and the hawkbit-example-mgmt-feign-client.
|
||||
|
||||
|
||||
@@ -79,6 +79,11 @@
|
||||
<artifactId>hawkbit-http-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
|
||||
@@ -8,11 +8,10 @@ package org.eclipse.hawkbit.app;
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
|
||||
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.EnableJpaRepository;
|
||||
import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* A {@link SpringBootApplication} annotated class with a main method to start.
|
||||
@@ -20,10 +19,10 @@ import org.springframework.context.annotation.Import;
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@Import({ RepositoryApplicationConfiguration.class })
|
||||
@EnableHawkbitManagedSecurityConfiguration
|
||||
// Exception squid:S1118 - Spring boot standard behavior
|
||||
@SuppressWarnings({ "squid:S1118" })
|
||||
@EnableJpaRepository
|
||||
public class Start {
|
||||
/**
|
||||
* Main method to start the spring-boot application.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>hawkbit-device-simulator</artifactId>
|
||||
<name>hawkBit :: Device Simulator</name>
|
||||
<name>hawkBit-example :: Device Simulator</name>
|
||||
<description>Device Management Federation API based simulator</description>
|
||||
|
||||
<build>
|
||||
@@ -71,6 +71,10 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
@@ -82,16 +86,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vaadin</groupId>
|
||||
@@ -106,10 +100,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
@@ -117,12 +107,10 @@
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
<version>8.14.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<version>8.12.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
|
||||
@@ -27,7 +27,7 @@ public abstract class AbstractSimulatedDevice {
|
||||
private UpdateStatus updateStatus = new UpdateStatus(ResponseStatus.SUCCESSFUL, "Simulation complete!");
|
||||
private Protocol protocol = Protocol.DMF_AMQP;
|
||||
private String targetSecurityToken;
|
||||
|
||||
private int pollDelaySec;
|
||||
private int nextPollCounterSec;
|
||||
|
||||
/**
|
||||
@@ -84,13 +84,30 @@ public abstract class AbstractSimulatedDevice {
|
||||
* the ID of the simulated device
|
||||
* @param tenant
|
||||
* the tenant of the simulated device
|
||||
* @param int
|
||||
* pollDelaySec
|
||||
*/
|
||||
AbstractSimulatedDevice(final String id, final String tenant, final Protocol protocol) {
|
||||
AbstractSimulatedDevice(final String id, final String tenant, final Protocol protocol, final int pollDelaySec) {
|
||||
this.id = id;
|
||||
this.tenant = tenant;
|
||||
this.status = Status.UNKNWON;
|
||||
this.progress = 0.0;
|
||||
this.protocol = protocol;
|
||||
this.pollDelaySec = pollDelaySec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be called by a scheduler to trigger a device polling, like in real
|
||||
* scenarios devices are frequently asking for updates etc.
|
||||
*/
|
||||
public abstract void poll();
|
||||
|
||||
public int getPollDelaySec() {
|
||||
return pollDelaySec;
|
||||
}
|
||||
|
||||
public void setPollDelaySec(final int pollDelaySec) {
|
||||
this.pollDelaySec = pollDelaySec;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,6 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DDISimulatedDevice.class);
|
||||
|
||||
private final int pollDelaySec;
|
||||
private final ControllerResource controllerResource;
|
||||
|
||||
private final DeviceSimulatorUpdater deviceUpdater;
|
||||
@@ -45,11 +44,9 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
*/
|
||||
public DDISimulatedDevice(final String id, final String tenant, final int pollDelaySec,
|
||||
final ControllerResource controllerResource, final DeviceSimulatorUpdater deviceUpdater) {
|
||||
super(id, tenant, Protocol.DDI_HTTP);
|
||||
this.pollDelaySec = pollDelaySec;
|
||||
super(id, tenant, Protocol.DDI_HTTP, pollDelaySec);
|
||||
this.controllerResource = controllerResource;
|
||||
this.deviceUpdater = deviceUpdater;
|
||||
setNextPollCounterSec(pollDelaySec);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,13 +55,10 @@ public class DDISimulatedDevice extends AbstractSimulatedDevice {
|
||||
removed = true;
|
||||
}
|
||||
|
||||
public int getPollDelaySec() {
|
||||
return pollDelaySec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls the base URL for the DDI API interface.
|
||||
*/
|
||||
@Override
|
||||
public void poll() {
|
||||
if (!removed) {
|
||||
final String basePollJson = controllerResource.get(getTenant(), getId());
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
|
||||
/**
|
||||
* A simulated device using the DMF API of the hawkBit update server.
|
||||
*/
|
||||
public class DMFSimulatedDevice extends AbstractSimulatedDevice {
|
||||
private final SpSenderService spSenderService;
|
||||
|
||||
/**
|
||||
* @param id
|
||||
@@ -19,8 +22,15 @@ public class DMFSimulatedDevice extends AbstractSimulatedDevice {
|
||||
* @param tenant
|
||||
* the tenant of the simulated device
|
||||
*/
|
||||
public DMFSimulatedDevice(final String id, final String tenant) {
|
||||
super(id, tenant, Protocol.DMF_AMQP);
|
||||
public DMFSimulatedDevice(final String id, final String tenant, final SpSenderService spSenderService,
|
||||
final int pollDelaySec) {
|
||||
super(id, tenant, Protocol.DMF_AMQP, pollDelaySec);
|
||||
this.spSenderService = spSenderService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void poll() {
|
||||
spSenderService.createOrUpdateThing(super.getTenant(), super.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -25,7 +25,7 @@ import org.springframework.stereotype.Service;
|
||||
@Service
|
||||
public class DeviceSimulatorRepository {
|
||||
|
||||
private final Map<DeviceKey, AbstractSimulatedDevice> devices = new LinkedHashMap<>();
|
||||
private final Map<DeviceKey, AbstractSimulatedDevice> devices = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
private SimulatedDeviceFactory deviceFactory;
|
||||
|
||||
@@ -10,8 +10,6 @@ package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.DigestOutputStream;
|
||||
import java.security.KeyManagementException;
|
||||
@@ -34,6 +32,7 @@ import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.eclipse.hawkbit.dmf.json.model.Artifact;
|
||||
import org.eclipse.hawkbit.dmf.json.model.Artifact.UrlProtocol;
|
||||
import org.eclipse.hawkbit.dmf.json.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.UpdateStatus.ResponseStatus;
|
||||
@@ -59,7 +58,7 @@ import com.google.common.io.ByteStreams;
|
||||
public class DeviceSimulatorUpdater {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DeviceSimulatorUpdater.class);
|
||||
|
||||
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(4);
|
||||
private static final ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(8);
|
||||
|
||||
@Autowired
|
||||
private SpSenderService spSenderService;
|
||||
@@ -99,7 +98,8 @@ public class DeviceSimulatorUpdater {
|
||||
|
||||
// plug and play - non existing device will be auto created
|
||||
if (device == null) {
|
||||
device = repository.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, -1, null, null));
|
||||
device = repository
|
||||
.add(deviceFactory.createSimulatedDevice(id, tenant, Protocol.DMF_AMQP, 1800, null, null));
|
||||
}
|
||||
|
||||
device.setProgress(0.0);
|
||||
@@ -149,6 +149,8 @@ public class DeviceSimulatorUpdater {
|
||||
eventbus.post(new ProgressUpdate(device));
|
||||
return;
|
||||
}
|
||||
// download is 80% of the game after all
|
||||
device.setProgress(0.8);
|
||||
}
|
||||
|
||||
final double newProgress = device.getProgress() + 0.2;
|
||||
@@ -195,18 +197,14 @@ public class DeviceSimulatorUpdater {
|
||||
|
||||
private static void handleArtifacts(final String targetToken, final List<UpdateStatus> status,
|
||||
final Artifact artifact) {
|
||||
artifact.getUrls().entrySet().forEach(entry -> {
|
||||
switch (entry.getKey()) {
|
||||
case HTTP:
|
||||
case HTTPS:
|
||||
status.add(downloadUrl(entry.getValue(), targetToken, artifact.getHashes().getSha1(),
|
||||
artifact.getSize()));
|
||||
break;
|
||||
default:
|
||||
// not supported yet
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (artifact.getUrls().containsKey(UrlProtocol.HTTPS)) {
|
||||
status.add(downloadUrl(artifact.getUrls().get(UrlProtocol.HTTPS), targetToken,
|
||||
artifact.getHashes().getSha1(), artifact.getSize()));
|
||||
} else if (artifact.getUrls().containsKey(UrlProtocol.HTTP)) {
|
||||
status.add(downloadUrl(artifact.getUrls().get(UrlProtocol.HTTP), targetToken,
|
||||
artifact.getHashes().getSha1(), artifact.getSize()));
|
||||
}
|
||||
}
|
||||
|
||||
private static UpdateStatus downloadUrl(final String url, final String targetToken, final String sha1Hash,
|
||||
@@ -233,18 +231,15 @@ public class DeviceSimulatorUpdater {
|
||||
return new UpdateStatus(ResponseStatus.ERROR, message);
|
||||
}
|
||||
|
||||
final File tempFile = File.createTempFile("uploadFile", null);
|
||||
// Exception squid:S2070 - not used for hashing sensitive
|
||||
// data
|
||||
@SuppressWarnings("squid:S2070")
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
|
||||
try (final DigestOutputStream dos = new DigestOutputStream(new FileOutputStream(tempFile), md)) {
|
||||
try (final BufferedOutputStream bdos = new BufferedOutputStream(dos)) {
|
||||
try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) {
|
||||
overallread = ByteStreams.copy(bis, bdos);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (tempFile != null && !tempFile.delete()) {
|
||||
LOGGER.error("Could not delete temporary file: {}", tempFile);
|
||||
try (final BufferedOutputStream bdos = new BufferedOutputStream(
|
||||
new DigestOutputStream(ByteStreams.nullOutputStream(), md))) {
|
||||
try (BufferedInputStream bis = new BufferedInputStream(response.getEntity().getContent())) {
|
||||
overallread = ByteStreams.copy(bis, bdos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +257,7 @@ public class DeviceSimulatorUpdater {
|
||||
}
|
||||
|
||||
} catch (IOException | KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
|
||||
LOGGER.error("Failed to download {} with {}", url, e.getMessage());
|
||||
LOGGER.error("Failed to download" + url, e);
|
||||
return new UpdateStatus(ResponseStatus.ERROR, "Failed to download " + url + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
@@ -272,6 +267,10 @@ public class DeviceSimulatorUpdater {
|
||||
}
|
||||
|
||||
private static String hideTokenDetails(final String targetToken) {
|
||||
if (targetToken == null) {
|
||||
return "<NULL!>";
|
||||
}
|
||||
|
||||
if (targetToken.isEmpty()) {
|
||||
return "<EMTPTY!>";
|
||||
}
|
||||
|
||||
@@ -8,12 +8,11 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.event.NextPollCounterUpdate;
|
||||
import org.slf4j.Logger;
|
||||
@@ -51,18 +50,17 @@ public class NextPollTimeController {
|
||||
private class NextPollUpdaterRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
final List<AbstractSimulatedDevice> devices = repository.getAll().stream()
|
||||
.filter(device -> device instanceof DDISimulatedDevice).collect(Collectors.toList());
|
||||
final Collection<AbstractSimulatedDevice> devices = repository.getAll();
|
||||
|
||||
devices.forEach(device -> {
|
||||
int nextCounter = device.getNextPollCounterSec() - 1;
|
||||
if (nextCounter < 0 && device instanceof DDISimulatedDevice) {
|
||||
if (nextCounter < 0) {
|
||||
try {
|
||||
pollService.submit(() -> ((DDISimulatedDevice) device).poll());
|
||||
pollService.submit(() -> device.poll());
|
||||
} catch (final IllegalStateException e) {
|
||||
LOGGER.trace("Device could not be polled", e);
|
||||
}
|
||||
nextCounter = ((DDISimulatedDevice) device).getPollDelaySec();
|
||||
nextCounter = device.getPollDelaySec();
|
||||
}
|
||||
|
||||
device.setNextPollCounterSec(nextCounter);
|
||||
|
||||
@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.simulator;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.eclipse.hawkbit.simulator.http.ControllerResource;
|
||||
import org.eclipse.hawkbit.simulator.http.GatewayTokenInterceptor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -28,6 +29,9 @@ public class SimulatedDeviceFactory {
|
||||
@Autowired
|
||||
private DeviceSimulatorUpdater deviceUpdater;
|
||||
|
||||
@Autowired
|
||||
private SpSenderService spSenderService;
|
||||
|
||||
/**
|
||||
* Creating a simulated devices.
|
||||
*
|
||||
@@ -41,7 +45,7 @@ public class SimulatedDeviceFactory {
|
||||
*/
|
||||
public AbstractSimulatedDevice createSimulatedDevice(final String id, final String tenant,
|
||||
final Protocol protocol) {
|
||||
return createSimulatedDevice(id, tenant, protocol, 30, null, null);
|
||||
return createSimulatedDevice(id, tenant, protocol, 1800, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +59,7 @@ public class SimulatedDeviceFactory {
|
||||
* the protocol which should be used be the simulated device
|
||||
* @param pollDelaySec
|
||||
* the poll delay time in seconds which should be used for
|
||||
* {@link DDISimulatedDevice}s
|
||||
* {@link DDISimulatedDevice}s and {@link DMFSimulatedDevice}
|
||||
* @param baseEndpoint
|
||||
* the http base endpoint which should be used for
|
||||
* {@link DDISimulatedDevice}s
|
||||
@@ -68,7 +72,7 @@ public class SimulatedDeviceFactory {
|
||||
final int pollDelaySec, final URL baseEndpoint, final String gatewayToken) {
|
||||
switch (protocol) {
|
||||
case DMF_AMQP:
|
||||
return new DMFSimulatedDevice(id, tenant);
|
||||
return new DMFSimulatedDevice(id, tenant, spSenderService, pollDelaySec);
|
||||
case DDI_HTTP:
|
||||
final ControllerResource controllerResource = Feign.builder().logger(new Logger.ErrorLogger())
|
||||
.requestInterceptor(new GatewayTokenInterceptor(gatewayToken)).logLevel(Logger.Level.BASIC)
|
||||
|
||||
@@ -66,7 +66,7 @@ public class SimulationController {
|
||||
@RequestParam(value = "tenant", defaultValue = "DEFAULT") final String tenant,
|
||||
@RequestParam(value = "api", defaultValue = "dmf") final String api,
|
||||
@RequestParam(value = "endpoint", defaultValue = "http://localhost:8080") final String endpoint,
|
||||
@RequestParam(value = "polldelay", defaultValue = "30") final int pollDelay,
|
||||
@RequestParam(value = "polldelay", defaultValue = "1800") final int pollDelay,
|
||||
@RequestParam(value = "gatewaytoken", defaultValue = "") final String gatewayToken)
|
||||
throws MalformedURLException {
|
||||
|
||||
@@ -86,10 +86,6 @@ public class SimulationController {
|
||||
final String deviceId = name + i;
|
||||
repository.add(deviceFactory.createSimulatedDevice(deviceId, tenant, protocol, pollDelay, new URL(endpoint),
|
||||
gatewayToken));
|
||||
|
||||
if (protocol == Protocol.DMF_AMQP) {
|
||||
spSenderService.createOrUpdateThing(tenant, deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
return ResponseEntity.ok("Updated " + amount + " DMF connected targets!");
|
||||
|
||||
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.simulator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
@@ -68,9 +69,9 @@ public class SimulationProperties {
|
||||
private String endpoint = "http://localhost:8080";
|
||||
|
||||
/**
|
||||
* Poll time in case of DDI API based simulation.
|
||||
* Poll time in {@link TimeUnit#SECONDS} for simulated devices.
|
||||
*/
|
||||
private int pollDelay = 30;
|
||||
private int pollDelay = (int) TimeUnit.MINUTES.toSeconds(30);
|
||||
|
||||
/**
|
||||
* Optional gateway token for DDI API based simulation.
|
||||
|
||||
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.simulator;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice.Protocol;
|
||||
import org.eclipse.hawkbit.simulator.amqp.SpSenderService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -54,10 +53,6 @@ public class SimulatorStartup implements ApplicationListener<ContextRefreshedEve
|
||||
} catch (final MalformedURLException e) {
|
||||
LOGGER.error("Creation of simulated device at startup failed.", e);
|
||||
}
|
||||
|
||||
if (autostart.getApi() == Protocol.DMF_AMQP) {
|
||||
spSenderService.createOrUpdateThing(autostart.getTenant(), deviceId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,54 +8,107 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
import org.springframework.amqp.core.FanoutExchange;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.amqp.core.QueueBuilder;
|
||||
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
|
||||
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
|
||||
import org.springframework.amqp.support.converter.MessageConverter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.retry.backoff.ExponentialBackOffPolicy;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
|
||||
/**
|
||||
* The spring AMQP configuration to use a AMQP for communication with SP update
|
||||
* server.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(AmqpProperties.class)
|
||||
public class AmqpConfiguration {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AmqpConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
protected AmqpProperties amqpProperties;
|
||||
|
||||
@Autowired
|
||||
private ConnectionFactory connectionFactory;
|
||||
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
/**
|
||||
* Create jackson message converter bean.
|
||||
*
|
||||
* @return the jackson message converter
|
||||
* @return {@link RabbitTemplate} with automatic retry, published confirms
|
||||
* and {@link Jackson2JsonMessageConverter}.
|
||||
*/
|
||||
@Bean
|
||||
public MessageConverter jsonMessageConverter() {
|
||||
final Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
|
||||
rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter);
|
||||
return jackson2JsonMessageConverter;
|
||||
public RabbitTemplate rabbitTemplate() {
|
||||
final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
|
||||
rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
|
||||
|
||||
final RetryTemplate retryTemplate = new RetryTemplate();
|
||||
retryTemplate.setBackOffPolicy(new ExponentialBackOffPolicy());
|
||||
rabbitTemplate.setRetryTemplate(retryTemplate);
|
||||
|
||||
rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
|
||||
if (ack) {
|
||||
LOGGER.debug("Message with correlation ID {} confirmed by broker.", correlationData.getId());
|
||||
} else {
|
||||
LOGGER.error("Broker is unable to handle message with correlation ID {} : {}", correlationData.getId(),
|
||||
cause);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return rabbitTemplate;
|
||||
}
|
||||
|
||||
@Configuration
|
||||
protected static class RabbitConnectionFactoryCreator {
|
||||
|
||||
/**
|
||||
* {@link ConnectionFactory} with enabled publisher confirms and
|
||||
* heartbeat.
|
||||
*
|
||||
* @param config
|
||||
* with standard {@link RabbitProperties}
|
||||
* @return {@link ConnectionFactory}
|
||||
*/
|
||||
@Bean
|
||||
public ConnectionFactory rabbitConnectionFactory(final RabbitProperties config) {
|
||||
final CachingConnectionFactory factory = new CachingConnectionFactory();
|
||||
factory.setRequestedHeartBeat(60);
|
||||
factory.setPublisherConfirms(true);
|
||||
|
||||
final String addresses = config.getAddresses();
|
||||
factory.setAddresses(addresses);
|
||||
if (config.getHost() != null) {
|
||||
factory.setHost(config.getHost());
|
||||
factory.setPort(config.getPort());
|
||||
}
|
||||
if (config.getUsername() != null) {
|
||||
factory.setUsername(config.getUsername());
|
||||
}
|
||||
if (config.getPassword() != null) {
|
||||
factory.setPassword(config.getPassword());
|
||||
}
|
||||
if (config.getVirtualHost() != null) {
|
||||
factory.setVirtualHost(config.getVirtualHost());
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,9 +118,12 @@ public class AmqpConfiguration {
|
||||
* @return the queue
|
||||
*/
|
||||
@Bean
|
||||
public Queue receiverConnectorQueueFromSp() {
|
||||
return new Queue(amqpProperties.getReceiverConnectorQueueFromSp(), true, false, false,
|
||||
getDeadLetterExchangeArgs());
|
||||
public Queue receiverConnectorQueueFromHawkBit() {
|
||||
final Map<String, Object> arguments = getDeadLetterExchangeArgs();
|
||||
arguments.putAll(getTTLMaxArgs());
|
||||
|
||||
return QueueBuilder.nonDurable(amqpProperties.getReceiverConnectorQueueFromSp()).autoDelete()
|
||||
.withArguments(arguments).build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,19 +133,19 @@ public class AmqpConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public FanoutExchange exchangeQueueToConnector() {
|
||||
return new FanoutExchange(amqpProperties.getSenderForSpExchange());
|
||||
return new FanoutExchange(amqpProperties.getSenderForSpExchange(), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Binding
|
||||
* {@link AmqpConfiguration#receiverConnectorQueueFromSp()} to
|
||||
* {@link AmqpConfiguration#receiverConnectorQueueFromHawkBit()} to
|
||||
* {@link AmqpConfiguration#exchangeQueueToConnector()}.
|
||||
*
|
||||
* @return the binding and create the queue and exchange
|
||||
*/
|
||||
@Bean
|
||||
public Binding bindReceiverQueueToSpExchange() {
|
||||
return BindingBuilder.bind(receiverConnectorQueueFromSp()).to(exchangeQueueToConnector());
|
||||
return BindingBuilder.bind(receiverConnectorQueueFromHawkBit()).to(exchangeQueueToConnector());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +155,7 @@ public class AmqpConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public Queue deadLetterQueue() {
|
||||
return new Queue(amqpProperties.getDeadLetterQueue(), true, false, true);
|
||||
return QueueBuilder.nonDurable(amqpProperties.getDeadLetterQueue()).withArguments(getTTLMaxArgs()).build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +165,7 @@ public class AmqpConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public FanoutExchange exchangeDeadLetter() {
|
||||
return new FanoutExchange(amqpProperties.getDeadLetterExchange());
|
||||
return new FanoutExchange(amqpProperties.getDeadLetterExchange(), false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,10 +187,10 @@ public class AmqpConfiguration {
|
||||
@Bean(name = { "listenerContainerFactory" })
|
||||
public SimpleRabbitListenerContainerFactory listenerContainerFactory() {
|
||||
final SimpleRabbitListenerContainerFactory containerFactory = new SimpleRabbitListenerContainerFactory();
|
||||
containerFactory.setDefaultRequeueRejected(false);
|
||||
containerFactory.setDefaultRequeueRejected(true);
|
||||
containerFactory.setConnectionFactory(connectionFactory);
|
||||
containerFactory.setConcurrentConsumers(20);
|
||||
containerFactory.setMaxConcurrentConsumers(20);
|
||||
containerFactory.setConcurrentConsumers(3);
|
||||
containerFactory.setMaxConcurrentConsumers(10);
|
||||
containerFactory.setPrefetchCount(20);
|
||||
return containerFactory;
|
||||
}
|
||||
@@ -145,4 +201,11 @@ public class AmqpConfiguration {
|
||||
return args;
|
||||
}
|
||||
|
||||
private static Map<String, Object> getTTLMaxArgs() {
|
||||
final Map<String, Object> args = new HashMap<>();
|
||||
args.put("x-message-ttl", Duration.ofDays(1).toMillis());
|
||||
args.put("x-max-length", 100_000);
|
||||
return args;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,21 +82,4 @@ public class MessageService {
|
||||
clazz.getTypeName());
|
||||
return (T) rabbitTemplate.getMessageConverter().fromMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to verify if lwm2m header is set.
|
||||
*
|
||||
* @param message
|
||||
* the message with the header
|
||||
* @param header
|
||||
* the header to verify
|
||||
*/
|
||||
public void checkIfLwm2mHeaderEmpty(final Message message, final String header) {
|
||||
final Object headerObject = message.getMessageProperties().getHeaders().get(header);
|
||||
if (null == headerObject) {
|
||||
logAndThrowMessageError(message, "Header of " + header + "empty.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import org.springframework.amqp.AmqpRejectAndDontRequeueException;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
@@ -55,7 +56,7 @@ public abstract class ReceiverService extends MessageService {
|
||||
if (contentType != null && contentType.contains("json")) {
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Content-Type is not JSON compatible");
|
||||
throw new AmqpRejectAndDontRequeueException("Content-Type is not JSON compatible");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,9 +8,14 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.amqp;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.core.Message;
|
||||
import org.springframework.amqp.core.MessageProperties;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.amqp.rabbit.support.CorrelationData;
|
||||
import org.springframework.amqp.support.converter.AbstractJavaTypeMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -22,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
*/
|
||||
public abstract class SenderService extends MessageService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SenderService.class);
|
||||
|
||||
/**
|
||||
* Constructor for sender service.
|
||||
*
|
||||
@@ -40,18 +47,26 @@ public abstract class SenderService extends MessageService {
|
||||
/**
|
||||
* Send a message if the message is not null.
|
||||
*
|
||||
* @param adress
|
||||
* @param address
|
||||
* the exchange name
|
||||
* @param message
|
||||
* the amqp message which will be send if its not null
|
||||
*/
|
||||
public void sendMessage(final String adress, final Message message) {
|
||||
public void sendMessage(final String address, final Message message) {
|
||||
if (message == null) {
|
||||
return;
|
||||
}
|
||||
message.getMessageProperties().getHeaders().remove(AbstractJavaTypeMapper.DEFAULT_CLASSID_FIELD_NAME);
|
||||
rabbitTemplate.setExchange(adress);
|
||||
rabbitTemplate.send(message);
|
||||
final String correlationId = UUID.randomUUID().toString();
|
||||
message.getMessageProperties().setCorrelationId(correlationId.getBytes());
|
||||
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Sending message {} to exchange {} with correlationId {}", message, address, correlationId);
|
||||
} else {
|
||||
LOGGER.debug("Sending message to exchange {} with correlationId {}", address, correlationId);
|
||||
}
|
||||
|
||||
rabbitTemplate.send(address, null, message, new CorrelationData(correlationId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,14 +35,21 @@ import com.google.common.collect.Lists;
|
||||
public class SpReceiverService extends ReceiverService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReceiverService.class);
|
||||
|
||||
public static final String SOFTWARE_MODULE_FIRMWARE = "firmware";
|
||||
|
||||
private final SpSenderService spSenderService;
|
||||
|
||||
private final DeviceSimulatorUpdater deviceUpdater;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param rabbitTemplate
|
||||
* for sending messages
|
||||
* @param amqpProperties
|
||||
* for amqp configuration
|
||||
* @param spSenderService
|
||||
* to send messages
|
||||
* @param deviceUpdater
|
||||
* simulator service for updates
|
||||
*/
|
||||
@Autowired
|
||||
public SpReceiverService(final RabbitTemplate rabbitTemplate, final AmqpProperties amqpProperties,
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.event;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
*/
|
||||
public class NextPollCounterUpdate {
|
||||
|
||||
private final List<AbstractSimulatedDevice> devices;
|
||||
private final Collection<AbstractSimulatedDevice> devices;
|
||||
|
||||
/**
|
||||
* Creates poll timer update event.
|
||||
@@ -28,14 +28,14 @@ public class NextPollCounterUpdate {
|
||||
* @param devices
|
||||
* the devices which progress has been updated
|
||||
*/
|
||||
public NextPollCounterUpdate(final List<AbstractSimulatedDevice> devices) {
|
||||
public NextPollCounterUpdate(final Collection<AbstractSimulatedDevice> devices) {
|
||||
this.devices = devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the devices of the event
|
||||
*/
|
||||
public List<AbstractSimulatedDevice> getDevices() {
|
||||
public Collection<AbstractSimulatedDevice> getDevices() {
|
||||
return devices;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ public class GenerateDialog extends Window {
|
||||
|
||||
pollDelayTextField = createRequiredTextfield("poll delay (sec)", new ObjectProperty<Integer>(10),
|
||||
FontAwesome.CLOCK_O, new RangeValidator<Integer>("Must be between 1 and 60", Integer.class, 1, 60));
|
||||
pollDelayTextField.setVisible(false);
|
||||
|
||||
pollUrlTextField = createRequiredTextfield("base poll URL endpoint", "http://localhost:8080",
|
||||
FontAwesome.FLAG_O, new RegexpValidator(
|
||||
@@ -193,7 +192,6 @@ public class GenerateDialog extends Window {
|
||||
protocolGroup.select(Protocol.DMF_AMQP);
|
||||
protocolGroup.addValueChangeListener(event -> {
|
||||
final boolean directDeviceOptionSelected = event.getProperty().getValue().equals(Protocol.DDI_HTTP);
|
||||
pollDelayTextField.setVisible(directDeviceOptionSelected);
|
||||
pollUrlTextField.setVisible(directDeviceOptionSelected);
|
||||
gatewayTokenTextField.setVisible(directDeviceOptionSelected);
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.simulator.ui;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.hawkbit.simulator.AbstractSimulatedDevice;
|
||||
@@ -167,7 +167,7 @@ public class SimulatorView extends VerticalLayout implements View {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Subscribe
|
||||
public void pollCounterUpdate(final NextPollCounterUpdate update) {
|
||||
final List<AbstractSimulatedDevice> devices = update.getDevices();
|
||||
final Collection<AbstractSimulatedDevice> devices = update.getDevices();
|
||||
this.getUI().access(() -> devices.forEach(device -> {
|
||||
final BeanItem<AbstractSimulatedDevice> item = beanContainer.getItem(device.getId());
|
||||
if (item != null) {
|
||||
|
||||
@@ -24,7 +24,6 @@ spring.rabbitmq.virtualHost=/
|
||||
spring.rabbitmq.host=localhost
|
||||
spring.rabbitmq.port=5672
|
||||
spring.rabbitmq.dynamic=true
|
||||
spring.rabbitmq.listener.prefetch=100
|
||||
|
||||
security.basic.enabled=false
|
||||
server.port=8083
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?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.catalina.startup.DigesterFactory" level="ERROR" />
|
||||
|
||||
<Root level="INFO">
|
||||
<AppenderRef ref="Console" />
|
||||
</Root>
|
||||
|
||||
</configuration>
|
||||
@@ -17,7 +17,7 @@
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-example-app</artifactId>
|
||||
<name>hawkBit :: Example App</name>
|
||||
<name>hawkBit-example :: UI Application</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -64,7 +64,12 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-rest-resource</artifactId>
|
||||
<artifactId>hawkbit-mgmt-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-ddi-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -87,6 +92,11 @@
|
||||
<artifactId>hawkbit-http-security</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
<dependency>
|
||||
@@ -96,16 +106,26 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Log4j API and Core implementation required for binding -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
</dependency>
|
||||
<!-- Logging binding for java-util-logging e.g. Tomcat -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jul-to-slf4j</artifactId>
|
||||
</dependency>
|
||||
<!-- Logging binding for Jakarta Commons Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<!-- Logging binding for Log4J Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
|
||||
@@ -8,13 +8,12 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.app;
|
||||
|
||||
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.EnableJpaRepository;
|
||||
import org.eclipse.hawkbit.autoconfigure.security.EnableHawkbitManagedSecurityConfiguration;
|
||||
import org.eclipse.hawkbit.controller.EnableDirectDeviceApi;
|
||||
import org.eclipse.hawkbit.rest.resource.EnableRestResources;
|
||||
import org.eclipse.hawkbit.ddi.EnableDdiApi;
|
||||
import org.eclipse.hawkbit.mgmt.EnableMgmtApi;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* A {@link SpringBootApplication} annotated class with a main method to start.
|
||||
@@ -22,10 +21,10 @@ import org.springframework.context.annotation.Import;
|
||||
*
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@Import({ RepositoryApplicationConfiguration.class })
|
||||
@EnableHawkbitManagedSecurityConfiguration
|
||||
@EnableRestResources
|
||||
@EnableDirectDeviceApi
|
||||
@EnableMgmtApi
|
||||
@EnableDdiApi
|
||||
@EnableJpaRepository
|
||||
// Exception squid:S1118 - Spring boot standard behavior
|
||||
@SuppressWarnings({ "squid:S1118" })
|
||||
public class Start {
|
||||
|
||||
32
examples/hawkbit-example-app/src/main/resources/logback.xml
Normal file
32
examples/hawkbit-example-app/src/main/resources/logback.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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" />
|
||||
|
||||
<!-- Security Log with hints on potential attacks -->
|
||||
<logger name="server-security" level="INFO" />
|
||||
|
||||
<Root level="INFO">
|
||||
<AppenderRef ref="Console" />
|
||||
</Root>
|
||||
|
||||
</configuration>
|
||||
13
examples/hawkbit-example-core-feign-client/README.md
Normal file
13
examples/hawkbit-example-core-feign-client/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Eclipse.IoT hawkBit - Example Core Feign Client
|
||||
|
||||
This modules contains core beans that are needed to create a [Feign Client](https://github.com/Netflix/feign) with hwakBit.
|
||||
|
||||
# Compile
|
||||
|
||||
#### Build hawkbit-example-core-feign-client
|
||||
|
||||
```
|
||||
$ cd hawkbit/examples/hawkbit-example-core-feign-client
|
||||
$ mvn clean install
|
||||
```
|
||||
|
||||
46
examples/hawkbit-example-core-feign-client/pom.xml
Normal file
46
examples/hawkbit-example-core-feign-client/pom.xml
Normal file
@@ -0,0 +1,46 @@
|
||||
<!--
|
||||
|
||||
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-examples-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hawkbit-example-core-feign-client</artifactId>
|
||||
<name>hawkBit-example :: Feign Core Client</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix-core</artifactId>
|
||||
<version>1.0.7.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -6,7 +6,7 @@
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client;
|
||||
package org.eclipse.hawkbit.feign.core.client;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.feign.core.client;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.cloud.netflix.feign.FeignClientsConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import feign.Contract;
|
||||
import feign.Feign;
|
||||
|
||||
/**
|
||||
* Spring annotated java configuration class which defines necessary beans for
|
||||
* configure the feign-client.
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass(Feign.class)
|
||||
@Import(FeignClientsConfiguration.class)
|
||||
public class FeignClientConfiguration {
|
||||
|
||||
@Bean
|
||||
public ApplicationJsonRequestHeaderInterceptor jsonHeaderInterceptor() {
|
||||
return new ApplicationJsonRequestHeaderInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Contract feignContract() {
|
||||
return new IgnoreMultipleConsumersProducersSpringMvcContract();
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client;
|
||||
package org.eclipse.hawkbit.feign.core.client;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
14
examples/hawkbit-example-ddi-feign-client/README.md
Normal file
14
examples/hawkbit-example-ddi-feign-client/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# Eclipse.IoT hawkBit - Example DDI Feign Client API
|
||||
|
||||
This modules contains the declarative client binding resources of the DDI API.
|
||||
For more information see 'Feign Inheritance Support' at [Spring Cloud] (http://projects.spring.io/spring-cloud/spring-cloud.html).
|
||||
Powered by [Feign](https://github.com/Netflix/feign).
|
||||
|
||||
# Compile
|
||||
|
||||
#### Build hawkbit-example-ddi-feign-client
|
||||
|
||||
```
|
||||
$ cd hawkbit/examples/hawkbit-example-ddi-feign-client
|
||||
$ mvn clean install
|
||||
```
|
||||
68
examples/hawkbit-example-ddi-feign-client/pom.xml
Normal file
68
examples/hawkbit-example-ddi-feign-client/pom.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<!--
|
||||
|
||||
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 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-examples-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-example-ddi-feign-client</artifactId>
|
||||
|
||||
<name>hawkBit-example :: DDI Feign Client</name>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-netflix</artifactId>
|
||||
<version>1.0.7.RELEASE</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-example-core-feign-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-ddi-dl-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-ddi-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.ddi.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.ddi.dl.rest.api.DdiDlArtifactStoreControllerRestApi;
|
||||
import org.eclipse.hawkbit.ddi.dl.rest.api.DdiDlRestConstants;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the artifact store controller resource of the DDI-DL API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/" + DdiDlRestConstants.ARTIFACTS_V1_REQUEST_MAPPING)
|
||||
public interface DdiDlArtifactStoreControllerResourceClient extends DdiDlArtifactStoreControllerRestApi {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.ddi.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRootControllerRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the Rootcontroller resource of the DDI API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/" + DdiRestConstants.BASE_V1_REQUEST_MAPPING)
|
||||
public interface RootControllerResourceClient extends DdiRootControllerRestApi {
|
||||
|
||||
}
|
||||
15
examples/hawkbit-example-mgmt-feign-client/README.md
Normal file
15
examples/hawkbit-example-mgmt-feign-client/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Eclipse.IoT hawkBit - Example Management Feign Client API
|
||||
|
||||
This modules contains the declarative client binding resources of the Management API.
|
||||
For more information see 'Feign Inheritance Support' at [Spring Cloud] (http://projects.spring.io/spring-cloud/spring-cloud.html).
|
||||
Powered by [Feign](https://github.com/Netflix/feign).
|
||||
|
||||
# Compile
|
||||
|
||||
#### Build hawkbit-example-mgmt-feign-client
|
||||
|
||||
```
|
||||
$ cd hawkbit/examples/hawkbit-example-mgmt-feign-client
|
||||
$ mvn clean install
|
||||
```
|
||||
|
||||
56
examples/hawkbit-example-mgmt-feign-client/pom.xml
Normal file
56
examples/hawkbit-example-mgmt-feign-client/pom.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
|
||||
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-examples-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>hawkbit-example-mgmt-feign-client</artifactId>
|
||||
<name>hawkBit-example :: Management client API</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-example-core-feign-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-mgmt-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<!-- need to overwrite for the interface inheritance feature of feign-core -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<groupId>org.hibernate</groupId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -8,13 +8,14 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.DistributionSetRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the DistributionSet resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsets")
|
||||
public interface DistributionSetResourceClient extends DistributionSetRestApi {
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDistributionSetClientResource extends MgmtDistributionSetRestApi {
|
||||
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.DistributionSetTagRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTagRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the DistributionSetTag resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsettags")
|
||||
public interface DistributionSetTagResourceClient extends DistributionSetTagRestApi {
|
||||
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDistributionSetTagClientResource extends MgmtDistributionSetTagRestApi {
|
||||
}
|
||||
@@ -8,14 +8,15 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.DistributionSetTypeRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the DistributionSetType resource of the management API.
|
||||
*
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/distributionsettypes")
|
||||
public interface DistributionSetTypeResourceClient extends DistributionSetTypeRestApi {
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDistributionSetTypeClientResource extends MgmtDistributionSetTypeRestApi {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadArtifactRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* A feign-client interface declaration which allows to build a feign-client
|
||||
* stub.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDownloadArtifactClientResource extends MgmtDownloadArtifactRestApi {
|
||||
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.SoftwareModuleRestAPI;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDownloadRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the SoftwareModule resource of the management API.
|
||||
*
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/softwaremodules")
|
||||
public interface SoftwareModuleResourceClient extends SoftwareModuleRestAPI {
|
||||
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.DOWNLOAD_ID_V1_REQUEST_MAPPING_BASE)
|
||||
public interface MgmtDownloadClientResource extends MgmtDownloadRestApi {
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.RolloutRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the Rollout resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/rollouts")
|
||||
public interface RolloutResourceClient extends RolloutRestApi {
|
||||
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING)
|
||||
public interface MgmtRolloutClientResource extends MgmtRolloutRestApi {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import feign.Param;
|
||||
|
||||
/**
|
||||
* Client binding for the SoftwareModule resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
|
||||
public interface MgmtSoftwareModuleClientResource extends MgmtSoftwareModuleRestApi {
|
||||
|
||||
@Override
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{softwareModuleId}/artifacts")
|
||||
ResponseEntity<MgmtArtifact> uploadArtifact(@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@Param("file") final MultipartFile file,
|
||||
@RequestParam(value = "filename", required = false) final String optionalFileName,
|
||||
@RequestParam(value = "md5sum", required = false) final String md5Sum,
|
||||
@RequestParam(value = "sha1sum", required = false) final String sha1Sum);
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.SoftwareModuleTypeRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the oftwareModuleType resource of the management API.
|
||||
* Client binding for the SoftwareModuleType resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/softwaremoduletypes")
|
||||
public interface SoftwareModuleTypeResourceClient extends SoftwareModuleTypeRestApi {
|
||||
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING)
|
||||
public interface MgmtSoftwareModuleTypeClientResource extends MgmtSoftwareModuleTypeRestApi {
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSystemRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the {@link MgmtSystemRestApi}.
|
||||
*
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SYSTEM_V1_REQUEST_MAPPING)
|
||||
public interface MgmtSystemClientResource extends MgmtSystemRestApi {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSystemManagementRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the {@link MgmtSystemManagementRestApi}.
|
||||
*
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.SYSTEM_ADMIN_MAPPING)
|
||||
public interface MgmtSystemManagementClientResource extends MgmtSystemManagementRestApi {
|
||||
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.TargetRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the Target resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/targets")
|
||||
public interface TargetResourceClient extends TargetRestApi {
|
||||
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.TARGET_V1_REQUEST_MAPPING)
|
||||
public interface MgmtTargetClientResource extends MgmtTargetRestApi {
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.api.TargetTagRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetTagRestApi;
|
||||
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||
|
||||
/**
|
||||
* Client binding for the TargetTag resource of the management API.
|
||||
*/
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}/rest/v1/targettags")
|
||||
public interface TargetTagResourceClient extends TargetTagRestApi {
|
||||
|
||||
@FeignClient(url = "${hawkbit.url:localhost:8080}" + MgmtRestConstants.TARGET_TAG_V1_REQUEST_MAPPING)
|
||||
public interface MgmtTargetTagClientResource extends MgmtTargetTagRestApi {
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource.builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssigment;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Builder pattern for building {@link MgmtDistributionSetRequestBodyPost}.
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class DistributionSetBuilder {
|
||||
|
||||
private String name;
|
||||
private String version;
|
||||
private String type;
|
||||
private String description;
|
||||
private final List<MgmtSoftwareModuleAssigment> modules = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the distribution set
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DistributionSetBuilder moduleByID(final Long id) {
|
||||
final MgmtSoftwareModuleAssigment softwareModuleAssigmentRest = new MgmtSoftwareModuleAssigment();
|
||||
softwareModuleAssigmentRest.setId(id);
|
||||
modules.add(softwareModuleAssigmentRest);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version
|
||||
* the version of the distribution set
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder version(final String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the distribution set type name for this distribution set
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder type(final String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder description(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of
|
||||
* {@link MgmtDistributionSetRequestBodyPost} which can directly be used to
|
||||
* post on the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link MgmtDistributionSetRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtDistributionSetRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} to
|
||||
* create multiple distribution sets at once. An increasing number will be
|
||||
* used for version of the distribution set. The name and type will remain
|
||||
* the same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of distribution sets body which should be created
|
||||
* @return a list of {@link MgmtDistributionSetRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtDistributionSetRequestBodyPost> buildAsList(final int count) {
|
||||
return buildAsList(0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} to
|
||||
* create multiple distribution sets at once. An increasing number will be
|
||||
* used for version of the distribution set starting from given offset. The
|
||||
* name and type will remain the same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of distribution sets body which should be created
|
||||
* @param offset
|
||||
* for for index start
|
||||
* @return a list of {@link MgmtDistributionSetRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtDistributionSetRequestBodyPost> buildAsList(final int offset, final int count) {
|
||||
final ArrayList<MgmtDistributionSetRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
for (int index = offset; index < count + offset; index++) {
|
||||
bodyList.add(doBuild(String.valueOf(index)));
|
||||
}
|
||||
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private MgmtDistributionSetRequestBodyPost doBuild(final String suffix) {
|
||||
final MgmtDistributionSetRequestBodyPost body = new MgmtDistributionSetRequestBodyPost();
|
||||
body.setName(name);
|
||||
body.setVersion(version + suffix);
|
||||
body.setType(type);
|
||||
body.setDescription(description);
|
||||
body.setModules(modules);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,23 +11,25 @@ package org.eclipse.hawkbit.mgmt.client.resource.builder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeAssigmentRest;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeAssigment;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link DistributionSetTypeRequestBodyPost}.
|
||||
* Builder pattern for building {@link MgmtDistributionSetTypeRequestBodyPost}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class DistributionSetTypeBuilder {
|
||||
|
||||
private String key;
|
||||
private String name;
|
||||
private final List<SoftwareModuleTypeAssigmentRest> mandatorymodules = Lists.newArrayList();
|
||||
private final List<SoftwareModuleTypeAssigmentRest> optionalmodules = Lists.newArrayList();
|
||||
private String description;
|
||||
private final List<MgmtSoftwareModuleTypeAssigment> mandatorymodules = Lists.newArrayList();
|
||||
private final List<MgmtSoftwareModuleTypeAssigment> optionalmodules = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* @param key
|
||||
@@ -49,6 +51,16 @@ public class DistributionSetTypeBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetTypeBuilder description(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param softwareModuleTypeIds
|
||||
* the IDs of the software module types which should be mandatory
|
||||
@@ -57,7 +69,7 @@ public class DistributionSetTypeBuilder {
|
||||
*/
|
||||
public DistributionSetTypeBuilder mandatorymodules(final Long... softwareModuleTypeIds) {
|
||||
for (final Long id : softwareModuleTypeIds) {
|
||||
final SoftwareModuleTypeAssigmentRest softwareModuleTypeAssigmentRest = new SoftwareModuleTypeAssigmentRest();
|
||||
final MgmtSoftwareModuleTypeAssigment softwareModuleTypeAssigmentRest = new MgmtSoftwareModuleTypeAssigment();
|
||||
softwareModuleTypeAssigmentRest.setId(id);
|
||||
this.mandatorymodules.add(softwareModuleTypeAssigmentRest);
|
||||
}
|
||||
@@ -73,7 +85,7 @@ public class DistributionSetTypeBuilder {
|
||||
*/
|
||||
public DistributionSetTypeBuilder optionalmodules(final Long... softwareModuleTypeIds) {
|
||||
for (final Long id : softwareModuleTypeIds) {
|
||||
final SoftwareModuleTypeAssigmentRest softwareModuleTypeAssigmentRest = new SoftwareModuleTypeAssigmentRest();
|
||||
final MgmtSoftwareModuleTypeAssigment softwareModuleTypeAssigmentRest = new MgmtSoftwareModuleTypeAssigment();
|
||||
softwareModuleTypeAssigmentRest.setId(id);
|
||||
this.optionalmodules.add(softwareModuleTypeAssigmentRest);
|
||||
}
|
||||
@@ -82,39 +94,41 @@ public class DistributionSetTypeBuilder {
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of
|
||||
* {@link DistributionSetTypeRequestBodyPost} which can directly be used in
|
||||
* the RESTful-API.
|
||||
* {@link MgmtDistributionSetTypeRequestBodyPost} which can directly be used
|
||||
* in the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link DistributionSetTypeRequestBodyPost}
|
||||
* @return a single entry list of
|
||||
* {@link MgmtDistributionSetTypeRequestBodyPost}
|
||||
*/
|
||||
public List<DistributionSetTypeRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(name, key));
|
||||
public List<MgmtDistributionSetTypeRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link DistributionSetTypeRequestBodyPost} to
|
||||
* create multiple distribution set types at once. An increasing number will
|
||||
* be added to the name and key of the distribution set type. The optional
|
||||
* and mandatory software module types will remain the same.
|
||||
* Builds a list of multiple {@link MgmtDistributionSetTypeRequestBodyPost}
|
||||
* to create multiple distribution set types at once. An increasing number
|
||||
* will be added to the name and key of the distribution set type. The
|
||||
* optional and mandatory software module types will remain the same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of distribution sets type body which should be
|
||||
* created
|
||||
* @return a list of {@link DistributionSetTypeRequestBodyPost}
|
||||
* @return a list of {@link MgmtDistributionSetTypeRequestBodyPost}
|
||||
*/
|
||||
public List<DistributionSetTypeRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<DistributionSetTypeRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
public List<MgmtDistributionSetTypeRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<MgmtDistributionSetTypeRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(name + index, key + index));
|
||||
bodyList.add(doBuild(String.valueOf(index)));
|
||||
}
|
||||
return bodyList;
|
||||
|
||||
}
|
||||
|
||||
private DistributionSetTypeRequestBodyPost doBuild(final String prefixName, final String prefixKey) {
|
||||
final DistributionSetTypeRequestBodyPost body = new DistributionSetTypeRequestBodyPost();
|
||||
body.setKey(prefixKey);
|
||||
body.setName(prefixName);
|
||||
private MgmtDistributionSetTypeRequestBodyPost doBuild(final String suffix) {
|
||||
final MgmtDistributionSetTypeRequestBodyPost body = new MgmtDistributionSetTypeRequestBodyPost();
|
||||
body.setKey(key + suffix);
|
||||
body.setName(name + suffix);
|
||||
body.setDescription(description);
|
||||
body.setMandatorymodules(mandatorymodules);
|
||||
body.setOptionalmodules(optionalmodules);
|
||||
return body;
|
||||
@@ -8,13 +8,13 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.client.resource.builder;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutCondition;
|
||||
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutCondition.Condition;
|
||||
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutRestRequestBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition.Condition;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBody;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link RolloutRestRequestBody}.
|
||||
* Builder pattern for building {@link MgmtRolloutRestRequestBody}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@@ -27,6 +27,7 @@ public class RolloutBuilder {
|
||||
private long distributionSetId;
|
||||
private String successThreshold;
|
||||
private String errorThreshold;
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
@@ -59,6 +60,16 @@ public class RolloutBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description
|
||||
* @return the builder itself
|
||||
*/
|
||||
public RolloutBuilder description(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to assign to the target in the
|
||||
@@ -97,18 +108,19 @@ public class RolloutBuilder {
|
||||
*
|
||||
* @return the rest request body for creating a rollout
|
||||
*/
|
||||
public RolloutRestRequestBody build() {
|
||||
public MgmtRolloutRestRequestBody build() {
|
||||
return doBuild();
|
||||
}
|
||||
|
||||
private RolloutRestRequestBody doBuild() {
|
||||
final RolloutRestRequestBody body = new RolloutRestRequestBody();
|
||||
private MgmtRolloutRestRequestBody doBuild() {
|
||||
final MgmtRolloutRestRequestBody body = new MgmtRolloutRestRequestBody();
|
||||
body.setName(name);
|
||||
body.setAmountGroups(groupSize);
|
||||
body.setTargetFilterQuery(targetFilterQuery);
|
||||
body.setDistributionSetId(distributionSetId);
|
||||
body.setSuccessCondition(new RolloutCondition(Condition.THRESHOLD, successThreshold));
|
||||
body.setErrorCondition(new RolloutCondition(Condition.THRESHOLD, errorThreshold));
|
||||
body.setDescription(description);
|
||||
body.setSuccessCondition(new MgmtRolloutCondition(Condition.THRESHOLD, successThreshold));
|
||||
body.setErrorCondition(new MgmtRolloutCondition(Condition.THRESHOLD, errorThreshold));
|
||||
return body;
|
||||
}
|
||||
|
||||
@@ -11,13 +11,15 @@ package org.eclipse.hawkbit.mgmt.client.resource.builder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleAssigmentRest;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssigment;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link SoftwareModuleAssigmentRest}.
|
||||
* Builder pattern for building {@link MgmtSoftwareModuleAssigment}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class SoftwareModuleAssigmentBuilder {
|
||||
|
||||
private final List<Long> ids;
|
||||
@@ -37,15 +39,15 @@ public class SoftwareModuleAssigmentBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of {@link SoftwareModuleAssigmentRest}
|
||||
* Builds a list with a single entry of {@link MgmtSoftwareModuleAssigment}
|
||||
* which can directly be used in the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link SoftwareModuleAssigmentRest}
|
||||
* @return a single entry list of {@link MgmtSoftwareModuleAssigment}
|
||||
*/
|
||||
public List<SoftwareModuleAssigmentRest> build() {
|
||||
final List<SoftwareModuleAssigmentRest> softwareModuleAssigmentRestList = new ArrayList<>();
|
||||
public List<MgmtSoftwareModuleAssigment> build() {
|
||||
final List<MgmtSoftwareModuleAssigment> softwareModuleAssigmentRestList = new ArrayList<>();
|
||||
for (final Long id : ids) {
|
||||
final SoftwareModuleAssigmentRest softwareModuleAssigmentRest = new SoftwareModuleAssigmentRest();
|
||||
final MgmtSoftwareModuleAssigment softwareModuleAssigmentRest = new MgmtSoftwareModuleAssigment();
|
||||
softwareModuleAssigmentRest.setId(id);
|
||||
softwareModuleAssigmentRestList.add(softwareModuleAssigmentRest);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource.builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link MgmtSoftwareModuleRequestBodyPost}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class SoftwareModuleBuilder {
|
||||
|
||||
private String name;
|
||||
private String version;
|
||||
private String type;
|
||||
private String vendor;
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the software module
|
||||
* @return the builder itself
|
||||
*/
|
||||
public SoftwareModuleBuilder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version
|
||||
* the version of the software module
|
||||
* @return the builder itsefl
|
||||
*/
|
||||
public SoftwareModuleBuilder version(final String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the key of the software module type to be used for this
|
||||
* software module
|
||||
* @return the builder itself
|
||||
*/
|
||||
public SoftwareModuleBuilder type(final String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vendor
|
||||
* the vendor
|
||||
* @return the builder itself
|
||||
*/
|
||||
public SoftwareModuleBuilder vendor(final String vendor) {
|
||||
this.vendor = vendor;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description
|
||||
* @return the builder itself
|
||||
*/
|
||||
public SoftwareModuleBuilder description(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of
|
||||
* {@link MgmtSoftwareModuleRequestBodyPost} which can directly be used in
|
||||
* the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link MgmtSoftwareModuleRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtSoftwareModuleRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link MgmtSoftwareModuleRequestBodyPost} to
|
||||
* create multiple software module at once. An increasing number will be
|
||||
* added to the version of the software module. The name and type will
|
||||
* remain the same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of software module body which should be created
|
||||
* @return a list of {@link MgmtDistributionSetTypeRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtSoftwareModuleRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<MgmtSoftwareModuleRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(String.valueOf(index)));
|
||||
}
|
||||
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private MgmtSoftwareModuleRequestBodyPost doBuild(final String suffix) {
|
||||
final MgmtSoftwareModuleRequestBodyPost body = new MgmtSoftwareModuleRequestBodyPost();
|
||||
body.setName(name);
|
||||
body.setVersion(version + suffix);
|
||||
body.setType(type);
|
||||
body.setVendor(vendor);
|
||||
body.setDescription(description);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,14 +11,14 @@ package org.eclipse.hawkbit.mgmt.client.resource.builder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPost;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
|
||||
* Builder pattern for building {@link MgmtSoftwareModuleRequestBodyPost}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@@ -62,37 +62,38 @@ public class SoftwareModuleTypeBuilder {
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of
|
||||
* {@link SoftwareModuleTypeRequestBodyPost} which can directly be used in
|
||||
* the RESTful-API.
|
||||
* {@link MgmtSoftwareModuleTypeRequestBodyPost} which can directly be used
|
||||
* in the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link SoftwareModuleTypeRequestBodyPost}
|
||||
* @return a single entry list of
|
||||
* {@link MgmtSoftwareModuleTypeRequestBodyPost}
|
||||
*/
|
||||
public List<SoftwareModuleTypeRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(key, name));
|
||||
public List<MgmtSoftwareModuleTypeRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link SoftwareModuleTypeRequestBodyPost} to
|
||||
* create multiple software module types at once. An increasing number will
|
||||
* be added to the name and key of the software module type.
|
||||
* Builds a list of multiple {@link MgmtSoftwareModuleTypeRequestBodyPost}
|
||||
* to create multiple software module types at once. An increasing number
|
||||
* will be added to the name and key of the software module type.
|
||||
*
|
||||
* @param count
|
||||
* the amount of software module type bodies which should be
|
||||
* created
|
||||
* @return a list of {@link SoftwareModuleTypeRequestBodyPost}
|
||||
* @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost}
|
||||
*/
|
||||
public List<SoftwareModuleTypeRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<SoftwareModuleTypeRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
public List<MgmtSoftwareModuleTypeRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<MgmtSoftwareModuleTypeRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(key + index, name + index));
|
||||
bodyList.add(doBuild(String.valueOf(index)));
|
||||
}
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private SoftwareModuleTypeRequestBodyPost doBuild(final String prefixKey, final String prefixName) {
|
||||
final SoftwareModuleTypeRequestBodyPost body = new SoftwareModuleTypeRequestBodyPost();
|
||||
body.setKey(prefixKey);
|
||||
body.setName(prefixName);
|
||||
private MgmtSoftwareModuleTypeRequestBodyPost doBuild(final String suffix) {
|
||||
final MgmtSoftwareModuleTypeRequestBodyPost body = new MgmtSoftwareModuleTypeRequestBodyPost();
|
||||
body.setKey(key + suffix);
|
||||
body.setName(name + suffix);
|
||||
body.setDescription(description);
|
||||
body.setMaxAssignments(maxAssignments);
|
||||
return body;
|
||||
@@ -11,12 +11,12 @@ package org.eclipse.hawkbit.mgmt.client.resource.builder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.tag.TagRequestBodyPut;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Builder pattern for building {@link TagRequestBodyPut}.
|
||||
* Builder pattern for building {@link MgmtTagRequestBodyPut}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@@ -58,26 +58,26 @@ public class TagBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of {@link TagRequestBodyPut} which can
|
||||
* directly be used in the RESTful-API.
|
||||
* Builds a list with a single entry of {@link MgmtTagRequestBodyPut} which
|
||||
* can directly be used in the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link TagRequestBodyPut}
|
||||
* @return a single entry list of {@link MgmtTagRequestBodyPut}
|
||||
*/
|
||||
public List<TagRequestBodyPut> build() {
|
||||
public List<MgmtTagRequestBodyPut> build() {
|
||||
return Lists.newArrayList(doBuild(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link TagRequestBodyPut} to create multiple
|
||||
* tags at once. An increasing number will be added to the name of the tag.
|
||||
* The color and description will remain the same.
|
||||
* Builds a list of multiple {@link MgmtTagRequestBodyPut} to create
|
||||
* multiple tags at once. An increasing number will be added to the name of
|
||||
* the tag. The color and description will remain the same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of distribution sets body which should be created
|
||||
* @return a list of {@link TagRequestBodyPut}
|
||||
* @return a list of {@link MgmtTagRequestBodyPut}
|
||||
*/
|
||||
public List<TagRequestBodyPut> buildAsList(final int count) {
|
||||
final ArrayList<TagRequestBodyPut> bodyList = Lists.newArrayList();
|
||||
public List<MgmtTagRequestBodyPut> buildAsList(final int count) {
|
||||
final ArrayList<MgmtTagRequestBodyPut> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(name + index));
|
||||
}
|
||||
@@ -85,8 +85,8 @@ public class TagBuilder {
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private TagRequestBodyPut doBuild(final String prefixName) {
|
||||
final TagRequestBodyPut body = new TagRequestBodyPut();
|
||||
private MgmtTagRequestBodyPut doBuild(final String prefixName) {
|
||||
final MgmtTagRequestBodyPut body = new MgmtTagRequestBodyPut();
|
||||
body.setName(prefixName);
|
||||
body.setDescription(description);
|
||||
body.setColour(color);
|
||||
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* 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.mgmt.client.resource.builder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link MgmtTargetRequestBody}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class TargetBuilder {
|
||||
|
||||
private String controllerId;
|
||||
private String name;
|
||||
private String description;
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* @param controllerId
|
||||
* the ID of the controller/target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder controllerId(final String controllerId) {
|
||||
this.controllerId = controllerId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param address
|
||||
* the address of the target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder address(final String address) {
|
||||
this.address = address;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description of the target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder description(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of {@link MgmtTargetRequestBody} which
|
||||
* can directly be used in the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link MgmtTargetRequestBody}
|
||||
*/
|
||||
public List<MgmtTargetRequestBody> build() {
|
||||
return Lists.newArrayList(doBuild(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link MgmtTargetRequestBody} to create
|
||||
* multiple targets at once. An increasing number will be added to the
|
||||
* controllerId and name of the target. The description will remain.
|
||||
*
|
||||
* @param count
|
||||
* the amount of target bodies which should be created
|
||||
* @param offset
|
||||
* for
|
||||
* @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtTargetRequestBody> buildAsList(final int count) {
|
||||
|
||||
return buildAsList(0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link MgmtTargetRequestBody} to create
|
||||
* multiple targets at once. An increasing number will be added to the
|
||||
* controllerId and name of the target starting from the provided offset.
|
||||
* The description will remain.
|
||||
*
|
||||
* @param count
|
||||
* the amount of target bodies which should be created
|
||||
* @param offset
|
||||
* for for index start
|
||||
* @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost}
|
||||
*/
|
||||
public List<MgmtTargetRequestBody> buildAsList(final int offset, final int count) {
|
||||
final List<MgmtTargetRequestBody> bodyList = Lists.newArrayList();
|
||||
for (int index = offset; index < count + offset; index++) {
|
||||
bodyList.add(doBuild(String.valueOf(index)));
|
||||
}
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private MgmtTargetRequestBody doBuild(final String suffix) {
|
||||
final MgmtTargetRequestBody body = new MgmtTargetRequestBody();
|
||||
body.setControllerId(controllerId + suffix);
|
||||
if (name == null) {
|
||||
name = controllerId;
|
||||
}
|
||||
body.setName(name + suffix);
|
||||
body.setDescription(description);
|
||||
body.setAddress(address);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
4
examples/hawkbit-example-mgmt-simulator/.gitignore
vendored
Normal file
4
examples/hawkbit-example-mgmt-simulator/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/target/
|
||||
/bin/
|
||||
/.apt_generated/
|
||||
/.springBeans
|
||||
@@ -1,6 +1,6 @@
|
||||
# hawkBit Management API example client
|
||||
# Eclipse.IoT hawkBit - Example Management Feign Client
|
||||
|
||||
Example client that shows how to efficiently use the hawkBit management API.
|
||||
Example Spring Boot client that shows how to efficiently use the hawkBit Example Management Feign Client and the hawkBit Management API.
|
||||
|
||||
Powered by [Feign](https://github.com/Netflix/feign).
|
||||
|
||||
@@ -10,13 +10,13 @@ Run getting started example
|
||||
|
||||
|
||||
|
||||
$ java -jar hawkbit-mgmt-api-client-#version#.jar
|
||||
$ java -jar hawkbit-example-mgmt-simulator-#version#.jar
|
||||
|
||||
|
||||
Run create and start rollout example
|
||||
|
||||
|
||||
$ java -jar hawkbit-mgmt-api-client-#version#.jar --createrollout
|
||||
$ java -jar hawkbit-example-mgmt-simulator-#version#.jar --createrollout
|
||||
|
||||
|
||||
## This example shows
|
||||
@@ -28,7 +28,7 @@ In getting started example:
|
||||
* creating software modules
|
||||
* assigning software modules to distribution sets
|
||||
|
||||
In rollout mode:
|
||||
In create rollout example:
|
||||
* creating software modules type
|
||||
* creating distribution set type
|
||||
* creating distribution sets
|
||||
@@ -17,8 +17,8 @@
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<packaging>jar</packaging>
|
||||
<artifactId>hawkbit-mgmt-api-client</artifactId>
|
||||
<name>hawkBit :: Management API example client</name>
|
||||
<artifactId>hawkbit-example-mgmt-simulator</artifactId>
|
||||
<name>hawkBit-example :: Management feign client simulator</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
@@ -57,14 +57,20 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-rest-api</artifactId>
|
||||
<artifactId>hawkbit-example-mgmt-feign-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<!-- need to overwrite for the interface inheritance feature of feign-core -->
|
||||
<version>8.14.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
@@ -82,11 +88,6 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-logging</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.collections</groupId>
|
||||
<artifactId>google-collections</artifactId>
|
||||
<version>1.0-rc2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
@@ -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.mgmt.client;
|
||||
|
||||
import org.eclipse.hawkbit.feign.core.client.FeignClientConfiguration;
|
||||
import org.eclipse.hawkbit.feign.core.client.IgnoreMultipleConsumersProducersSpringMvcContract;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.scenarios.ConfigurableScenario;
|
||||
import org.eclipse.hawkbit.mgmt.client.scenarios.CreateStartedRolloutExample;
|
||||
import org.eclipse.hawkbit.mgmt.client.scenarios.upload.FeignMultipartEncoder;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||
import org.springframework.cloud.netflix.feign.support.ResponseEntityDecoder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.hateoas.hal.Jackson2HalModule;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.auth.BasicAuthRequestInterceptor;
|
||||
import feign.jackson.JacksonDecoder;
|
||||
import feign.slf4j.Slf4jLogger;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableFeignClients("org.eclipse.hawkbit.mgmt.client.resource")
|
||||
@EnableConfigurationProperties(ClientConfigurationProperties.class)
|
||||
@Configuration
|
||||
@AutoConfigureAfter(FeignClientConfiguration.class)
|
||||
@Import(FeignClientConfiguration.class)
|
||||
public class Application implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private ClientConfigurationProperties configuration;
|
||||
|
||||
@Autowired
|
||||
private ConfigurableScenario configuredScenario;
|
||||
|
||||
@Autowired
|
||||
private CreateStartedRolloutExample gettingStartedRolloutScenario;
|
||||
|
||||
public static void main(final String[] args) {
|
||||
new SpringApplicationBuilder().showBanner(false).sources(Application.class).run(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final String... args) throws Exception {
|
||||
if (containsArg("--createrollout", args)) {
|
||||
// run the create and start rollout example
|
||||
gettingStartedRolloutScenario.run();
|
||||
} else {
|
||||
// run the configured scenario from properties
|
||||
configuredScenario.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
|
||||
return new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConfigurableScenario configurableScenario(final MgmtDistributionSetClientResource distributionSetResource,
|
||||
@Qualifier("mgmtSoftwareModuleClientResource") final MgmtSoftwareModuleClientResource softwareModuleResource,
|
||||
@Qualifier("uploadSoftwareModule") final MgmtSoftwareModuleClientResource uploadSoftwareModule,
|
||||
final MgmtTargetClientResource targetResource, final MgmtRolloutClientResource rolloutResource,
|
||||
final ClientConfigurationProperties clientConfigurationProperties) {
|
||||
return new ConfigurableScenario(distributionSetResource, softwareModuleResource, uploadSoftwareModule,
|
||||
targetResource, rolloutResource, clientConfigurationProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CreateStartedRolloutExample createStartedRolloutExample() {
|
||||
return new CreateStartedRolloutExample();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Logger.Level feignLoggerLevel() {
|
||||
return Logger.Level.FULL;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MgmtSoftwareModuleClientResource uploadSoftwareModule() {
|
||||
final ObjectMapper mapper = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.registerModule(new Jackson2HalModule());
|
||||
|
||||
return Feign.builder().contract(new IgnoreMultipleConsumersProducersSpringMvcContract())
|
||||
.requestInterceptor(
|
||||
new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword()))
|
||||
.logger(new Slf4jLogger()).encoder(new FeignMultipartEncoder())
|
||||
.decoder(new ResponseEntityDecoder(new JacksonDecoder(mapper)))
|
||||
.target(MgmtSoftwareModuleClientResource.class,
|
||||
configuration.getUrl() + MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING);
|
||||
}
|
||||
|
||||
private static boolean containsArg(final String containsArg, final String... args) {
|
||||
for (final String arg : args) {
|
||||
if (arg.equalsIgnoreCase(containsArg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/**
|
||||
* 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.mgmt.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configuration bean which holds the configuration of the client e.g. the base
|
||||
* URL of the hawkbit-server and the credentials to use the RESTful Management
|
||||
* API.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "hawkbit")
|
||||
public class ClientConfigurationProperties {
|
||||
|
||||
/**
|
||||
* Update server URI.
|
||||
*/
|
||||
private String url = "localhost:8080";
|
||||
|
||||
/**
|
||||
* Update server user name.
|
||||
*/
|
||||
private String username = "admin";
|
||||
|
||||
/**
|
||||
* Update server password.
|
||||
*/
|
||||
private String password = "admin"; // NOSONAR this password is only used for
|
||||
// examples
|
||||
|
||||
private final List<Scenario> scenarios = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Simulation {@link Scenario}.
|
||||
*
|
||||
*/
|
||||
public static class Scenario {
|
||||
private boolean cleanRepository;
|
||||
private int targets = 100;
|
||||
private int distributionSets = 10;
|
||||
private int appModulesPerDistributionSet = 2;
|
||||
private String dsName = "Package";
|
||||
private String smSwName = "Application";
|
||||
private String smFwName = "Firmware";
|
||||
private String targetName = "Device";
|
||||
private int artifactsPerSM = 1;
|
||||
private String targetAddress = "amqp:/simulator.replyTo";
|
||||
private boolean runRollouts = true;
|
||||
private int rolloutDeploymentGroups = 4;
|
||||
|
||||
/**
|
||||
* Artifact size. Values can use the suffixed "MB" or "KB" to indicate a
|
||||
* Megabyte or Kilobyte size.
|
||||
*/
|
||||
private String artifactSize = "1MB";
|
||||
|
||||
public boolean isCleanRepository() {
|
||||
return cleanRepository;
|
||||
}
|
||||
|
||||
public void setCleanRepository(final boolean cleanRepository) {
|
||||
this.cleanRepository = cleanRepository;
|
||||
}
|
||||
|
||||
public int getRolloutDeploymentGroups() {
|
||||
return rolloutDeploymentGroups;
|
||||
}
|
||||
|
||||
public void setRolloutDeploymentGroups(final int rolloutDeploymentGroups) {
|
||||
this.rolloutDeploymentGroups = rolloutDeploymentGroups;
|
||||
}
|
||||
|
||||
public boolean isRunRollouts() {
|
||||
return runRollouts;
|
||||
}
|
||||
|
||||
public void setRunRollouts(final boolean runRollouts) {
|
||||
this.runRollouts = runRollouts;
|
||||
}
|
||||
|
||||
public String getTargetAddress() {
|
||||
return targetAddress;
|
||||
}
|
||||
|
||||
public void setTargetAddress(final String targetAddress) {
|
||||
this.targetAddress = targetAddress;
|
||||
}
|
||||
|
||||
public int getArtifactsPerSM() {
|
||||
return artifactsPerSM;
|
||||
}
|
||||
|
||||
public void setArtifactsPerSM(final int artifactsPerSM) {
|
||||
this.artifactsPerSM = artifactsPerSM;
|
||||
}
|
||||
|
||||
public String getArtifactSize() {
|
||||
return artifactSize;
|
||||
}
|
||||
|
||||
public void setArtifactSize(final String artifactSize) {
|
||||
this.artifactSize = artifactSize;
|
||||
}
|
||||
|
||||
public String getTargetName() {
|
||||
return targetName;
|
||||
}
|
||||
|
||||
public void setTargetName(final String targetName) {
|
||||
this.targetName = targetName;
|
||||
}
|
||||
|
||||
public String getDsName() {
|
||||
return dsName;
|
||||
}
|
||||
|
||||
public void setDsName(final String dsName) {
|
||||
this.dsName = dsName;
|
||||
}
|
||||
|
||||
public String getSmSwName() {
|
||||
return smSwName;
|
||||
}
|
||||
|
||||
public void setSmSwName(final String smSwName) {
|
||||
this.smSwName = smSwName;
|
||||
}
|
||||
|
||||
public String getSmFwName() {
|
||||
return smFwName;
|
||||
}
|
||||
|
||||
public void setSmFwName(final String smFwName) {
|
||||
this.smFwName = smFwName;
|
||||
}
|
||||
|
||||
public int getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
public int getDistributionSets() {
|
||||
return distributionSets;
|
||||
}
|
||||
|
||||
public int getAppModulesPerDistributionSet() {
|
||||
return appModulesPerDistributionSet;
|
||||
}
|
||||
|
||||
public void setTargets(final int targets) {
|
||||
this.targets = targets;
|
||||
}
|
||||
|
||||
public void setDistributionSets(final int distributionSets) {
|
||||
this.distributionSets = distributionSets;
|
||||
}
|
||||
|
||||
public void setAppModulesPerDistributionSet(final int appModulesPerDistributionSet) {
|
||||
this.appModulesPerDistributionSet = appModulesPerDistributionSet;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<Scenario> getScenarios() {
|
||||
return scenarios;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(final String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* 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.mgmt.client.scenarios;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties;
|
||||
import org.eclipse.hawkbit.mgmt.client.ClientConfigurationProperties.Scenario;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.RolloutBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.scenarios.upload.ArtifactFile;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
/**
|
||||
*
|
||||
* A configurable scenario which runs the configured scenarios.
|
||||
*
|
||||
* @see {@link ClientConfigurationProperties#getScenarios()}
|
||||
*
|
||||
*/
|
||||
public class ConfigurableScenario {
|
||||
|
||||
private static final int PAGE_SIZE = 100;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurableScenario.class);
|
||||
|
||||
private final MgmtDistributionSetClientResource distributionSetResource;
|
||||
|
||||
private final MgmtSoftwareModuleClientResource softwareModuleResource;
|
||||
|
||||
private final MgmtSoftwareModuleClientResource uploadSoftwareModule;
|
||||
|
||||
private final MgmtTargetClientResource targetResource;
|
||||
|
||||
private final MgmtRolloutClientResource rolloutResource;
|
||||
|
||||
private final ClientConfigurationProperties clientConfigurationProperties;
|
||||
|
||||
public ConfigurableScenario(final MgmtDistributionSetClientResource distributionSetResource,
|
||||
@Qualifier("mgmtSoftwareModuleClientResource") final MgmtSoftwareModuleClientResource softwareModuleResource,
|
||||
@Qualifier("uploadSoftwareModule") final MgmtSoftwareModuleClientResource uploadSoftwareModule,
|
||||
final MgmtTargetClientResource targetResource, final MgmtRolloutClientResource rolloutResource,
|
||||
final ClientConfigurationProperties clientConfigurationProperties) {
|
||||
this.distributionSetResource = distributionSetResource;
|
||||
this.softwareModuleResource = softwareModuleResource;
|
||||
this.uploadSoftwareModule = uploadSoftwareModule;
|
||||
this.targetResource = targetResource;
|
||||
this.rolloutResource = rolloutResource;
|
||||
this.clientConfigurationProperties = clientConfigurationProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the default getting started scenario.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
LOGGER.info("Running Configurable Scenario...");
|
||||
|
||||
clientConfigurationProperties.getScenarios().forEach(this::createScenario);
|
||||
}
|
||||
|
||||
private void createScenario(final Scenario scenario) {
|
||||
if (scenario.isCleanRepository()) {
|
||||
cleanRepository();
|
||||
}
|
||||
|
||||
createTargets(scenario);
|
||||
createDistributionSets(scenario);
|
||||
|
||||
if (scenario.isRunRollouts()) {
|
||||
runRollouts(scenario);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanRepository() {
|
||||
LOGGER.info("Cleaning repository");
|
||||
deleteTargets();
|
||||
deleteRollouts();
|
||||
deleteDistributionSets();
|
||||
deleteSoftwareModules();
|
||||
LOGGER.info("Cleaning repository -> Done");
|
||||
}
|
||||
|
||||
private void deleteRollouts() {
|
||||
// TODO: complete this as soon as rollouts can be deleted
|
||||
|
||||
}
|
||||
|
||||
private void deleteSoftwareModules() {
|
||||
PagedList<MgmtSoftwareModule> modules;
|
||||
do {
|
||||
modules = softwareModuleResource.getSoftwareModules(0, PAGE_SIZE, null, null).getBody();
|
||||
modules.getContent().forEach(module -> softwareModuleResource.deleteSoftwareModule(module.getModuleId()));
|
||||
} while (modules.getTotal() > PAGE_SIZE);
|
||||
}
|
||||
|
||||
private void deleteDistributionSets() {
|
||||
PagedList<MgmtDistributionSet> distributionSets;
|
||||
do {
|
||||
distributionSets = distributionSetResource.getDistributionSets(0, PAGE_SIZE, null, null).getBody();
|
||||
distributionSets.getContent().forEach(set -> distributionSetResource.deleteDistributionSet(set.getDsId()));
|
||||
} while (distributionSets.getTotal() > PAGE_SIZE);
|
||||
}
|
||||
|
||||
private void deleteTargets() {
|
||||
PagedList<MgmtTarget> targets;
|
||||
do {
|
||||
targets = targetResource.getTargets(0, PAGE_SIZE, null, null).getBody();
|
||||
targets.getContent().forEach(target -> targetResource.deleteTarget(target.getControllerId()));
|
||||
} while (targets.getTotal() > PAGE_SIZE);
|
||||
}
|
||||
|
||||
private void runRollouts(final Scenario scenario) {
|
||||
distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody()
|
||||
.getContent().forEach(set -> runRollout(set, scenario));
|
||||
|
||||
}
|
||||
|
||||
private void runRollout(final MgmtDistributionSet set, final Scenario scenario) {
|
||||
LOGGER.info("Run rollout for set {}", set.getDsId());
|
||||
// create a Rollout
|
||||
final MgmtRolloutResponseBody rolloutResponseBody = rolloutResource
|
||||
.create(new RolloutBuilder().name("Rollout" + set.getName() + set.getVersion())
|
||||
.groupSize(scenario.getRolloutDeploymentGroups()).targetFilterQuery("name==*")
|
||||
.distributionSetId(set.getDsId()).successThreshold("80").errorThreshold("5").build())
|
||||
.getBody();
|
||||
|
||||
// start the created Rollout
|
||||
rolloutResource.start(rolloutResponseBody.getRolloutId(), true);
|
||||
|
||||
// wait until rollout is complete
|
||||
do {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(35);
|
||||
} catch (final InterruptedException e) {
|
||||
LOGGER.warn("Interrupted!");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
} while (targetResource.getTargets(0, 1, null, "updateStatus==IN_SYNC").getBody().getTotal() < scenario
|
||||
.getTargets());
|
||||
LOGGER.info("Run rollout for set {} -> Done", set.getDsId());
|
||||
}
|
||||
|
||||
private void createDistributionSets(final Scenario scenario) {
|
||||
LOGGER.info("Creating {} distribution sets", scenario.getDistributionSets());
|
||||
final byte[] artifact = generateArtifact(scenario);
|
||||
|
||||
distributionSetResource.createDistributionSets(new DistributionSetBuilder().name(scenario.getDsName())
|
||||
.type("os_app").version("1.0.").buildAsList(scenario.getDistributionSets())).getBody()
|
||||
.forEach(dsSet -> {
|
||||
final List<MgmtSoftwareModule> modules = addModules(scenario, dsSet, artifact);
|
||||
|
||||
final SoftwareModuleAssigmentBuilder assign = new SoftwareModuleAssigmentBuilder();
|
||||
modules.forEach(module -> assign.id(module.getModuleId()));
|
||||
distributionSetResource.assignSoftwareModules(dsSet.getDsId(), assign.build());
|
||||
});
|
||||
|
||||
LOGGER.info("Creating {} distribution sets -> Done", scenario.getDistributionSets());
|
||||
}
|
||||
|
||||
private List<MgmtSoftwareModule> addModules(final Scenario scenario, final MgmtDistributionSet dsSet,
|
||||
final byte[] artifact) {
|
||||
final List<MgmtSoftwareModule> modules = softwareModuleResource
|
||||
.createSoftwareModules(new SoftwareModuleBuilder().name(scenario.getSmFwName() + "-os")
|
||||
.version(dsSet.getVersion()).type("os").build())
|
||||
.getBody();
|
||||
modules.addAll(softwareModuleResource.createSoftwareModules(
|
||||
new SoftwareModuleBuilder().name(scenario.getSmSwName() + "-app").version(dsSet.getVersion() + ".")
|
||||
.type("application").buildAsList(scenario.getAppModulesPerDistributionSet()))
|
||||
.getBody());
|
||||
|
||||
for (int x = 0; x < scenario.getArtifactsPerSM(); x++) {
|
||||
modules.forEach(module -> {
|
||||
final ArtifactFile file = new ArtifactFile("dummyfile.dummy", null, "multipart/form-data", artifact);
|
||||
uploadSoftwareModule.uploadArtifact(module.getModuleId(), file, null, null, null);
|
||||
});
|
||||
}
|
||||
|
||||
return modules;
|
||||
}
|
||||
|
||||
private static byte[] generateArtifact(final Scenario scenario) {
|
||||
|
||||
// Exception squid:S2245 - not used for cryptographic function
|
||||
@SuppressWarnings("squid:S2245")
|
||||
final Random random = new Random();
|
||||
|
||||
// create byte array
|
||||
final byte[] nbyte = new byte[parseSize(scenario.getArtifactSize())];
|
||||
|
||||
// put the next byte in the array
|
||||
random.nextBytes(nbyte);
|
||||
|
||||
return nbyte;
|
||||
}
|
||||
|
||||
private void createTargets(final Scenario scenario) {
|
||||
LOGGER.info("Creating {} targets", scenario.getTargets());
|
||||
|
||||
for (int i = 0; i < (scenario.getTargets() / PAGE_SIZE); i++) {
|
||||
targetResource.createTargets(
|
||||
new TargetBuilder().controllerId(scenario.getTargetName()).address(scenario.getTargetAddress())
|
||||
.buildAsList(i * PAGE_SIZE, (i + 1) * PAGE_SIZE > scenario.getTargets()
|
||||
? (scenario.getTargets() - (i * PAGE_SIZE)) : PAGE_SIZE));
|
||||
}
|
||||
|
||||
LOGGER.info("Creating {} targets -> Done", scenario.getTargets());
|
||||
}
|
||||
|
||||
private static int parseSize(final String s) {
|
||||
final String size = s.toUpperCase();
|
||||
if (size.endsWith("KB")) {
|
||||
return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024;
|
||||
}
|
||||
if (size.endsWith("MB")) {
|
||||
return Integer.valueOf(size.substring(0, size.length() - 2)) * 1024 * 1024;
|
||||
}
|
||||
return Integer.valueOf(size);
|
||||
}
|
||||
}
|
||||
@@ -10,12 +10,12 @@ package org.eclipse.hawkbit.mgmt.client.scenarios;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetTypeResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.RolloutResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleTypeResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.TargetResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetTypeClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtRolloutClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleTypeClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.MgmtTargetClientResource;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetTypeBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.RolloutBuilder;
|
||||
@@ -23,43 +23,43 @@ import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentB
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleTypeBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.TargetBuilder;
|
||||
import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
|
||||
import org.eclipse.hawkbit.rest.resource.model.rollout.RolloutResponseBody;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRest;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRest;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
/**
|
||||
* Example for creating and starting a Rollout.
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class CreateStartedRolloutExample {
|
||||
|
||||
/* known software module type name and key */
|
||||
private static final String SM_MODULE_TYPE = "firmware";
|
||||
private static final String SM_MODULE_TYPE = "gettingstarted-rollout-example";
|
||||
|
||||
/* known distribution set type name and key */
|
||||
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetResourceClient distributionSetResource;
|
||||
private MgmtDistributionSetClientResource distributionSetResource;
|
||||
|
||||
@Autowired
|
||||
private SoftwareModuleResourceClient softwareModuleResource;
|
||||
@Qualifier("mgmtSoftwareModuleClientResource")
|
||||
private MgmtSoftwareModuleClientResource softwareModuleResource;
|
||||
|
||||
@Autowired
|
||||
private TargetResourceClient targetResource;
|
||||
private MgmtTargetClientResource targetResource;
|
||||
|
||||
@Autowired
|
||||
private RolloutResourceClient rolloutResource;
|
||||
private MgmtRolloutClientResource rolloutResource;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetTypeResourceClient distributionSetTypeResource;
|
||||
private MgmtDistributionSetTypeClientResource distributionSetTypeResource;
|
||||
|
||||
@Autowired
|
||||
private SoftwareModuleTypeResourceClient softwareModuleTypeResource;
|
||||
private MgmtSoftwareModuleTypeClientResource softwareModuleTypeResource;
|
||||
|
||||
/**
|
||||
* Run the Rollout scenario.
|
||||
@@ -67,7 +67,7 @@ public class CreateStartedRolloutExample {
|
||||
public void run() {
|
||||
|
||||
// create three SoftwareModuleTypes
|
||||
final List<SoftwareModuleTypeRest> createdSoftwareModuleTypes = softwareModuleTypeResource
|
||||
final List<MgmtSoftwareModuleType> createdSoftwareModuleTypes = softwareModuleTypeResource
|
||||
.createSoftwareModuleTypes(new SoftwareModuleTypeBuilder().key(SM_MODULE_TYPE).name(SM_MODULE_TYPE)
|
||||
.maxAssignments(1).build())
|
||||
.getBody();
|
||||
@@ -78,12 +78,12 @@ public class CreateStartedRolloutExample {
|
||||
.getBody();
|
||||
|
||||
// create one DistributionSet
|
||||
final List<DistributionSetRest> distributionSetsRest = distributionSetResource.createDistributionSets(
|
||||
final List<MgmtDistributionSet> distributionSetsRest = distributionSetResource.createDistributionSets(
|
||||
new DistributionSetBuilder().name("rollout-example").version("1.0.0").type(DS_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
|
||||
// create three SoftwareModules
|
||||
final List<SoftwareModuleRest> softwareModulesRest = softwareModuleResource
|
||||
final List<MgmtSoftwareModule> softwareModulesRest = softwareModuleResource
|
||||
.createSoftwareModules(
|
||||
new SoftwareModuleBuilder().name("firmware").version("1.0.0").type(SM_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
@@ -97,7 +97,7 @@ public class CreateStartedRolloutExample {
|
||||
.description("Targets used for rollout example").buildAsList(10));
|
||||
|
||||
// create a Rollout
|
||||
final RolloutResponseBody rolloutResponseBody = rolloutResource
|
||||
final MgmtRolloutResponseBody rolloutResponseBody = rolloutResource
|
||||
.create(new RolloutBuilder().name("MyRollout").groupSize(2).targetFilterQuery("name==00-FF-AA-0*")
|
||||
.distributionSetId(distributionSetsRest.get(0).getDsId()).successThreshold("80")
|
||||
.errorThreshold("50").build())
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* 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.mgmt.client.scenarios.upload;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
* Implementation for {@link MultipartFile} for hawkBit artifact upload.
|
||||
*
|
||||
*/
|
||||
public class ArtifactFile implements MultipartFile {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String originalFilename;
|
||||
|
||||
private final String contentType;
|
||||
|
||||
private final byte[] content;
|
||||
|
||||
/**
|
||||
* Create a new ArtifactFile with the given content.
|
||||
*
|
||||
* @param name
|
||||
* the name of the file
|
||||
* @param content
|
||||
* the content of the file
|
||||
*/
|
||||
public ArtifactFile(final String name, final byte[] content) {
|
||||
this(name, "", null, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new ArtifactFile with the given content.
|
||||
*
|
||||
* @param name
|
||||
* of the file
|
||||
* @param originalFilename
|
||||
* the original filename (as on the client's machine)
|
||||
* @param contentType
|
||||
* the content type
|
||||
* @param content
|
||||
* of the file
|
||||
*/
|
||||
public ArtifactFile(final String name, final String originalFilename, final String contentType,
|
||||
final byte[] content) {
|
||||
Assert.hasLength(name, "Name must not be null");
|
||||
this.name = name;
|
||||
this.originalFilename = Optional.ofNullable(originalFilename).orElse("");
|
||||
this.contentType = contentType;
|
||||
this.content = Optional.ofNullable(content).orElse(new byte[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalFilename() {
|
||||
return this.originalFilename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContentType() {
|
||||
return this.contentType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.content.length == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return this.content.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getBytes() throws IOException {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return new ByteArrayInputStream(this.content);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transferTo(final File dest) throws IOException {
|
||||
FileCopyUtils.copy(this.content, dest);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* 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.mgmt.client.scenarios.upload;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import feign.RequestTemplate;
|
||||
import feign.codec.EncodeException;
|
||||
import feign.codec.Encoder;
|
||||
|
||||
/**
|
||||
* A feign encoder implementation which handles {@link MultipartFile} body.
|
||||
*/
|
||||
public class FeignMultipartEncoder implements Encoder {
|
||||
|
||||
private final List<HttpMessageConverter<?>> converters = new RestTemplate().getMessageConverters();
|
||||
private final HttpHeaders multipartHeaders = new HttpHeaders();
|
||||
private final HttpHeaders jsonHeaders = new HttpHeaders();
|
||||
|
||||
private static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
public FeignMultipartEncoder() {
|
||||
multipartHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
jsonHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void encode(final Object object, final Type bodyType, final RequestTemplate template) {
|
||||
encodeMultipartFormRequest(object, template);
|
||||
}
|
||||
|
||||
private void encodeMultipartFormRequest(final Object value, final RequestTemplate template) {
|
||||
if (value == null) {
|
||||
throw new EncodeException("Cannot encode request with null value.");
|
||||
}
|
||||
if (!isMultipartFile(value)) {
|
||||
throw new EncodeException("Only multipart can be handled by this encoder");
|
||||
}
|
||||
encodeRequest(encodeMultipartFile((MultipartFile) value), multipartHeaders, template);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void encodeRequest(final Object value, final HttpHeaders requestHeaders, final RequestTemplate template) {
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
final HttpOutputMessage dummyRequest = new HttpOutputMessageImpl(outputStream, requestHeaders);
|
||||
try {
|
||||
final Class<?> requestType = value.getClass();
|
||||
final MediaType requestContentType = requestHeaders.getContentType();
|
||||
for (final HttpMessageConverter<?> messageConverter : converters) {
|
||||
if (messageConverter.canWrite(requestType, requestContentType)) {
|
||||
((HttpMessageConverter<Object>) messageConverter).write(value, requestContentType, dummyRequest);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (final IOException ex) {
|
||||
throw new EncodeException("Cannot encode request.", ex);
|
||||
}
|
||||
final HttpHeaders headers = dummyRequest.getHeaders();
|
||||
if (headers != null) {
|
||||
for (final Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
template.header(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
/*
|
||||
* we should use a template output stream... this will cause issues if
|
||||
* files are too big, since the whole request will be in memory.
|
||||
*/
|
||||
template.body(outputStream.toByteArray(), UTF_8);
|
||||
}
|
||||
|
||||
private MultiValueMap<String, Object> encodeMultipartFile(final MultipartFile file) {
|
||||
try {
|
||||
final MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
|
||||
multiValueMap.add("file", new MultipartFileResource(file.getName(), file.getSize(), file.getInputStream()));
|
||||
return multiValueMap;
|
||||
} catch (final IOException ex) {
|
||||
throw new EncodeException("Cannot encode request.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isMultipartFile(final Object object) {
|
||||
return object instanceof MultipartFile;
|
||||
}
|
||||
|
||||
private static final class HttpOutputMessageImpl implements HttpOutputMessage {
|
||||
|
||||
private final OutputStream body;
|
||||
private final HttpHeaders headers;
|
||||
|
||||
private HttpOutputMessageImpl(final OutputStream body, final HttpHeaders headers) {
|
||||
this.body = body;
|
||||
this.headers = headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getBody() throws IOException {
|
||||
return body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return headers;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy resource class. Wraps file content and its original name.
|
||||
*/
|
||||
static class MultipartFileResource extends InputStreamResource {
|
||||
|
||||
private final String filename;
|
||||
private final long size;
|
||||
|
||||
public MultipartFileResource(final String filename, final long size, final InputStream inputStream) {
|
||||
super(inputStream);
|
||||
this.size = size;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return this.filename;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long contentLength() throws IOException {
|
||||
return size;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# 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
|
||||
#
|
||||
|
||||
hawkbit.url=http://localhost:8080
|
||||
hawkbit.username=admin
|
||||
hawkbit.password=admin
|
||||
|
||||
spring.main.show-banner=false
|
||||
|
||||
hawkbit.scenarios.[0].cleanRepository=false
|
||||
hawkbit.scenarios.[0].targets=0
|
||||
hawkbit.scenarios.[0].ds-name=gettingstarted-example
|
||||
hawkbit.scenarios.[0].distribution-sets=3
|
||||
hawkbit.scenarios.[0].sm-fw-name=gettingstarted-example
|
||||
hawkbit.scenarios.[0].sm-sw-name=gettingstarted-example
|
||||
hawkbit.scenarios.[0].runRollouts=false
|
||||
@@ -10,17 +10,11 @@
|
||||
|
||||
-->
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!-- Log message format -->
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||
|
||||
<logger name="org.eclipse.hawkbit" level="info" />
|
||||
<logger name="feign.Logger" level="debug" />
|
||||
|
||||
<root level="error">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
@@ -1,77 +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.mgmt.client;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.client.scenarios.CreateStartedRolloutExample;
|
||||
import org.eclipse.hawkbit.mgmt.client.scenarios.GettingStartedDefaultScenario;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import feign.Contract;
|
||||
import feign.auth.BasicAuthRequestInterceptor;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableFeignClients
|
||||
@EnableConfigurationProperties(ClientConfigurationProperties.class)
|
||||
public class Application implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private ClientConfigurationProperties configuration;
|
||||
|
||||
@Autowired
|
||||
private GettingStartedDefaultScenario gettingStarted;
|
||||
|
||||
@Autowired
|
||||
private CreateStartedRolloutExample gettingStartedRolloutScenario;
|
||||
|
||||
public static void main(final String[] args) {
|
||||
new SpringApplicationBuilder().showBanner(false).sources(Application.class).run(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final String... args) throws Exception {
|
||||
if (containsArg("--createrollout", args)) {
|
||||
// run the create and start rollout example
|
||||
gettingStartedRolloutScenario.run();
|
||||
} else {
|
||||
// run the getting started scenario which creates a setup of
|
||||
// distribution set and software modules to be used
|
||||
gettingStarted.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
|
||||
return new BasicAuthRequestInterceptor(configuration.getUsername(), configuration.getPassword());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ApplicationJsonRequestHeaderInterceptor jsonHeaderInterceptor() {
|
||||
return new ApplicationJsonRequestHeaderInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Contract feignContract() {
|
||||
return new IgnoreMultipleConsumersProducersSpringMvcContract();
|
||||
}
|
||||
|
||||
private boolean containsArg(final String containsArg, final String... args) {
|
||||
for (final String arg : args) {
|
||||
if (arg.equalsIgnoreCase(containsArg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -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.mgmt.client;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Configuration bean which holds the configuration of the client e.g. the base
|
||||
* URL of the hawkbit-server and the credentials to use the RESTful Management
|
||||
* API.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "hawkbit")
|
||||
public class ClientConfigurationProperties {
|
||||
|
||||
/**
|
||||
* Update server URI.
|
||||
*/
|
||||
private String url = "localhost:8080";
|
||||
|
||||
/**
|
||||
* Update server user name.
|
||||
*/
|
||||
private String username = "admin";
|
||||
|
||||
/**
|
||||
* Update server password.
|
||||
*/
|
||||
private String password = "admin"; // NOSONAR this password is only used for
|
||||
// examples
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(final String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(final String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -1,96 +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.mgmt.client.resource.builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRequestBodyPost;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* Builder pattern for building {@link DistributionSetRequestBodyPost}.
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class DistributionSetBuilder {
|
||||
private String name;
|
||||
private String version;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the distribution set
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version
|
||||
* the version of the distribution set
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder version(final String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the distribution set type name for this distribution set
|
||||
* @return the builder itself
|
||||
*/
|
||||
public DistributionSetBuilder type(final String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of
|
||||
* {@link DistributionSetRequestBodyPost} which can directly be used to post
|
||||
* on the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link DistributionSetRequestBodyPost}
|
||||
*/
|
||||
public List<DistributionSetRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link DistributionSetRequestBodyPost} to
|
||||
* create multiple distribution sets at once. An increasing number will be
|
||||
* added to the name of the distribution set. The version and type will
|
||||
* remain the same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of distribution sets body which should be created
|
||||
* @return a list of {@link DistributionSetRequestBodyPost}
|
||||
*/
|
||||
public List<DistributionSetRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<DistributionSetRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(name + index));
|
||||
}
|
||||
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private DistributionSetRequestBodyPost doBuild(final String prefixName) {
|
||||
final DistributionSetRequestBodyPost body = new DistributionSetRequestBodyPost();
|
||||
body.setName(prefixName);
|
||||
body.setVersion(version);
|
||||
body.setType(type);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +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.mgmt.client.resource.builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.distributionsettype.DistributionSetTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPost;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link SoftwareModuleRequestBodyPost}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class SoftwareModuleBuilder {
|
||||
|
||||
private String name;
|
||||
private String version;
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the software module
|
||||
* @return the builder itself
|
||||
*/
|
||||
public SoftwareModuleBuilder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version
|
||||
* the version of the software module
|
||||
* @return the builder itsefl
|
||||
*/
|
||||
public SoftwareModuleBuilder version(final String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the key of the software module type to be used for this
|
||||
* software module
|
||||
* @return the builder itself
|
||||
*/
|
||||
public SoftwareModuleBuilder type(final String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of
|
||||
* {@link SoftwareModuleRequestBodyPost} which can directly be used in the
|
||||
* RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link SoftwareModuleRequestBodyPost}
|
||||
*/
|
||||
public List<SoftwareModuleRequestBodyPost> build() {
|
||||
return Lists.newArrayList(doBuild(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link SoftwareModuleRequestBodyPost} to create
|
||||
* multiple software module at once. An increasing number will be added to
|
||||
* the name of the software module. The version and type will remain the
|
||||
* same.
|
||||
*
|
||||
* @param count
|
||||
* the amount of software module body which should be created
|
||||
* @return a list of {@link DistributionSetTypeRequestBodyPost}
|
||||
*/
|
||||
public List<SoftwareModuleRequestBodyPost> buildAsList(final int count) {
|
||||
final ArrayList<SoftwareModuleRequestBodyPost> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(name + index));
|
||||
}
|
||||
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private SoftwareModuleRequestBodyPost doBuild(final String prefixName) {
|
||||
final SoftwareModuleRequestBodyPost body = new SoftwareModuleRequestBodyPost();
|
||||
body.setName(prefixName);
|
||||
body.setVersion(version);
|
||||
body.setType(type);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +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.mgmt.client.resource.builder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
*
|
||||
* Builder pattern for building {@link TargetRequestBody}.
|
||||
*
|
||||
*/
|
||||
// Exception squid:S1701 - builder pattern
|
||||
@SuppressWarnings({ "squid:S1701" })
|
||||
public class TargetBuilder {
|
||||
|
||||
private String controllerId;
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @param controllerId
|
||||
* the ID of the controller/target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder controllerId(final String controllerId) {
|
||||
this.controllerId = controllerId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder name(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description of the target
|
||||
* @return the builder itself
|
||||
*/
|
||||
public TargetBuilder description(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list with a single entry of {@link TargetRequestBody} which can
|
||||
* directly be used in the RESTful-API.
|
||||
*
|
||||
* @return a single entry list of {@link TargetRequestBody}
|
||||
*/
|
||||
public List<TargetRequestBody> build() {
|
||||
return Lists.newArrayList(doBuild(controllerId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a list of multiple {@link TargetRequestBody} to create multiple
|
||||
* targets at once. An increasing number will be added to the controllerId
|
||||
* of the target. The name and description will remain.
|
||||
*
|
||||
* @param count
|
||||
* the amount of software module type bodies which should be
|
||||
* created
|
||||
* @return a list of {@link SoftwareModuleTypeRequestBodyPost}
|
||||
*/
|
||||
public List<TargetRequestBody> buildAsList(final int count) {
|
||||
final ArrayList<TargetRequestBody> bodyList = Lists.newArrayList();
|
||||
for (int index = 0; index < count; index++) {
|
||||
bodyList.add(doBuild(controllerId + index));
|
||||
}
|
||||
return bodyList;
|
||||
}
|
||||
|
||||
private TargetRequestBody doBuild(final String prefixControllerId) {
|
||||
final TargetRequestBody body = new TargetRequestBody();
|
||||
body.setControllerId(prefixControllerId);
|
||||
body.setName(name);
|
||||
body.setDescription(description);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,137 +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.mgmt.client.scenarios;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.DistributionSetTypeResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.SoftwareModuleTypeResourceClient;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.DistributionSetTypeBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleAssigmentBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleBuilder;
|
||||
import org.eclipse.hawkbit.mgmt.client.resource.builder.SoftwareModuleTypeBuilder;
|
||||
import org.eclipse.hawkbit.rest.resource.model.distributionset.DistributionSetRest;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRest;
|
||||
import org.eclipse.hawkbit.rest.resource.model.softwaremoduletype.SoftwareModuleTypeRest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* Default getting started scenario.
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class GettingStartedDefaultScenario {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(GettingStartedDefaultScenario.class);
|
||||
|
||||
/* known software module type name and key */
|
||||
private static final String SM_MODULE_TYPE = "gettingstarted";
|
||||
|
||||
/* known distribution set type name and key */
|
||||
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
|
||||
|
||||
/* known distribution name of this getting started example */
|
||||
private static final String SM_EXAMPLE_NAME = "gettingstarted-example";
|
||||
|
||||
/* known distribution name of this getting started example */
|
||||
private static final String DS_EXAMPLE_NAME = SM_EXAMPLE_NAME;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetResourceClient distributionSetResource;
|
||||
|
||||
@Autowired
|
||||
private DistributionSetTypeResourceClient distributionSetTypeResource;
|
||||
|
||||
@Autowired
|
||||
private SoftwareModuleResourceClient softwareModuleResource;
|
||||
|
||||
@Autowired
|
||||
private SoftwareModuleTypeResourceClient softwareModuleTypeResource;
|
||||
|
||||
/**
|
||||
* Run the default getting started scenario.
|
||||
*/
|
||||
public void run() {
|
||||
|
||||
LOGGER.info("Running Getting-Started-Scenario...");
|
||||
|
||||
// create one SoftwareModuleTypes
|
||||
LOGGER.info("Creating software module type {}", SM_MODULE_TYPE);
|
||||
final List<SoftwareModuleTypeRest> createdSoftwareModuleTypes = softwareModuleTypeResource
|
||||
.createSoftwareModuleTypes(new SoftwareModuleTypeBuilder().key(SM_MODULE_TYPE).name(SM_MODULE_TYPE)
|
||||
.maxAssignments(1).build())
|
||||
.getBody();
|
||||
|
||||
// create one DistributionSetType
|
||||
LOGGER.info("Creating distribution set type {}", DS_MODULE_TYPE);
|
||||
distributionSetTypeResource.createDistributionSetTypes(new DistributionSetTypeBuilder().key(DS_MODULE_TYPE)
|
||||
.name(DS_MODULE_TYPE).mandatorymodules(createdSoftwareModuleTypes.get(0).getModuleId()).build());
|
||||
|
||||
// create three DistributionSet
|
||||
final String dsVersion1 = "1.0.0";
|
||||
final String dsVersion2 = "2.0.0";
|
||||
final String dsVersion3 = "2.1.0";
|
||||
|
||||
LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion1);
|
||||
final List<DistributionSetRest> distributionSetsRest1 = distributionSetResource.createDistributionSets(
|
||||
new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion1).type(DS_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
|
||||
LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion2);
|
||||
final List<DistributionSetRest> distributionSetsRest2 = distributionSetResource.createDistributionSets(
|
||||
new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion2).type(DS_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
|
||||
LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion3);
|
||||
final List<DistributionSetRest> distributionSetsRest3 = distributionSetResource.createDistributionSets(
|
||||
new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion3).type(DS_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
|
||||
// create three SoftwareModules
|
||||
final String swVersion1 = "1";
|
||||
final String swVersion2 = "2";
|
||||
final String swVersion3 = "3";
|
||||
|
||||
LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1);
|
||||
final List<SoftwareModuleRest> softwareModulesRest1 = softwareModuleResource.createSoftwareModules(
|
||||
new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion1).type(SM_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion2);
|
||||
final List<SoftwareModuleRest> softwareModulesRest2 = softwareModuleResource.createSoftwareModules(
|
||||
new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion2).type(SM_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion3);
|
||||
final List<SoftwareModuleRest> softwareModulesRest3 = softwareModuleResource.createSoftwareModules(
|
||||
new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion3).type(SM_MODULE_TYPE).build())
|
||||
.getBody();
|
||||
|
||||
// Assign SoftwareModules to DistributionSet
|
||||
LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1,
|
||||
DS_EXAMPLE_NAME, dsVersion1);
|
||||
distributionSetResource.assignSoftwareModules(distributionSetsRest1.get(0).getDsId(),
|
||||
new SoftwareModuleAssigmentBuilder().id(softwareModulesRest1.get(0).getModuleId()).build());
|
||||
|
||||
LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion2,
|
||||
DS_EXAMPLE_NAME, dsVersion2);
|
||||
distributionSetResource.assignSoftwareModules(distributionSetsRest2.get(0).getDsId(),
|
||||
new SoftwareModuleAssigmentBuilder().id(softwareModulesRest2.get(0).getModuleId()).build());
|
||||
|
||||
LOGGER.info("Assign software module {}:{} to distribution set {}:{}", SM_EXAMPLE_NAME, swVersion3,
|
||||
DS_EXAMPLE_NAME, dsVersion3);
|
||||
distributionSetResource.assignSoftwareModules(distributionSetsRest3.get(0).getDsId(),
|
||||
new SoftwareModuleAssigmentBuilder().id(softwareModulesRest3.get(0).getModuleId()).build());
|
||||
}
|
||||
}
|
||||
@@ -1,14 +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
|
||||
#
|
||||
|
||||
hawkbit.url=localhost:8080
|
||||
hawkbit.username=admin
|
||||
hawkbit.password=admin
|
||||
|
||||
spring.main.show-banner=false
|
||||
@@ -8,8 +8,7 @@
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
@@ -19,13 +18,45 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>hawkbit-examples-parent</artifactId>
|
||||
<name>hawkBit :: Examples Parent</name>
|
||||
<name>hawkBit-example :: Parent</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>hawkbit-device-simulator</module>
|
||||
<module>hawkbit-example-app</module>
|
||||
<module>hawkbit-mgmt-api-client</module>
|
||||
</modules>
|
||||
<module>hawkbit-example-core-feign-client</module>
|
||||
<module>hawkbit-example-ddi-feign-client</module>
|
||||
<module>hawkbit-example-mgmt-feign-client</module>
|
||||
<module>hawkbit-example-mgmt-simulator</module>
|
||||
</modules>
|
||||
|
||||
|
||||
<properties>
|
||||
<feign.version>8.14.2</feign.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-core</artifactId>
|
||||
<!-- need to overwrite for the interface inheritance feature of feign-core -->
|
||||
<!-- <version>8.16.0</version> -->
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-jackson</artifactId>
|
||||
<!-- need to overwrite for the interface inheritance feature of feign-core -->
|
||||
<!-- <version>8.16.0</version> -->
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.feign</groupId>
|
||||
<artifactId>feign-slf4j</artifactId>
|
||||
<version>${feign.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
@@ -87,9 +87,7 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
|
||||
/**
|
||||
* Retrieves a {@link GridFSDBFile} from the store by it's MD5 hash.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
*
|
||||
* @param md5Hash
|
||||
* the md5-hash of the file to lookup.
|
||||
* @return The gridfs file object or {@code null} if no file exists.
|
||||
@@ -100,9 +98,7 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
|
||||
/**
|
||||
* Retrieves a {@link GridFSDBFile} from the store by it's object id.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
*
|
||||
* @param id
|
||||
* the id of the file to lookup.
|
||||
* @return The gridfs file object or {@code null} if no file exists.
|
||||
@@ -124,11 +120,9 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
try {
|
||||
LOGGER.debug("storing file {} of content {}", filename, contentType);
|
||||
tempFile = File.createTempFile("uploadFile", null);
|
||||
try (final FileOutputStream os = new FileOutputStream(tempFile)) {
|
||||
try (BufferedOutputStream bos = new BufferedOutputStream(os)) {
|
||||
try (BufferedInputStream bis = new BufferedInputStream(content)) {
|
||||
return store(content, contentType, bos, tempFile, hash);
|
||||
}
|
||||
try (final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile))) {
|
||||
try (BufferedInputStream bis = new BufferedInputStream(content)) {
|
||||
return store(bis, contentType, bos, tempFile, hash);
|
||||
}
|
||||
}
|
||||
} catch (final IOException | MongoException e1) {
|
||||
@@ -207,6 +201,9 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
throws NoSuchAlgorithmException, IOException {
|
||||
String sha1Hash;
|
||||
// compute digest
|
||||
// Exception squid:S2070 - not used for hashing sensitive
|
||||
// data
|
||||
@SuppressWarnings("squid:S2070")
|
||||
final MessageDigest md = MessageDigest.getInstance("SHA-1");
|
||||
try (final DigestOutputStream dos = new DigestOutputStream(os, md)) {
|
||||
ByteStreams.copy(stream, dos);
|
||||
@@ -230,15 +227,13 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
* @return a paged list of artifacts mapped from the given dbFiles
|
||||
*/
|
||||
private List<DbArtifact> map(final List<GridFSDBFile> dbFiles) {
|
||||
return dbFiles.stream().map(dbFile -> map(dbFile)).collect(Collectors.toList());
|
||||
return dbFiles.stream().map(this::map).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of {@link GridFSDBFile} from the store by all SHA1
|
||||
* hashes.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
*
|
||||
* @param sha1Hashes
|
||||
* the sha1-hashes of the files to lookup.
|
||||
* @return list of artifacts
|
||||
@@ -251,8 +246,6 @@ public class ArtifactStore implements ArtifactRepository {
|
||||
/**
|
||||
* Retrieves a list of {@link GridFSDBFile} from the store by all ids.
|
||||
*
|
||||
* @param tenant
|
||||
* the tenant to retrieve the artifacts from, ignore case.
|
||||
* @param ids
|
||||
* the ids of the files to lookup.
|
||||
* @return list of artfiacts
|
||||
|
||||
@@ -10,18 +10,13 @@ package org.eclipse.hawkbit.artifact.repository;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Auto configuration for the {@link ArtifactStore}.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@ConditionalOnMissingBean(value = ArtifactRepository.class)
|
||||
@Import(value = MongoConfiguration.class)
|
||||
public class ArtifactStoreAutoConfiguration {
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository</artifactId>
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
@@ -64,7 +64,13 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-rest-resource</artifactId>
|
||||
<artifactId>hawkbit-ddi-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-mgmt-resource</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.cache.interceptor.CacheOperationInvocationContext;
|
||||
import org.springframework.cache.interceptor.SimpleCacheResolver;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
|
||||
/**
|
||||
* A configuration for configuring the spring {@link CacheManager} for specific
|
||||
@@ -33,9 +34,6 @@ import org.springframework.context.annotation.Configuration;
|
||||
*
|
||||
* This is done by providing a special {@link TenantCacheResolver} which
|
||||
* generates a cache name included the current tenant.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
@@ -51,18 +49,27 @@ public class CacheAutoConfiguration extends CachingConfigurerSupport {
|
||||
@Override
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
@Primary
|
||||
public TenancyCacheManager cacheManager() {
|
||||
return new TenantAwareCacheManager(new GuavaCacheManager(), tenantAware);
|
||||
return new TenantAwareCacheManager(directCacheManager(), tenantAware);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the direct cache manager to access without tenant aware check,
|
||||
* cause in sometimes it's necessary to access the cache directly
|
||||
* without having the current tenant, e.g. initial creation of
|
||||
* tenant
|
||||
*/
|
||||
@Bean(name = "directCacheManager")
|
||||
@ConditionalOnMissingBean(name = "directCacheManager")
|
||||
public CacheManager directCacheManager() {
|
||||
return new GuavaCacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link SimpleCacheResolver} implementation which includes the
|
||||
* {@link TenantAware#getCurrentTenant()} into the cache name before
|
||||
* resolving it.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TenantCacheResolver extends SimpleCacheResolver {
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ public class DownloadIdCacheAutoConfiguration {
|
||||
private CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* Bean for the downlod id cache.
|
||||
* Bean for the download id cache.
|
||||
*
|
||||
* @return the cache
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.concurrent.Executor;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.EventBusSubscriberProcessor;
|
||||
import org.eclipse.hawkbit.eventbus.EventSubscriber;
|
||||
import org.eclipse.hawkbit.repository.model.helper.EventBusHolder;
|
||||
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;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* 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.repository;
|
||||
|
||||
import org.eclipse.hawkbit.EnableJpaRepository;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Auto-Configuration for enabling the REST-Resources.
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableJpaRepository.class })
|
||||
@Import({ EnableJpaRepository.class })
|
||||
public class JpaRepositoryAutoConfiguration {
|
||||
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import org.springframework.scheduling.annotation.EnableAsync;
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
@ConditionalOnMissingBean(AsyncConfigurer.class)
|
||||
|
||||
@@ -20,7 +20,7 @@ public class AsyncConfigurerThreadpoolProperties {
|
||||
/**
|
||||
* Max queue size for central event executor.
|
||||
*/
|
||||
private Integer queuesize = 250;
|
||||
private Integer queuesize = 5_000;
|
||||
|
||||
/**
|
||||
* Core processing threads for central event executor.
|
||||
@@ -30,7 +30,12 @@ public class AsyncConfigurerThreadpoolProperties {
|
||||
/**
|
||||
* Maximum thread pool size for central event executor.
|
||||
*/
|
||||
private Integer maxthreads = 50;
|
||||
private Integer maxthreads = 20;
|
||||
|
||||
/**
|
||||
* Core processing threads for scheduled event executor.
|
||||
*/
|
||||
private Integer schedulerThreads = 3;
|
||||
|
||||
/**
|
||||
* When the number of threads is greater than the core, this is the maximum
|
||||
@@ -70,4 +75,12 @@ public class AsyncConfigurerThreadpoolProperties {
|
||||
this.idletimeout = idletimeout;
|
||||
}
|
||||
|
||||
public Integer getSchedulerThreads() {
|
||||
return schedulerThreads;
|
||||
}
|
||||
|
||||
public void setSchedulerThreads(final Integer schedulerThreads) {
|
||||
this.schedulerThreads = schedulerThreads;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,7 +11,11 @@ package org.eclipse.hawkbit.autoconfigure.scheduling;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -21,7 +25,13 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
|
||||
import org.springframework.security.concurrent.DelegatingSecurityContextExecutor;
|
||||
import org.springframework.security.concurrent.DelegatingSecurityContextExecutorService;
|
||||
import org.springframework.security.concurrent.DelegatingSecurityContextScheduledExecutorService;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
@@ -39,21 +49,46 @@ public class ExecutorAutoConfiguration {
|
||||
private AsyncConfigurerThreadpoolProperties asyncConfigurerProperties;
|
||||
|
||||
/**
|
||||
* @return ExecutorService for general purpose multi threaded operations
|
||||
* @return ExecutorService with security context availability in thread
|
||||
* execution.
|
||||
*/
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean
|
||||
public ExecutorService asyncExecutor() {
|
||||
return new DelegatingSecurityContextExecutorService(threadPoolExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link TaskExecutor} for task execution
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public Executor asyncExecutor() {
|
||||
public TaskExecutor taskExecutor() {
|
||||
return new ConcurrentTaskExecutor(asyncExecutor());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return central ThreadPoolExecutor for general purpose multi threaded
|
||||
* operations. Tries an orderly shutdown when destroyed.
|
||||
*/
|
||||
private ThreadPoolExecutor threadPoolExecutor() {
|
||||
final BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<>(
|
||||
asyncConfigurerProperties.getQueuesize());
|
||||
final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(asyncConfigurerProperties.getCorethreads(),
|
||||
return new ThreadPoolExecutor(asyncConfigurerProperties.getCorethreads(),
|
||||
asyncConfigurerProperties.getMaxthreads(), asyncConfigurerProperties.getIdletimeout(),
|
||||
TimeUnit.MILLISECONDS, blockingQueue,
|
||||
new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build());
|
||||
threadPoolExecutor.setRejectedExecutionHandler((r, executor) -> LOGGER.warn(
|
||||
"Reject runnable for centralExecutorService, reached limit of queue size {}",
|
||||
executor.getQueue().size()));
|
||||
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
|
||||
new ThreadFactoryBuilder().setNameFormat("central-executor-pool-%d").build(),
|
||||
new PoolSizeExceededPolicy());
|
||||
}
|
||||
|
||||
private static class PoolSizeExceededPolicy extends CallerRunsPolicy {
|
||||
@Override
|
||||
public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
|
||||
LOGGER.warn(
|
||||
"Caller has to run on its own instead of centralExecutorService, reached limit of queue size {}",
|
||||
executor.getQueue().size());
|
||||
super.rejectedExecution(r, executor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,4 +104,25 @@ public class ExecutorAutoConfiguration {
|
||||
return new DelegatingSecurityContextExecutor(threadPoolExecutor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link ScheduledExecutorService} with security context
|
||||
* availability in thread execution.
|
||||
*/
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
@ConditionalOnMissingBean
|
||||
public ScheduledExecutorService scheduledExecutorService() {
|
||||
return new DelegatingSecurityContextScheduledExecutorService(
|
||||
Executors.newScheduledThreadPool(asyncConfigurerProperties.getSchedulerThreads(),
|
||||
new ThreadFactoryBuilder().setNameFormat("central-scheduled-executor-pool-%d").build()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link TaskScheduler} for task execution
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TaskScheduler taskScheduler() {
|
||||
return new ConcurrentTaskScheduler(scheduledExecutorService());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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.security;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
|
||||
import org.eclipse.hawkbit.im.authentication.PermissionUtils;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
|
||||
/**
|
||||
* Auto-configuration for the in-memory-user-management.
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(UserDetailsService.class)
|
||||
public class InMemoryUserManagementConfiguration extends GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
final DaoAuthenticationProvider userDaoAuthenticationProvider = new TenantDaoAuthenticationProvider();
|
||||
userDaoAuthenticationProvider.setUserDetailsService(userDetailsService());
|
||||
auth.authenticationProvider(userDaoAuthenticationProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the user details service to load a user from memory user manager.
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public UserDetailsService userDetailsService() {
|
||||
final InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(new ArrayList<>());
|
||||
inMemoryUserDetailsManager.setAuthenticationManager(null);
|
||||
inMemoryUserDetailsManager.createUser(new User("admin", "admin", PermissionUtils.createAllAuthorityList()));
|
||||
return inMemoryUserDetailsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the multi-tenancy indicator to disallow multi-tenancy
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public MultitenancyIndicator multiTenancyIndicator() {
|
||||
return () -> false;
|
||||
}
|
||||
|
||||
private static class TenantDaoAuthenticationProvider extends DaoAuthenticationProvider {
|
||||
|
||||
@Override
|
||||
protected Authentication createSuccessAuthentication(final Object principal,
|
||||
final Authentication authentication, final UserDetails user) {
|
||||
final UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
|
||||
authentication.getCredentials(), user.getAuthorities());
|
||||
result.setDetails(new TenantAwareAuthenticationDetails("DEFAULT", false));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,43 +8,17 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.autoconfigure.security;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.MultitenancyIndicator;
|
||||
import org.eclipse.hawkbit.im.authentication.PermissionService;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantAwareAuthenticationDetails;
|
||||
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.SecurityContextTenantAware;
|
||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* {@link EnableAutoConfiguration Auto-configuration} for security.
|
||||
@@ -88,119 +62,4 @@ public class SecurityAutoConfiguration {
|
||||
return new SpringSecurityAuditorAware();
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto-configuration for the in-memory-user-management.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(value = { UserAuthenticationFilter.class })
|
||||
public static class InMemoryUserManagementConfiguration extends GlobalAuthenticationConfigurerAdapter {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InMemoryUserManagementConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private AuthenticationConfiguration configuration;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.config.annotation.authentication.
|
||||
* configurers. GlobalAuthenticationConfigurerAdapter
|
||||
* #configure(org.springframework.security.config.annotation.
|
||||
* authentication.builders.AuthenticationManagerBuilder)
|
||||
*/
|
||||
@Override
|
||||
public void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
final DaoAuthenticationProvider userDaoAuthenticationProvider = new TenantDaoAuthenticationProvider();
|
||||
userDaoAuthenticationProvider.setUserDetailsService(userDetailsService());
|
||||
auth.authenticationProvider(userDaoAuthenticationProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the user details service to load a user from memory user
|
||||
* manager.
|
||||
*/
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
final InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(
|
||||
new ArrayList<>());
|
||||
inMemoryUserDetailsManager.setAuthenticationManager(null);
|
||||
inMemoryUserDetailsManager.createUser(new User("admin", "admin", getAllAuthorities()));
|
||||
return inMemoryUserDetailsManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the multi-tenancy indicator to disallow multi-tenancy
|
||||
*/
|
||||
@Bean
|
||||
public MultitenancyIndicator multiTenancyIndicator() {
|
||||
return new MultitenancyIndicator() {
|
||||
@Override
|
||||
public boolean isMultiTenancySupported() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Collection<SimpleGrantedAuthority> getAllAuthorities() {
|
||||
final List<SimpleGrantedAuthority> allPermissions = new ArrayList<>();
|
||||
final Field[] declaredFields = SpPermission.class.getDeclaredFields();
|
||||
for (final Field field : declaredFields) {
|
||||
if (Modifier.isPublic(field.getModifiers()) && Modifier.isStatic(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
final String permissionName = (String) field.get(null);
|
||||
allPermissions.add(new SimpleGrantedAuthority(permissionName));
|
||||
} catch (final IllegalAccessException e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return allPermissions;
|
||||
}
|
||||
|
||||
private static class TenantDaoAuthenticationProvider extends DaoAuthenticationProvider {
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.springframework.security.authentication.dao.
|
||||
* AbstractUserDetailsAuthenticationProvider
|
||||
* #createSuccessAuthentication(java.lang.Object,
|
||||
* org.springframework.security.core.Authentication,
|
||||
* org.springframework.security.core.userdetails.UserDetails)
|
||||
*/
|
||||
@Override
|
||||
protected Authentication createSuccessAuthentication(final Object principal,
|
||||
final Authentication authentication, final UserDetails user) {
|
||||
final UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(principal,
|
||||
authentication.getCredentials(), user.getAuthorities());
|
||||
result.setDetails(new TenantAwareAuthenticationDetails("DEFAULT", false));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link UserAuthenticationFilter} to include into the SP
|
||||
* security configuration.
|
||||
* @throws Exception
|
||||
* lazy bean exception maybe if the authentication manager
|
||||
* cannot be instantiated
|
||||
*/
|
||||
@Bean
|
||||
public UserAuthenticationFilter userAuthenticationFilter() throws Exception {
|
||||
return new UserAuthenticationFilterBasicAuth(configuration.getAuthenticationManager());
|
||||
}
|
||||
|
||||
private static final class UserAuthenticationFilterBasicAuth extends BasicAuthenticationFilter
|
||||
implements UserAuthenticationFilter {
|
||||
|
||||
private UserAuthenticationFilterBasicAuth(final AuthenticationManager authenticationManager) {
|
||||
super(authenticationManager);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.autoconfigure.security;
|
||||
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
import static org.springframework.context.annotation.AdviceMode.ASPECTJ;
|
||||
import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
@@ -26,10 +30,10 @@ import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions;
|
||||
import org.eclipse.hawkbit.im.authentication.TenantUserPasswordAuthenticationToken;
|
||||
import org.eclipse.hawkbit.im.authentication.UserAuthenticationFilter;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.rest.resource.RestConstants;
|
||||
import org.eclipse.hawkbit.security.ControllerTenantAwareAuthenticationDetailsSource;
|
||||
import org.eclipse.hawkbit.security.DdiSecurityProperties;
|
||||
import org.eclipse.hawkbit.security.DosFilter;
|
||||
@@ -46,18 +50,19 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
|
||||
import org.springframework.boot.context.embedded.FilterRegistrationBean;
|
||||
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.context.annotation.AdviceMode;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
@@ -72,10 +77,13 @@ import org.springframework.security.web.access.intercept.FilterSecurityIntercept
|
||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode;
|
||||
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.vaadin.spring.security.VaadinSecurityContext;
|
||||
import org.vaadin.spring.security.annotation.EnableVaadinSecurity;
|
||||
import org.vaadin.spring.security.web.VaadinDefaultRedirectStrategy;
|
||||
@@ -83,30 +91,49 @@ import org.vaadin.spring.security.web.VaadinRedirectStrategy;
|
||||
import org.vaadin.spring.security.web.authentication.VaadinAuthenticationSuccessHandler;
|
||||
import org.vaadin.spring.security.web.authentication.VaadinUrlAuthenticationSuccessHandler;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
/**
|
||||
* All configurations related to SP authentication and authorization layer.
|
||||
*
|
||||
*
|
||||
*
|
||||
* All configurations related to HawkBit's authentication and authorization
|
||||
* layer.
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = AdviceMode.ASPECTJ, proxyTargetClass = true, securedEnabled = true)
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, mode = ASPECTJ, proxyTargetClass = true, securedEnabled = true)
|
||||
@EnableWebMvcSecurity
|
||||
@Order(value = Ordered.HIGHEST_PRECEDENCE)
|
||||
@Order(value = HIGHEST_PRECEDENCE)
|
||||
public class SecurityManagedConfiguration {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SecurityManagedConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
@Autowired
|
||||
private AuthenticationConfiguration configuration;
|
||||
|
||||
/**
|
||||
* @return the {@link UserAuthenticationFilter} to include into the SP
|
||||
* security configuration.
|
||||
* @throws Exception
|
||||
* lazy bean exception maybe if the authentication manager
|
||||
* cannot be instantiated
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public UserAuthenticationFilter userAuthenticationFilter() throws Exception {
|
||||
return new UserAuthenticationFilterBasicAuth(configuration.getAuthenticationManager());
|
||||
}
|
||||
|
||||
private static final class UserAuthenticationFilterBasicAuth extends BasicAuthenticationFilter
|
||||
implements UserAuthenticationFilter {
|
||||
|
||||
private UserAuthenticationFilterBasicAuth(final AuthenticationManager authenticationManager) {
|
||||
super(authenticationManager);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebSecurityConfigurer} for the internal SP controller API.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(300)
|
||||
@@ -114,19 +141,25 @@ public class SecurityManagedConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ControllerManagement controllerManagement;
|
||||
|
||||
@Autowired
|
||||
private TenantConfigurationManagement tenantConfigurationManagement;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private DdiSecurityProperties ddiSecurityConfiguration;
|
||||
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
@Autowired
|
||||
private SystemSecurityContext systemSecurityContext;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
final ControllerTenantAwareAuthenticationDetailsSource authenticationDetailsSource = new ControllerTenantAwareAuthenticationDetailsSource();
|
||||
|
||||
final HttpControllerPreAuthenticatedSecurityHeaderFilter securityHeaderFilter = new HttpControllerPreAuthenticatedSecurityHeaderFilter(
|
||||
@@ -164,16 +197,19 @@ public class SecurityManagedConfiguration {
|
||||
}
|
||||
|
||||
if (ddiSecurityConfiguration.getAuthentication().getAnonymous().isEnabled()) {
|
||||
|
||||
LOG.info(
|
||||
"******************\n** Anonymous controller security enabled, should only use for developing purposes **\n******************");
|
||||
"******************\n** Anonymous controller security enabled, should only be used for developing purposes **\n******************");
|
||||
|
||||
final AnonymousAuthenticationFilter anoymousFilter = new AnonymousAuthenticationFilter(
|
||||
"controllerAnonymousFilter", "anonymous",
|
||||
Lists.newArrayList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS),
|
||||
newArrayList(new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS),
|
||||
new SimpleGrantedAuthority(SpringEvalExpressions.CONTROLLER_DOWNLOAD_ROLE)));
|
||||
anoymousFilter.setAuthenticationDetailsSource(authenticationDetailsSource);
|
||||
httpSec.requestMatchers().antMatchers("/*/controller/v1/**", "/*/controller/artifacts/v1/**").and()
|
||||
.securityContext().disable().anonymous().authenticationFilter(anoymousFilter);
|
||||
} else {
|
||||
|
||||
httpSec.addFilter(securityHeaderFilter).addFilter(securityTokenFilter)
|
||||
.addFilter(gatewaySecurityTokenFilter).addFilter(controllerAnonymousDownloadFilter)
|
||||
.antMatcher("/*/controller/**").anonymous().disable().authorizeRequests().anyRequest()
|
||||
@@ -186,6 +222,7 @@ public class SecurityManagedConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
||||
|
||||
auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(
|
||||
ddiSecurityConfiguration.getRp().getTrustedIPs()));
|
||||
}
|
||||
@@ -200,6 +237,7 @@ public class SecurityManagedConfiguration {
|
||||
@Bean
|
||||
@Order(50)
|
||||
public FilterRegistrationBean dosFilter() {
|
||||
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
|
||||
filterRegBean.setFilter(new DosFilter(securityProperties.getDos().getFilter().getMaxRead(),
|
||||
@@ -207,6 +245,7 @@ public class SecurityManagedConfiguration {
|
||||
securityProperties.getDos().getFilter().getWhitelist(), securityProperties.getClients().getBlacklist(),
|
||||
securityProperties.getClients().getRemoteIpHeader()));
|
||||
filterRegBean.addUrlPatterns("/{tenant}/controller/v1/*", "/rest/*");
|
||||
|
||||
return filterRegBean;
|
||||
}
|
||||
|
||||
@@ -219,58 +258,49 @@ public class SecurityManagedConfiguration {
|
||||
@Bean
|
||||
@Order(100)
|
||||
public FilterRegistrationBean eTagFilter() {
|
||||
|
||||
final FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
|
||||
// eclude the URLs for downloading artifacts, so no eTag is generated in
|
||||
// the
|
||||
// ShallowEtagHeaderFilter, just using the SH1 hash of the artifact
|
||||
// itself as 'ETag', because
|
||||
// otherwise the file will be copied in memory!
|
||||
// Exclude the URLs for downloading artifacts, so no eTag is generated
|
||||
// in the ShallowEtagHeaderFilter, just using the SH1 hash of the
|
||||
// artifact itself as 'ETag', because otherwise the file will be copied
|
||||
// in memory!
|
||||
filterRegBean.setFilter(new ExcludePathAwareShallowETagFilter(
|
||||
"/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download", "/{tenant}/controller/artifacts/**",
|
||||
"/{targetid}/softwaremodules/{softwareModuleId}/artifacts/**"));
|
||||
|
||||
return filterRegBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Security configuration for the REST management API of the health url.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(310)
|
||||
public static class HealthSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
http.regexMatcher("/system/health").csrf().disable().httpBasic().and().sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Security configuration for the REST management API.
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(350)
|
||||
public static class RestSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private UserAuthenticationFilter userAuthenticationFilter;
|
||||
|
||||
@Autowired
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
private SecurityProperties springSecurityProperties;
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
HttpSecurity httpSec = http.regexMatcher("\\/rest.*|\\/system.*").csrf().disable();
|
||||
final BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
|
||||
basicAuthEntryPoint.setRealmName(springSecurityProperties.getBasic().getRealm());
|
||||
|
||||
HttpSecurity httpSec = http.regexMatcher("\\/rest.*|\\/system/admin.*").csrf().disable();
|
||||
if (springSecurityProperties.isRequireSsl()) {
|
||||
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
|
||||
}
|
||||
|
||||
httpSec.addFilterBefore(new Filter() {
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
@@ -290,17 +320,17 @@ public class SecurityManagedConfiguration {
|
||||
}, RequestHeaderAuthenticationFilter.class)
|
||||
.addFilterAfter(
|
||||
new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement),
|
||||
RequestHeaderAuthenticationFilter.class)
|
||||
SessionManagementFilter.class)
|
||||
.authorizeRequests().anyRequest().authenticated()
|
||||
.antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
|
||||
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN).antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/**")
|
||||
.hasAnyAuthority(SpPermission.SYSTEM_DIAG);
|
||||
.antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
|
||||
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN);
|
||||
|
||||
httpSec.httpBasic().and().exceptionHandling().authenticationEntryPoint(basicAuthEntryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WebSecurityConfigurer} for external (management) access.
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@Order(400)
|
||||
@@ -310,10 +340,13 @@ public class SecurityManagedConfiguration {
|
||||
private static final String XFRAME_OPTION_DENY = "DENY";
|
||||
private static final String XFRAME_OPTION_SAMEORIGIN = "SAMEORIGIN";
|
||||
private static final String XFAME_OPTION_ALLOW_FROM = "ALLOW-FROM";
|
||||
|
||||
@Autowired
|
||||
private VaadinSecurityContext vaadinSecurityContext;
|
||||
|
||||
@Autowired
|
||||
private org.springframework.boot.autoconfigure.security.SecurityProperties springSecurityProperties;
|
||||
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
@@ -345,10 +378,13 @@ public class SecurityManagedConfiguration {
|
||||
*/
|
||||
@Bean
|
||||
public VaadinAuthenticationSuccessHandler redirectSaveHandler() {
|
||||
|
||||
final VaadinUrlAuthenticationSuccessHandler handler = new TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler();
|
||||
|
||||
handler.setRedirectStrategy(vaadinRedirectStrategy());
|
||||
handler.setDefaultTargetUrl("/UI/");
|
||||
handler.setTargetUrlParameter("r");
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
@@ -370,7 +406,8 @@ public class SecurityManagedConfiguration {
|
||||
// configuration xframe-option
|
||||
final String confXframeOption = securityProperties.getXframe().getOption();
|
||||
final String confAllowFromUri = securityProperties.getXframe().getAllowfrom();
|
||||
if (confXframeOption.equals(XFAME_OPTION_ALLOW_FROM) && confAllowFromUri.isEmpty()) {
|
||||
|
||||
if (XFAME_OPTION_ALLOW_FROM.equals(confXframeOption) && confAllowFromUri.isEmpty()) {
|
||||
// if allow-from option is specified but no allowFromUri throw
|
||||
// exception
|
||||
throw new IllegalStateException("hawkbit.server.security.xframe.option has been specified as ALLOW-FROM"
|
||||
@@ -379,9 +416,8 @@ public class SecurityManagedConfiguration {
|
||||
}
|
||||
|
||||
// workaround regex: we need to exclude the URL /UI/HEARTBEAT here
|
||||
// because we bound the
|
||||
// vaadin application to /UI and not to root, described in
|
||||
// vaadin-forum:
|
||||
// because we bound the vaadin application to /UI and not to root,
|
||||
// described in vaadin-forum:
|
||||
// https://vaadin.com/forum#!/thread/3200565.
|
||||
HttpSecurity httpSec = http.regexMatcher("(?!.*HEARTBEAT)^.*\\/UI.*$")
|
||||
// disable as CSRF is handled by Vaadin
|
||||
@@ -390,8 +426,9 @@ public class SecurityManagedConfiguration {
|
||||
if (springSecurityProperties.isRequireSsl()) {
|
||||
httpSec = httpSec.requiresChannel().anyRequest().requiresSecure().and();
|
||||
} else {
|
||||
|
||||
LOG.info(
|
||||
"\"******************\\n** Requires HTTPS Security has been disabled for UI, should only use for developing purposes **\\n******************\"");
|
||||
"\"******************\\n** Requires HTTPS Security has been disabled for UI, should only be used for developing purposes **\\n******************\"");
|
||||
}
|
||||
|
||||
// for UI integrator we allow frame integration on same origin
|
||||
@@ -440,9 +477,6 @@ public class SecurityManagedConfiguration {
|
||||
|
||||
/**
|
||||
* A Websecruity config to handle and filter the download ids.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@@ -458,6 +492,7 @@ public class SecurityManagedConfiguration {
|
||||
|
||||
@Override
|
||||
protected void configure(final HttpSecurity http) throws Exception {
|
||||
|
||||
final HttpDownloadAuthenticationFilter downloadIdAuthenticationFilter = new HttpDownloadAuthenticationFilter(
|
||||
downloadIdCache);
|
||||
downloadIdAuthenticationFilter.setAuthenticationManager(authenticationManager());
|
||||
@@ -475,32 +510,21 @@ public class SecurityManagedConfiguration {
|
||||
auth.authenticationProvider(new PreAuthTokenSourceTrustAuthenticationProvider(
|
||||
ddiSecurityConfiguration.getRp().getTrustedIPs()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* After a successful login on the UI we need to ensure to create the tenant
|
||||
* meta data within SP.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends VaadinUrlAuthenticationSuccessHandler {
|
||||
|
||||
@Autowired
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.vaadin.spring.security.web.authentication.
|
||||
* SavedRequestAwareVaadinAuthenticationSuccessHandler
|
||||
* #onAuthenticationSuccess(org.springframework.security.core.
|
||||
* Authentication)
|
||||
*/
|
||||
@Override
|
||||
public void onAuthenticationSuccess(final Authentication authentication) throws Exception {
|
||||
|
||||
if (authentication.getClass().equals(TenantUserPasswordAuthenticationToken.class)) {
|
||||
systemManagement
|
||||
.getTenantMetadata(((TenantUserPasswordAuthenticationToken) authentication).getTenant().toString());
|
||||
@@ -514,14 +538,13 @@ class TenantMetadataSavedRequestAwareVaadinAuthenticationSuccessHandler extends
|
||||
// has been fixed.
|
||||
systemManagement.getTenantMetadata("DEFAULT");
|
||||
}
|
||||
|
||||
super.onAuthenticationSuccess(authentication);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sevletfilter to create metadata after successful authentication over RESTful.
|
||||
*
|
||||
*
|
||||
*/
|
||||
class AuthenticationSuccessTenantMetadataCreationFilter implements Filter {
|
||||
|
||||
@@ -542,11 +565,13 @@ class AuthenticationSuccessTenantMetadataCreationFilter implements Filter {
|
||||
@Override
|
||||
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
final String currentTenant = tenantAware.getCurrentTenant();
|
||||
if (currentTenant != null) {
|
||||
// lazy initialize tenant meta data after successful authentication
|
||||
systemManagement.getTenantMetadata(currentTenant);
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,21 +8,19 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.autoconfigure.web;
|
||||
|
||||
import org.eclipse.hawkbit.controller.EnableDirectDeviceApi;
|
||||
import org.eclipse.hawkbit.rest.resource.EnableRestResources;
|
||||
import org.eclipse.hawkbit.ddi.EnableDdiApi;
|
||||
import org.eclipse.hawkbit.mgmt.EnableMgmtApi;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
/**
|
||||
* Auto-Configuration for enabling the REST-Resources.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnClass({ EnableDirectDeviceApi.class, EnableRestResources.class })
|
||||
@Import({ EnableDirectDeviceApi.class, EnableRestResources.class })
|
||||
@ConditionalOnClass({ EnableDdiApi.class, EnableMgmtApi.class })
|
||||
@Import({ EnableDdiApi.class, EnableMgmtApi.class })
|
||||
public class ResourceControllerAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@@ -11,4 +11,5 @@ org.eclipse.hawkbit.autoconfigure.eventbus.EventBusAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.AsyncConfigurerAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.cache.RedisAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.scheduling.ExecutorAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration
|
||||
org.eclipse.hawkbit.autoconfigure.amqp.AmqpAutoConfiguration,\
|
||||
org.eclipse.hawkbit.autoconfigure.security.InMemoryUserManagementConfiguration
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
# Displayed basic auth realm
|
||||
security.basic.realm=HawkBit
|
||||
|
||||
# JPA / Datasource
|
||||
spring.jpa.eclipselink.eclipselink.weaving=false
|
||||
spring.jpa.database=H2
|
||||
@@ -27,12 +30,6 @@ vaadin.servlet.urlMapping=/UI/*
|
||||
vaadin.servlet.heartbeatInterval=60
|
||||
vaadin.servlet.closeIdleSessions=false
|
||||
|
||||
# Defines the thread pool executor
|
||||
hawkbit.threadpool.corethreads=5
|
||||
hawkbit.threadpool.maxthreads=20
|
||||
hawkbit.threadpool.idletimeout=10000
|
||||
hawkbit.threadpool.queuesize=20000
|
||||
|
||||
# Defines the polling time for the controllers in HH:MM:SS notation
|
||||
hawkbit.controller.pollingTime=00:05:00
|
||||
hawkbit.controller.pollingOverdueTime=00:05:00
|
||||
@@ -44,4 +41,5 @@ hawkbit.controller.minPollingTime=00:00:30
|
||||
# Configuration for RabbitMQ integration
|
||||
hawkbit.dmf.rabbitmq.deadLetterQueue=dmf_connector_deadletter_ttl
|
||||
hawkbit.dmf.rabbitmq.deadLetterExchange=dmf.connector.deadletter
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
hawkbit.dmf.rabbitmq.receiverQueue=dmf_receiver
|
||||
hawkbit.dmf.rabbitmq.authenticationReceiverQueue=authentication_receiver
|
||||
|
||||
@@ -45,6 +45,12 @@
|
||||
|
||||
|
||||
<!-- 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>
|
||||
|
||||
@@ -15,6 +15,7 @@ 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;
|
||||
@@ -50,8 +51,14 @@ public class RedisConfiguration {
|
||||
* @return the spring redis cache manager.
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
public CacheManager cacheManager() {
|
||||
return new TenantAwareCacheManager(new RedisCacheManager(redisTemplate()), tenantAware);
|
||||
return new TenantAwareCacheManager(directCacheManager(), tenantAware);
|
||||
}
|
||||
|
||||
@Bean(name = "directCacheManager")
|
||||
public CacheManager directCacheManager() {
|
||||
return new RedisCacheManager(redisTemplate());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,8 +16,8 @@ import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
|
||||
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;
|
||||
@@ -56,7 +56,7 @@ public class EventDistributorTest {
|
||||
@Test
|
||||
public void distributeDistributedEventSendsToRedis() {
|
||||
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
underTest.distribute(event);
|
||||
|
||||
// origin node ID should be set by distributing the event
|
||||
@@ -67,7 +67,7 @@ public class EventDistributorTest {
|
||||
@Test
|
||||
public void dontDistributeDistributedEventIfSameNode() {
|
||||
final String knownNodeId = EventDistributor.getNodeId();
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
event.setNodeId(knownNodeId);
|
||||
|
||||
// test
|
||||
@@ -79,7 +79,7 @@ public class EventDistributorTest {
|
||||
|
||||
@Test
|
||||
public void handleDistributedMessageFromRedis() {
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
final String knownChannel = "someChannel";
|
||||
|
||||
underTest.handleMessage(event, knownChannel);
|
||||
@@ -90,7 +90,7 @@ public class EventDistributorTest {
|
||||
|
||||
@Test
|
||||
public void handleDistributedMessageFilteredIfSameNodeId() {
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 10);
|
||||
final DownloadProgressEvent event = new DownloadProgressEvent("tenant", 123L, 500L, 100L, 200L);
|
||||
final String knownChannel = "someChannel";
|
||||
event.setOriginNodeId(EventDistributor.getNodeId());
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user