Merge remote-tracking branch 'origin/master' into fix_introduce_consistent_button_position_in_change_dialogs

This commit is contained in:
Melanie Retter
2016-05-30 12:35:12 +02:00
251 changed files with 4872 additions and 3434 deletions

View File

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

View File

@@ -41,9 +41,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 +57,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.

View File

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

View File

@@ -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>
@@ -82,16 +82,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>com.vaadin</groupId>

View File

@@ -118,9 +118,6 @@ public class DeviceSimulatorUpdater {
}
private static final class DeviceSimulatorUpdateThread implements Runnable {
/**
*
*/
private static final int MINIMUM_TOKENLENGTH_FOR_HINT = 6;
private static final Random rndSleep = new SecureRandom();
@@ -152,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;
@@ -265,7 +264,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());
}
@@ -275,6 +274,10 @@ public class DeviceSimulatorUpdater {
}
private static String hideTokenDetails(final String targetToken) {
if (targetToken == null) {
return "<NULL!>";
}
if (targetToken.isEmpty()) {
return "<EMTPTY!>";
}

View File

@@ -53,11 +53,13 @@ import com.vaadin.ui.renderers.ProgressBarRenderer;
*
*/
@SpringView(name = "")
// The inheritance comes from Vaadin
@SuppressWarnings("squid:MaximumInheritanceDepth")
public class SimulatorView extends VerticalLayout implements View {
private static final String NEXT_POLL_COUNTER_SEC_COL = "nextPollCounterSec";
private static final String RESPONSE_STATUS_COL = "responseStatus";
private static final String RESPONSE_STATUS_COL = "updateStatus";
private static final String PROTOCOL_COL = "protocol";
@@ -141,10 +143,9 @@ public class SimulatorView extends VerticalLayout implements View {
responseComboBox.setItemIcon(ResponseStatus.ERROR, FontAwesome.EXCLAMATION_CIRCLE);
responseComboBox.setNullSelectionAllowed(false);
responseComboBox.setValue(ResponseStatus.SUCCESSFUL);
responseComboBox.addValueChangeListener(valueChangeEvent -> {
beanContainer.getItemIds().forEach(itemId -> beanContainer.getItem(itemId)
.getItemProperty(RESPONSE_STATUS_COL).setValue(valueChangeEvent.getProperty().getValue()));
});
responseComboBox.addValueChangeListener(
valueChangeEvent -> beanContainer.getItemIds().forEach(itemId -> beanContainer.getItem(itemId)
.getItemProperty(RESPONSE_STATUS_COL).setValue(valueChangeEvent.getProperty().getValue())));
// add all components
addComponent(caption);

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

View File

@@ -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>
@@ -96,16 +101,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>

View File

@@ -20,11 +20,11 @@ import com.vaadin.spring.annotation.SpringUI;
* login path. The easiest way to get an hawkBit login UI running is to extend
* the {@link HawkbitLoginUI} and to annotated it with {@link SpringUI} as in
* this example to the defined {@link HawkbitTheme#LOGIN_UI_PATH}.
*
*
*
*/
@SpringUI(path = HawkbitTheme.LOGIN_UI_PATH)
// Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from
// Vaadin.
@SuppressWarnings({ "squid:MaximumInheritanceDepth" })
public class MyLoginUI extends HawkbitLoginUI {
private static final long serialVersionUID = 1L;

View File

@@ -29,6 +29,9 @@ import com.vaadin.spring.annotation.SpringUI;
*/
@SpringUI
@Push(value = PushMode.AUTOMATIC, transport = Transport.WEBSOCKET)
// Exception squid:MaximumInheritanceDepth - Most of the inheritance comes from
// Vaadin.
@SuppressWarnings({ "squid:MaximumInheritanceDepth" })
public class MyUI extends HawkbitUI {
private static final long serialVersionUID = 1L;

View File

@@ -10,8 +10,8 @@ package org.eclipse.hawkbit.app;
import org.eclipse.hawkbit.RepositoryApplicationConfiguration;
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;
@@ -24,8 +24,8 @@ import org.springframework.context.annotation.Import;
@SpringBootApplication
@Import({ RepositoryApplicationConfiguration.class })
@EnableHawkbitManagedSecurityConfiguration
@EnableRestResources
@EnableDirectDeviceApi
@EnableMgmtApi
@EnableDdiApi
// Exception squid:S1118 - Spring boot standard behavior
@SuppressWarnings({ "squid:S1118" })
public class Start {

View File

@@ -0,0 +1,32 @@
#
# 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
#
# This profile adds basic configurations for a MySQL DB usage.
# Keep in mind that you need the MariaDB driver in your classpath on compile.
# see https://github.com/eclipse/hawkbit/wiki/Run-hawkBit
spring.jpa.database=MYSQL
spring.datasource.url=jdbc:mysql://localhost:3306/hawkbit
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driverClassName=org.mariadb.jdbc.Driver
spring.datasource.max-active=100
spring.datasource.max-idle=10
spring.datasource.min-idle=10
spring.datasource.initial-size=10
spring.datasource.validation-query=select 1 from dual
spring.datasource.validation-interval=30000
spring.datasource.test-on-borrow=true
spring.datasource.test-on-return=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=30000
spring.datasource.min-evictable-idle-time-millis=60000
spring.datasource.max-wait=10000
spring.datasource.jmx-enabled=true

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

View 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
```

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

View File

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

View File

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

View File

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

View 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
```

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

View File

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

View File

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

View 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
```

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,36 @@
/**
* 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 {
@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);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,19 +11,23 @@ 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 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 DistributionSetRequestBodyPost}.
* 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
@@ -35,6 +39,13 @@ public class DistributionSetBuilder {
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
@@ -56,28 +67,38 @@ public class DistributionSetBuilder {
}
/**
* 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}
* @param description
* the description
* @return the builder itself
*/
public List<DistributionSetRequestBodyPost> build() {
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(name));
}
/**
* Builds a list of multiple {@link DistributionSetRequestBodyPost} to
* Builds a list of multiple {@link MgmtDistributionSetRequestBodyPost} 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}
* @return a list of {@link MgmtDistributionSetRequestBodyPost}
*/
public List<DistributionSetRequestBodyPost> buildAsList(final int count) {
final ArrayList<DistributionSetRequestBodyPost> bodyList = Lists.newArrayList();
public List<MgmtDistributionSetRequestBodyPost> buildAsList(final int count) {
final ArrayList<MgmtDistributionSetRequestBodyPost> bodyList = Lists.newArrayList();
for (int index = 0; index < count; index++) {
bodyList.add(doBuild(name + index));
}
@@ -85,11 +106,13 @@ public class DistributionSetBuilder {
return bodyList;
}
private DistributionSetRequestBodyPost doBuild(final String prefixName) {
final DistributionSetRequestBodyPost body = new DistributionSetRequestBodyPost();
private MgmtDistributionSetRequestBodyPost doBuild(final String prefixName) {
final MgmtDistributionSetRequestBodyPost body = new MgmtDistributionSetRequestBodyPost();
body.setName(prefixName);
body.setVersion(version);
body.setType(type);
body.setDescription(description);
body.setModules(modules);
return body;
}

View File

@@ -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,28 +94,29 @@ 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() {
public List<MgmtDistributionSetTypeRequestBodyPost> build() {
return Lists.newArrayList(doBuild(name, key));
}
/**
* 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));
}
@@ -111,10 +124,11 @@ public class DistributionSetTypeBuilder {
}
private DistributionSetTypeRequestBodyPost doBuild(final String prefixName, final String prefixKey) {
final DistributionSetTypeRequestBodyPost body = new DistributionSetTypeRequestBodyPost();
private MgmtDistributionSetTypeRequestBodyPost doBuild(final String prefixName, final String prefixKey) {
final MgmtDistributionSetTypeRequestBodyPost body = new MgmtDistributionSetTypeRequestBodyPost();
body.setKey(prefixKey);
body.setName(prefixName);
body.setDescription(description);
body.setMandatorymodules(mandatorymodules);
body.setOptionalmodules(optionalmodules);
return body;

View File

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

View File

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

View File

@@ -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.distributionsettype.DistributionSetTypeRequestBodyPost;
import org.eclipse.hawkbit.rest.resource.model.softwaremodule.SoftwareModuleRequestBodyPost;
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 SoftwareModuleRequestBodyPost}.
* Builder pattern for building {@link MgmtSoftwareModuleRequestBodyPost}.
*
*/
// Exception squid:S1701 - builder pattern
@@ -28,6 +28,8 @@ public class SoftwareModuleBuilder {
private String name;
private String version;
private String type;
private String vendor;
private String description;
/**
* @param name
@@ -61,28 +63,48 @@ public class SoftwareModuleBuilder {
}
/**
* 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}
* @param vendor
* the vendor
* @return the builder itself
*/
public List<SoftwareModuleRequestBodyPost> build() {
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(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.
* Builds a list of multiple {@link MgmtSoftwareModuleRequestBodyPost} 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}
* @return a list of {@link MgmtDistributionSetTypeRequestBodyPost}
*/
public List<SoftwareModuleRequestBodyPost> buildAsList(final int count) {
final ArrayList<SoftwareModuleRequestBodyPost> bodyList = Lists.newArrayList();
public List<MgmtSoftwareModuleRequestBodyPost> buildAsList(final int count) {
final ArrayList<MgmtSoftwareModuleRequestBodyPost> bodyList = Lists.newArrayList();
for (int index = 0; index < count; index++) {
bodyList.add(doBuild(name + index));
}
@@ -90,11 +112,13 @@ public class SoftwareModuleBuilder {
return bodyList;
}
private SoftwareModuleRequestBodyPost doBuild(final String prefixName) {
final SoftwareModuleRequestBodyPost body = new SoftwareModuleRequestBodyPost();
private MgmtSoftwareModuleRequestBodyPost doBuild(final String prefixName) {
final MgmtSoftwareModuleRequestBodyPost body = new MgmtSoftwareModuleRequestBodyPost();
body.setName(prefixName);
body.setVersion(version);
body.setType(type);
body.setVendor(vendor);
body.setDescription(description);
return body;
}

View File

@@ -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,35 +62,36 @@ 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() {
public List<MgmtSoftwareModuleTypeRequestBodyPost> build() {
return Lists.newArrayList(doBuild(key, name));
}
/**
* 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));
}
return bodyList;
}
private SoftwareModuleTypeRequestBodyPost doBuild(final String prefixKey, final String prefixName) {
final SoftwareModuleTypeRequestBodyPost body = new SoftwareModuleTypeRequestBodyPost();
private MgmtSoftwareModuleTypeRequestBodyPost doBuild(final String prefixKey, final String prefixName) {
final MgmtSoftwareModuleTypeRequestBodyPost body = new MgmtSoftwareModuleTypeRequestBodyPost();
body.setKey(prefixKey);
body.setName(prefixName);
body.setDescription(description);

View File

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

View File

@@ -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.softwaremoduletype.SoftwareModuleTypeRequestBodyPost;
import org.eclipse.hawkbit.rest.resource.model.target.TargetRequestBody;
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 TargetRequestBody}.
* Builder pattern for building {@link MgmtTargetRequestBody}.
*
*/
// Exception squid:S1701 - builder pattern
@@ -60,35 +60,35 @@ public class TargetBuilder {
}
/**
* Builds a list with a single entry of {@link TargetRequestBody} which can
* directly be used in the RESTful-API.
* 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 TargetRequestBody}
* @return a single entry list of {@link MgmtTargetRequestBody}
*/
public List<TargetRequestBody> build() {
public List<MgmtTargetRequestBody> 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.
* Builds a list of multiple {@link MgmtTargetRequestBody} 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}
* @return a list of {@link MgmtSoftwareModuleTypeRequestBodyPost}
*/
public List<TargetRequestBody> buildAsList(final int count) {
final ArrayList<TargetRequestBody> bodyList = Lists.newArrayList();
public List<MgmtTargetRequestBody> buildAsList(final int count) {
final ArrayList<MgmtTargetRequestBody> 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();
private MgmtTargetRequestBody doBuild(final String prefixControllerId) {
final MgmtTargetRequestBody body = new MgmtTargetRequestBody();
body.setControllerId(prefixControllerId);
body.setName(name);
body.setDescription(description);

View File

@@ -0,0 +1,3 @@
/target/
/bin/
/.apt_generated/

View File

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

View File

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

View File

@@ -8,22 +8,28 @@
*/
package org.eclipse.hawkbit.mgmt.client;
import org.eclipse.hawkbit.feign.core.client.FeignClientConfiguration;
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.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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import feign.Contract;
import feign.auth.BasicAuthRequestInterceptor;
@SpringBootApplication
@EnableFeignClients
@EnableConfigurationProperties(ClientConfigurationProperties.class)
@Configuration
@AutoConfigureAfter(FeignClientConfiguration.class)
@Import(FeignClientConfiguration.class)
public class Application implements CommandLineRunner {
@Autowired
@@ -57,13 +63,13 @@ public class Application implements CommandLineRunner {
}
@Bean
public ApplicationJsonRequestHeaderInterceptor jsonHeaderInterceptor() {
return new ApplicationJsonRequestHeaderInterceptor();
public GettingStartedDefaultScenario gettingStartedDefaultScenario() {
return new GettingStartedDefaultScenario();
}
@Bean
public Contract feignContract() {
return new IgnoreMultipleConsumersProducersSpringMvcContract();
public CreateStartedRolloutExample createStartedRolloutExample() {
return new CreateStartedRolloutExample();
}
private boolean containsArg(final String containsArg, final String... args) {

View File

@@ -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,18 +23,16 @@ 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;
/**
* Example for creating and starting a Rollout.
*
*/
@Component
public class CreateStartedRolloutExample {
/* known software module type name and key */
@@ -44,22 +42,22 @@ public class CreateStartedRolloutExample {
private static final String DS_MODULE_TYPE = SM_MODULE_TYPE;
@Autowired
private DistributionSetResourceClient distributionSetResource;
private MgmtDistributionSetClientResource distributionSetResource;
@Autowired
private SoftwareModuleResourceClient softwareModuleResource;
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 +65,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 +76,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 +95,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())

View File

@@ -10,29 +10,27 @@ 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.MgmtDistributionSetClientResource;
import org.eclipse.hawkbit.mgmt.client.resource.MgmtDistributionSetTypeClientResource;
import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleClientResource;
import org.eclipse.hawkbit.mgmt.client.resource.MgmtSoftwareModuleTypeClientResource;
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.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType;
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);
@@ -50,16 +48,16 @@ public class GettingStartedDefaultScenario {
private static final String DS_EXAMPLE_NAME = SM_EXAMPLE_NAME;
@Autowired
private DistributionSetResourceClient distributionSetResource;
private MgmtDistributionSetClientResource distributionSetResource;
@Autowired
private DistributionSetTypeResourceClient distributionSetTypeResource;
private MgmtDistributionSetTypeClientResource distributionSetTypeResource;
@Autowired
private SoftwareModuleResourceClient softwareModuleResource;
private MgmtSoftwareModuleClientResource softwareModuleResource;
@Autowired
private SoftwareModuleTypeResourceClient softwareModuleTypeResource;
private MgmtSoftwareModuleTypeClientResource softwareModuleTypeResource;
/**
* Run the default getting started scenario.
@@ -70,7 +68,7 @@ public class GettingStartedDefaultScenario {
// create one SoftwareModuleTypes
LOGGER.info("Creating software module type {}", SM_MODULE_TYPE);
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();
@@ -86,17 +84,17 @@ public class GettingStartedDefaultScenario {
final String dsVersion3 = "2.1.0";
LOGGER.info("Creating distribution set {}:{}", DS_EXAMPLE_NAME, dsVersion1);
final List<DistributionSetRest> distributionSetsRest1 = distributionSetResource.createDistributionSets(
final List<MgmtDistributionSet> 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(
final List<MgmtDistributionSet> 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(
final List<MgmtDistributionSet> distributionSetsRest3 = distributionSetResource.createDistributionSets(
new DistributionSetBuilder().name(DS_EXAMPLE_NAME).version(dsVersion3).type(DS_MODULE_TYPE).build())
.getBody();
@@ -106,15 +104,15 @@ public class GettingStartedDefaultScenario {
final String swVersion3 = "3";
LOGGER.info("Creating distribution set {}:{}", SM_EXAMPLE_NAME, swVersion1);
final List<SoftwareModuleRest> softwareModulesRest1 = softwareModuleResource.createSoftwareModules(
final List<MgmtSoftwareModule> 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(
final List<MgmtSoftwareModule> 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(
final List<MgmtSoftwareModule> softwareModulesRest3 = softwareModuleResource.createSoftwareModules(
new SoftwareModuleBuilder().name(SM_EXAMPLE_NAME).version(swVersion3).type(SM_MODULE_TYPE).build())
.getBody();

View File

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

View File

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

View File

@@ -26,10 +26,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;
@@ -292,8 +292,9 @@ public class SecurityManagedConfiguration {
new AuthenticationSuccessTenantMetadataCreationFilter(tenantAware, systemManagement),
RequestHeaderAuthenticationFilter.class)
.authorizeRequests().anyRequest().authenticated()
.antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN).antMatchers(RestConstants.BASE_SYSTEM_MAPPING + "/**")
.antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/admin/**")
.hasAnyAuthority(SpPermission.SYSTEM_ADMIN)
.antMatchers(MgmtRestConstants.BASE_SYSTEM_MAPPING + "/**")
.hasAnyAuthority(SpPermission.SYSTEM_DIAG);
}
}

View File

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

View File

@@ -17,6 +17,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties("hawkbit.artifact.url")
public class ArtifactUrlHandlerProperties {
private static final String DEFAULT_IP_LOCALHOST = "127.0.0.1";
private static final String DEFAULT_PORT = "8080";
private static final String LOCALHOST = "localhost";
private final Http http = new Http();
@@ -92,7 +93,7 @@ public class ArtifactUrlHandlerProperties {
public static class Http implements ProtocolProperties {
private String hostname = LOCALHOST;
private String ip = DEFAULT_IP_LOCALHOST;
private String port = "";
private String port = DEFAULT_PORT;
/**
* An ant-URL pattern with placeholder to build the URL on. The URL can
* have specific artifact placeholder.
@@ -156,7 +157,7 @@ public class ArtifactUrlHandlerProperties {
public static class Https implements ProtocolProperties {
private String hostname = LOCALHOST;
private String ip = DEFAULT_IP_LOCALHOST;
private String port = "";
private String port = DEFAULT_PORT;
/**
* An ant-URL pattern with placeholder to build the URL on. The URL can
* have specific artifact placeholder.

View File

@@ -61,7 +61,7 @@ public class PropertyBasedArtifactUrlHandler implements ArtifactUrlHandler {
for (final Entry<String, String> entry : entrySet) {
if (entry.getKey().equals(PORT_PLACEHOLDER)) {
urlPattern = urlPattern.replace(":{" + entry.getKey() + "}",
Strings.isNullOrEmpty(entry.getValue()) ? "" : ":" + entry.getValue());
Strings.isNullOrEmpty(entry.getValue()) ? "" : (":" + entry.getValue()));
} else {
urlPattern = urlPattern.replace("{" + entry.getKey() + "}", entry.getValue());
}

12
hawkbit-ddi-api/README.md Normal file
View File

@@ -0,0 +1,12 @@
# Eclipse.IoT hawkBit - DDI API
The Direct Device Integration (DDI) API is used by devices for communicating with the HawkBit Update Server through HTTP.
# Compile
#### Build hawkbit-ddi-api
```
$ cd hawkbit/hawkbit-ddi-api
$ mvn clean install
```

45
hawkbit-ddi-api/pom.xml Normal file
View File

@@ -0,0 +1,45 @@
<!--
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-parent</artifactId>
<version>0.2.0-SNAPSHOT</version>
</parent>
<artifactId>hawkbit-ddi-api</artifactId>
<name>hawkBit :: DDI API</name>
<dependencies>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import javax.validation.constraints.NotNull;
@@ -15,16 +15,16 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
*
* <p>
* After the SP Target has executed an action, received by a GET(URL) request it
* reports the completion of it to the SP Server with a action status message,
* i.e. with a PUT message to the feedback channel, i.e. PUT URL/feedback. This
* message could be used not only at the end of execution but also as status
* updates during a longer lasting execution period. The format of each action
* answer message is defined below at each action. But it is expected, that the
* contents of the message answers have all a similar structure: The content
* starts with a generic header and additional elements. *
* After the HawkBit Target has executed an action, received by a GET(URL)
* request it reports the completion of it to the HawkBit Server with a action
* status message, i.e. with a PUT message to the feedback channel, i.e. PUT
* URL/feedback. This message could be used not only at the end of execution but
* also as status updates during a longer lasting execution period. The format
* of each action answer message is defined below at each action. But it is
* expected, that the contents of the message answers have all a similar
* structure: The content starts with a generic header and additional elements.
* *
* </p>
*
* <p>
@@ -35,12 +35,12 @@ import com.fasterxml.jackson.annotation.JsonProperty;
*
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class ActionFeedback {
public class DdiActionFeedback {
private final Long id;
private final String time;
@NotNull
private final Status status;
private final DdiStatus status;
/**
* Constructor.
@@ -53,8 +53,8 @@ public class ActionFeedback {
* is the feedback itself
*/
@JsonCreator
public ActionFeedback(@JsonProperty("id") final Long id, @JsonProperty("time") final String time,
@JsonProperty("status") final Status status) {
public DdiActionFeedback(@JsonProperty("id") final Long id, @JsonProperty("time") final String time,
@JsonProperty("status") final DdiStatus status) {
this.id = id;
this.time = time;
this.status = status;
@@ -68,15 +68,10 @@ public class ActionFeedback {
return time;
}
public Status getStatus() {
public DdiStatus getStatus() {
return status;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "ActionFeedback [id=" + id + ", time=" + time + ", status=" + status + "]";

View File

@@ -6,72 +6,50 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactHash;
import org.springframework.hateoas.ResourceSupport;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Download information for all artifacts related to a specific {@link Chunk}.
*
* Download information for all artifacts related to a specific {@link DdiChunk}
* .
*/
public class Artifact extends ResourceSupport {
public class DdiArtifact extends ResourceSupport {
@NotNull
@JsonProperty
private String filename;
@JsonProperty
private ArtifactHash hashes;
private DdiArtifactHash hashes;
@JsonProperty
private Long size;
/**
* @return the hashes
*/
public ArtifactHash getHashes() {
public DdiArtifactHash getHashes() {
return hashes;
}
/**
* @param hashes
* the hashes to set
*/
public void setHashes(final ArtifactHash hashes) {
public void setHashes(final DdiArtifactHash hashes) {
this.hashes = hashes;
}
/**
* @return the fileName
*/
public String getFilename() {
return filename;
}
/**
* @param fileName
* the fileName to set
*/
public void setFilename(final String fileName) {
filename = fileName;
}
/**
* @return the size
*/
public Long getSize() {
return size;
}
/**
* @param size
* the size to set
*/
public void setSize(final Long size) {
this.size = size;
}

View File

@@ -0,0 +1,57 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.json.model;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Hashes for given Artifact.
*
*
*/
public class DdiArtifactHash {
@JsonProperty
private String sha1;
@JsonProperty
private String md5;
/**
* Default constructor.
*/
public DdiArtifactHash() {
}
/**
* Public constructor.
*
* @param sha1
* @param md5
*/
public DdiArtifactHash(final String sha1, final String md5) {
this.sha1 = sha1;
this.md5 = md5;
}
/**
* @return the sha1
*/
public String getSha1() {
return sha1;
}
/**
* @return the md5
*/
public String getMd5() {
return md5;
}
}

View File

@@ -6,53 +6,42 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import javax.validation.constraints.NotNull;
/**
* Cancel action to be provided to the target.
*
*/
public class Cancel {
public class DdiCancel {
private final String id;
@NotNull
private final CancelActionToStop cancelAction;
private final DdiCancelActionToStop cancelAction;
/**
* Parameterized constructor.
*
* @param id
* of the {@link CancelAction}
* of the cancel action
* @param cancelAction
* the action
*/
public Cancel(final String id, final CancelActionToStop cancelAction) {
public DdiCancel(final String id, final DdiCancelActionToStop cancelAction) {
super();
this.id = id;
this.cancelAction = cancelAction;
}
/**
* @return the id
*/
public String getId() {
return id;
}
/**
* @return the cancelAction
*/
public CancelActionToStop getCancelAction() {
public DdiCancelActionToStop getCancelAction() {
return cancelAction;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Cancel [id=" + id + ", cancelAction=" + cancelAction + "]";

View File

@@ -6,17 +6,14 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import javax.validation.constraints.NotNull;
import org.eclipse.hawkbit.repository.model.Action;
/**
* The {@link Action} that has to be stopped by the target.
*
* The action that has to be stopped by the target.
*/
public class CancelActionToStop {
public class DdiCancelActionToStop {
@NotNull
private final String stopId;
@@ -25,25 +22,17 @@ public class CancelActionToStop {
* Parameterized constructor.
*
* @param stopId
* ID of the {@link Action} to be stoppedW
* ID of the action to be stoppedW
*/
public CancelActionToStop(final String stopId) {
public DdiCancelActionToStop(final String stopId) {
super();
this.stopId = stopId;
}
/**
* @return the stopId
*/
public String getStopId() {
return stopId;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "CancelAction [stopId=" + stopId + "]";

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import java.util.List;
@@ -14,20 +14,23 @@ import javax.validation.constraints.NotNull;
/**
* Deployment chunks.
*
*/
public class Chunk {
public class DdiChunk {
@NotNull
private final String part;
private String part;
@NotNull
private final String version;
private String version;
@NotNull
private final String name;
private String name;
private final List<Artifact> artifacts;
private List<DdiArtifact> artifacts;
public DdiChunk() {
}
/**
* Constructor.
@@ -40,9 +43,8 @@ public class Chunk {
* of the artifact
* @param artifacts
* download information
*
*/
public Chunk(final String part, final String version, final String name, final List<Artifact> artifacts) {
public DdiChunk(final String part, final String version, final String name, final List<DdiArtifact> artifacts) {
super();
this.part = part;
this.version = version;
@@ -58,17 +60,11 @@ public class Chunk {
return version;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the artifacts
*/
public List<Artifact> getArtifacts() {
public List<DdiArtifact> getArtifacts() {
return artifacts;
}

View File

@@ -6,15 +6,22 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Standard configuration for the target.
*
*/
public class Config {
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class DdiConfig {
private final Polling polling;
@JsonProperty
private DdiPolling polling;
/**
* Constructor.
@@ -22,12 +29,16 @@ public class Config {
* @param polling
* configuration of the SP target
*/
public Config(final Polling polling) {
public DdiConfig(final DdiPolling polling) {
super();
this.polling = polling;
}
public Polling getPolling() {
public DdiConfig() {
}
public DdiPolling getPolling() {
return polling;
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import java.util.Map;
@@ -17,9 +17,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Feedback channel for ConfigData action.
*
*/
public class ConfigData extends ActionFeedback {
public class DdiConfigData extends DdiActionFeedback {
@NotEmpty
private final Map<String, String> data;
@@ -35,28 +34,19 @@ public class ConfigData extends ActionFeedback {
* is the feedback itself
* @param data
* contains the attributes.
*
*/
@JsonCreator
public ConfigData(@JsonProperty(value = "id") final Long id, @JsonProperty(value = "time") final String time,
@JsonProperty(value = "status") final Status status,
public DdiConfigData(@JsonProperty(value = "id") final Long id, @JsonProperty(value = "time") final String time,
@JsonProperty(value = "status") final DdiStatus status,
@JsonProperty(value = "data") final Map<String, String> data) {
super(id, time, status);
this.data = data;
}
/**
* @return the data
*/
public Map<String, String> getData() {
return data;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "ConfigData [data=" + data + ", toString()=" + super.toString() + "]";

View File

@@ -0,0 +1,47 @@
/**
* 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.json.model;
import org.springframework.hateoas.ResourceSupport;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {@link DdiControllerBase} resource content.
*/
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class DdiControllerBase extends ResourceSupport {
@JsonProperty
private DdiConfig config;
/**
* Constructor.
*
* @param config
* configuration of the SP target
*/
public DdiControllerBase(final DdiConfig config) {
super();
this.config = config;
}
public DdiControllerBase() {
}
public DdiConfig getConfig() {
return config;
}
}

View File

@@ -6,25 +6,26 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import java.util.List;
import org.eclipse.hawkbit.repository.model.Action;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* Detailed {@link UpdateAction} information.
*
* Detailed update action information.
*/
public class Deployment {
public class DdiDeployment {
private final HandlingType download;
private HandlingType download;
private final HandlingType update;
private HandlingType update;
private final List<Chunk> chunks;
private List<DdiChunk> chunks;
public DdiDeployment() {
}
/**
* Constructor.
@@ -36,7 +37,7 @@ public class Deployment {
* @param chunks
* to handle.
*/
public Deployment(final HandlingType download, final HandlingType update, final List<Chunk> chunks) {
public DdiDeployment(final HandlingType download, final HandlingType update, final List<DdiChunk> chunks) {
super();
this.download = download;
this.update = update;
@@ -51,15 +52,15 @@ public class Deployment {
return update;
}
public List<Chunk> getChunks() {
public List<DdiChunk> getChunks() {
return chunks;
}
/**
* The handling type for the update {@link Action}.
*
* The handling type for the update action.
*/
public enum HandlingType {
/**
* Not necessary for the command.
*/
@@ -81,20 +82,12 @@ public class Deployment {
this.name = name;
}
/**
* @return the name
*/
@JsonValue
public String getName() {
return name;
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Deployment [download=" + download + ", update=" + update + ", chunks=" + chunks + "]";

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import javax.validation.constraints.NotNull;
@@ -15,40 +15,38 @@ import org.springframework.hateoas.ResourceSupport;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* {@link UpdateAction} resource.
*
* Update action resource.
*/
public class DeploymentBase extends ResourceSupport {
public class DdiDeploymentBase extends ResourceSupport {
@JsonProperty("id")
@NotNull
private final String deplyomentId;
private String deplyomentId;
@NotNull
private final Deployment deployment;
private DdiDeployment deployment;
/**
* Constructor.
*
* @param id
* of the {@link UpdateAction}
* of the update action
* @param deployment
* details.
*/
public DeploymentBase(final String id, final Deployment deployment) {
public DdiDeploymentBase(final String id, final DdiDeployment deployment) {
deplyomentId = id;
this.deployment = deployment;
}
public Deployment getDeployment() {
public DdiDeploymentBase() {
}
public DdiDeployment getDeployment() {
return deployment;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "DeploymentBase [id=" + deplyomentId + ", deployment=" + deployment + "]";

View File

@@ -6,15 +6,22 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Polling interval for the SP target.
*
*/
public class Polling {
@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class DdiPolling {
private final String sleep;
@JsonProperty
private String sleep;
/**
* Constructor.
@@ -22,11 +29,14 @@ public class Polling {
* @param sleep
* between polls
*/
public Polling(final String sleep) {
public DdiPolling(final String sleep) {
super();
this.sleep = sleep;
}
public DdiPolling() {
}
public String getSleep() {
return sleep;
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import javax.validation.constraints.NotNull;
@@ -16,9 +16,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
/**
* Action fulfillment progress by means of gives the achieved amount of maximal
* of possible levels.
*
*/
public class Progress {
public class DdiProgress {
@NotNull
private final Integer cnt;
@@ -34,7 +33,7 @@ public class Progress {
* maximum levels
*/
@JsonCreator
public Progress(@JsonProperty("cnt") final Integer cnt, @JsonProperty("of") final Integer of) {
public DdiProgress(@JsonProperty("cnt") final Integer cnt, @JsonProperty("of") final Integer of) {
super();
this.cnt = cnt;
this.of = of;
@@ -48,11 +47,6 @@ public class Progress {
return of;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Progress [cnt=" + cnt + ", of=" + of + "]";

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import org.hibernate.validator.constraints.NotEmpty;
@@ -17,15 +17,13 @@ import com.fasterxml.jackson.annotation.JsonValue;
/**
* Result information of the action progress which can by an intermediate or
* final update.
*
*
*/
public class Result {
public class DdiResult {
@NotEmpty
private final FinalResult finished;
private final Progress progress;
private final DdiProgress progress;
/**
* Constructor.
@@ -36,8 +34,8 @@ public class Result {
* if not yet finished
*/
@JsonCreator
public Result(@JsonProperty("finished") final FinalResult finished,
@JsonProperty("progress") final Progress progress) {
public DdiResult(@JsonProperty("finished") final FinalResult finished,
@JsonProperty("progress") final DdiProgress progress) {
super();
this.finished = finished;
this.progress = progress;
@@ -47,7 +45,7 @@ public class Result {
return finished;
}
public Progress getProgress() {
public DdiProgress getProgress() {
return progress;
}
@@ -77,21 +75,12 @@ public class Result {
this.name = name;
}
/**
* @return the name
*/
@JsonValue
public String getName() {
return name;
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Result [finished=" + finished + ", progress=" + progress + "]";

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller.model;
package org.eclipse.hawkbit.ddi.json.model;
import java.util.List;
@@ -18,15 +18,14 @@ import com.fasterxml.jackson.annotation.JsonValue;
/**
* Details status information concerning the action processing.
*
*/
public class Status {
public class DdiStatus {
@NotNull
private final ExecutionStatus execution;
@NotNull
private final Result result;
private final DdiResult result;
private final List<String> details;
@@ -41,8 +40,8 @@ public class Status {
* as optional addition
*/
@JsonCreator
public Status(@JsonProperty("execution") final ExecutionStatus execution,
@JsonProperty("result") final Result result, @JsonProperty("details") final List<String> details) {
public DdiStatus(@JsonProperty("execution") final ExecutionStatus execution,
@JsonProperty("result") final DdiResult result, @JsonProperty("details") final List<String> details) {
super();
this.execution = execution;
this.result = result;
@@ -53,7 +52,7 @@ public class Status {
return execution;
}
public Result getResult() {
public DdiResult getResult() {
return result;
}
@@ -103,20 +102,12 @@ public class Status {
this.name = name;
}
/**
* @return the name
*/
@JsonValue
public String getName() {
return name;
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Status [execution=" + execution + ", result=" + result + ", details=" + details + "]";

View File

@@ -6,24 +6,18 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.api;
/**
*
*
*
* Constants for the direct device integration rest resources.
*/
public final class ControllerConstants {
public final class DdiRestConstants {
/**
* The base URL mapping of the direct device integration rest resources.
*/
public static final String BASE_V1_REQUEST_MAPPING = "/{tenant}/controller/v1";
/**
* The base URL mapping of the artifact repository rest resources.
*/
public static final String ARTIFACTS_V1_REQUEST_MAPPING = "/{tenant}/controller/artifacts/v1";
/**
* Deployment action resources.
*/
@@ -37,30 +31,19 @@ public final class ControllerConstants {
/**
* Feedback channel.
*/
static final String FEEDBACK = "feedback";
public static final String FEEDBACK = "feedback";
/**
* File suffix for MDH hash download (see Linux md5sum).
*/
public static final String ARTIFACT_MD5_DWNL_SUFFIX = ".MD5SUM";
/**
* Config data action resources.
*/
public static final String CONFIG_DATA_ACTION = "configData";
/**
* The artifact URL mapping rest resource.
*/
static final String ARTIFACT_DOWNLOAD = "artifact";
/**
* The artifact by filename URL mapping rest resource.
*/
static final String ARTIFACT_DOWNLOAD_BY_FILENAME = "/filename";
/**
* File suffix for MDH hash download (see Linux md5sum).
*/
static final String ARTIFACT_MD5_DWNL_SUFFIX = ".MD5SUM";
// constant class, private constructor.
private ControllerConstants() {
private DdiRestConstants() {
// constant class, private constructor.
}
}

View File

@@ -0,0 +1,212 @@
/**
* 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.rest.api;
import java.io.InputStream;
import java.lang.annotation.Target;
import java.util.List;
import javax.validation.Valid;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiCancel;
import org.eclipse.hawkbit.ddi.json.model.DdiConfigData;
import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase;
import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase;
import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* REST resource handling for root controller CRUD operations.
*/
@RequestMapping(DdiRestConstants.BASE_V1_REQUEST_MAPPING)
public interface DdiRootControllerRestApi {
/**
* Returns all artifacts of a given software module and target.
*
* @param targetid
* of the target that matches to controller id
* @param softwareModuleId
* of the software module
* @return the response
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}/softwaremodules/{softwareModuleId}/artifacts", produces = {
"application/hal+json", MediaType.APPLICATION_JSON_VALUE })
ResponseEntity<List<org.eclipse.hawkbit.ddi.json.model.DdiArtifact>> getSoftwareModulesArtifacts(
@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId);
/**
* Root resource for an individual {@link Target}.
*
* @param targetid
* of the target that matches to controller id
* @param request
* the HTTP request injected by spring
* @return the response
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}", produces = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE })
ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("targetid") final String targetid);
/**
* Handles GET {@link DdiArtifact} download request. This could be full or
* partial (as specified by RFC7233 (Range Requests)) download request.
*
* @param targetid
* of the related target
* @param softwareModuleId
* of the parent software module
* @param fileName
* of the related local artifact
* @param response
* of the servlet
* @param request
* from the client
*
* @return response of the servlet which in case of success is status code
* {@link HttpStatus#OK} or in case of partial download
* {@link HttpStatus#PARTIAL_CONTENT}.
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}/softwaremodules/{softwareModuleId}/artifacts/{fileName}")
ResponseEntity<InputStream> downloadArtifact(@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("fileName") final String fileName);
/**
* Handles GET {@link DdiArtifact} MD5 checksum file download request.
*
* @param targetid
* of the related target
* @param softwareModuleId
* of the parent software module
* @param fileName
* of the related local artifact
* @param response
* of the servlet
* @param request
* the HTTP request injected by spring
*
* @return {@link ResponseEntity} with status {@link HttpStatus#OK} if
* successful
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}/softwaremodules/{softwareModuleId}/artifacts/{fileName}"
+ DdiRestConstants.ARTIFACT_MD5_DWNL_SUFFIX, produces = MediaType.TEXT_PLAIN_VALUE)
ResponseEntity<Void> downloadArtifactMd5(@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("fileName") final String fileName);
/**
* Resource for software module.
*
* @param targetid
* of the target that matches to controller id
* @param actionId
* of the {@link DdiDeploymentBase} that matches to active
* actions.
* @param resource
* an hashcode of the resource which indicates if the action has
* been changed, e.g. from 'soft' to 'force' and the eTag needs
* to be re-generated
* @param request
* the HTTP request injected by spring
* @return the response
*/
@RequestMapping(value = "/{targetid}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION
+ "/{actionId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<DdiDeploymentBase> getControllerBasedeploymentAction(
@PathVariable("targetid") @NotEmpty final String targetid,
@PathVariable("actionId") @NotEmpty final Long actionId,
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource);
/**
* This is the feedback channel for the {@link DdiDeploymentBase} action.
*
* @param feedback
* to provide
* @param targetid
* of the target that matches to controller id
* @param actionId
* of the action we have feedback for
* @param request
* the HTTP request injected by spring
*
* @return the response
*/
@RequestMapping(value = "/{targetid}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}/"
+ DdiRestConstants.FEEDBACK, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<Void> postBasedeploymentActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
@PathVariable("targetid") final String targetid, @PathVariable("actionId") @NotEmpty final Long actionId);
/**
* This is the feedback channel for the config data action.
*
* @param configData
* as body
* @param targetid
* to provide data for
* @param request
* the HTTP request injected by spring
*
* @return status of the request
*/
@RequestMapping(value = "/{targetid}/"
+ DdiRestConstants.CONFIG_DATA_ACTION, method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
@PathVariable("targetid") final String targetid);
/**
* RequestMethod.GET method for the {@link DdiCancel} action.
*
* @param targetid
* ID of the calling target
* @param actionId
* of the action
* @param request
* the HTTP request injected by spring
*
* @return the {@link DdiCancel} response
*/
@RequestMapping(value = "/{targetid}/" + DdiRestConstants.CANCEL_ACTION
+ "/{actionId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<DdiCancel> getControllerCancelAction(@PathVariable("targetid") @NotEmpty final String targetid,
@PathVariable("actionId") @NotEmpty final Long actionId);
/**
* RequestMethod.POST method receiving the {@link DdiActionFeedback} from
* the target.
*
* @param feedback
* the {@link DdiActionFeedback} from the target.
* @param targetid
* the ID of the calling target
* @param actionId
* of the action we have feedback for
* @param request
* the HTTP request injected by spring
*
* @return the {@link DdiActionFeedback} response
*/
@RequestMapping(value = "/{targetid}/" + DdiRestConstants.CANCEL_ACTION + "/{actionId}/"
+ DdiRestConstants.FEEDBACK, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
ResponseEntity<Void> postCancelActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
@PathVariable("targetid") @NotEmpty final String targetid,
@PathVariable("actionId") @NotEmpty final Long actionId);
}

View File

@@ -0,0 +1,12 @@
# Eclipse.IoT hawkBit - DDI Download API
This module is part of the Direct Device Integration (DDI) API and is used by devices/targets for downloading artifacts through HTTP.
# Compile
#### Build hawkbit-ddi-dl-api
```
$ cd hawkbit/hawkbit-ddi-dl-api
$ mvn clean install
```

View File

@@ -0,0 +1,28 @@
<!--
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-parent</artifactId>
<version>0.2.0-SNAPSHOT</version>
</parent>
<artifactId>hawkbit-ddi-dl-api</artifactId>
<name>hawkBit :: DDI Download Server (DL) API</name>
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,59 @@
/**
* 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.dl.rest.api;
import java.io.InputStream;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
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.ResponseBody;
/**
* REST resource handling for artifact download operations.
*/
@RequestMapping(DdiDlRestConstants.ARTIFACTS_V1_REQUEST_MAPPING)
public interface DdiDlArtifactStoreControllerRestApi {
/**
* Handles GET download request. This could be full or partial download
* request.
*
* @param fileName
* to search for
* @param targetid
* of authenticated target
*
* @return response of the servlet which in case of success is status code
* {@link HttpStatus#OK} or in case of partial download
* {@link HttpStatus#PARTIAL_CONTENT}.
*/
@RequestMapping(method = RequestMethod.GET, value = DdiDlRestConstants.ARTIFACT_DOWNLOAD_BY_FILENAME
+ "/{fileName}")
@ResponseBody
public ResponseEntity<InputStream> downloadArtifactByFilename(@PathVariable("fileName") final String fileName,
@AuthenticationPrincipal final String targetid);
/**
* Handles GET MD5 checksum file download request.
*
* @param fileName
* to search for
*
* @return response of the servlet
*/
@RequestMapping(method = RequestMethod.GET, value = DdiDlRestConstants.ARTIFACT_DOWNLOAD_BY_FILENAME + "/{fileName}"
+ DdiDlRestConstants.ARTIFACT_MD5_DWNL_SUFFIX)
@ResponseBody
public ResponseEntity<Void> downloadArtifactMD5ByFilename(@PathVariable("fileName") final String fileName);
}

View File

@@ -0,0 +1,40 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ddi.dl.rest.api;
/**
* Constants for the direct device integration rest resources.
*/
public final class DdiDlRestConstants {
/**
* The base URL mapping of the artifact repository rest resources.
*/
public static final String ARTIFACTS_V1_REQUEST_MAPPING = "/{tenant}/controller/artifacts/v1";
/**
* The artifact URL mapping rest resource.
*/
public static final String ARTIFACT_DOWNLOAD = "artifact";
/**
* The artifact by filename URL mapping rest resource.
*/
public static final String ARTIFACT_DOWNLOAD_BY_FILENAME = "/filename";
/**
* File suffix for MDH hash download (see Linux md5sum).
*/
public static final String ARTIFACT_MD5_DWNL_SUFFIX = ".MD5SUM";
// constant class, private constructor.
private DdiDlRestConstants() {
}
}

View File

@@ -0,0 +1,13 @@
# Eclipse.IoT hawkBit - DDI Resource
This is the server-side implementation of the hawkBit DDI API and the hawkBit DDI Download API that is used by devices for communicating with the HawkBit Update Server through HTTP.
# Compile
#### Build hawkbit-ddi-resource
```
$ cd hawkbit/hawkbit-ddi-resource
$ mvn clean install
```

View File

@@ -0,0 +1,163 @@
<!--
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-parent</artifactId>
<version>0.2.0-SNAPSHOT</version>
</parent>
<artifactId>hawkbit-ddi-resource</artifactId>
<name>hawkBit :: DDI Resources</name>
<dependencies>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-ddi-api</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-rest-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.plugin</groupId>
<artifactId>spring-plugin-core</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-rest-core</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-repository</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-http-security</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>de.flapdoodle.embed</groupId>
<artifactId>de.flapdoodle.embed.mongo</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ru.yandex.qatools.allure</groupId>
<artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -6,28 +6,28 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.eclipse.hawkbit.rest.configuration.RestConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Controller;
/**
* Annotation to enable {@link ComponentScan} in the resource package to setup
* all {@link Controller} annotated classes and setup the Direct Device API.
*
*
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration
@ComponentScan
public @interface EnableDirectDeviceApi {
@Import(RestConfiguration.class)
public @interface EnableDdiApi {
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
@@ -20,23 +20,25 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
import org.eclipse.hawkbit.api.UrlProtocol;
import org.eclipse.hawkbit.controller.model.Artifact;
import org.eclipse.hawkbit.controller.model.Chunk;
import org.eclipse.hawkbit.controller.model.Config;
import org.eclipse.hawkbit.controller.model.ControllerBase;
import org.eclipse.hawkbit.controller.model.Polling;
import org.eclipse.hawkbit.ddi.dl.rest.api.DdiDlRestConstants;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifactHash;
import org.eclipse.hawkbit.ddi.json.model.DdiChunk;
import org.eclipse.hawkbit.ddi.json.model.DdiConfig;
import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase;
import org.eclipse.hawkbit.ddi.json.model.DdiPolling;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.resource.model.artifact.ArtifactHash;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.hateoas.Link;
import com.google.common.base.Charsets;
/**
* Utility class for the Controller API.
* Utility class for the DDI API.
*/
public final class DataConversionHelper {
// utility class, private constructor.
@@ -44,12 +46,13 @@ public final class DataConversionHelper {
}
static List<Chunk> createChunks(final String targetid, final Action uAction,
static List<DdiChunk> createChunks(final String targetid, final Action uAction,
final ArtifactUrlHandler artifactUrlHandler) {
return uAction.getDistributionSet().getModules().stream()
.map(module -> new Chunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
.map(module -> new DdiChunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
module.getName(), createArtifacts(targetid, module, artifactUrlHandler)))
.collect(Collectors.toList());
}
private static String mapChunkLegacyKeys(final String key) {
@@ -70,22 +73,22 @@ public final class DataConversionHelper {
* of the target
* @param module
* the software module
*
* @return a list of artifacts or a empty list. Cannot be <null>.
*/
public static List<Artifact> createArtifacts(final String targetid,
public static List<DdiArtifact> createArtifacts(final String targetid,
final org.eclipse.hawkbit.repository.model.SoftwareModule module,
final ArtifactUrlHandler artifactUrlHandler) {
final List<Artifact> files = new ArrayList<>();
final List<DdiArtifact> files = new ArrayList<>();
module.getLocalArtifacts()
.forEach(artifact -> files.add(createArtifact(targetid, artifactUrlHandler, artifact)));
.forEach(artifact -> files.add(createArtifact(targetid, artifactUrlHandler, artifact)));
return files;
}
private static Artifact createArtifact(final String targetid, final ArtifactUrlHandler artifactUrlHandler,
private static DdiArtifact createArtifact(final String targetid, final ArtifactUrlHandler artifactUrlHandler,
final LocalArtifact artifact) {
final Artifact file = new Artifact();
file.setHashes(new ArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash()));
final DdiArtifact file = new DdiArtifact();
file.setHashes(new DdiArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash()));
file.setFilename(artifact.getFilename());
file.setSize(artifact.getSize());
@@ -93,21 +96,22 @@ public final class DataConversionHelper {
final String linkHttp = artifactUrlHandler.getUrl(targetid, artifact.getSoftwareModule().getId(),
artifact.getFilename(), artifact.getSha1Hash(), UrlProtocol.HTTP);
file.add(new Link(linkHttp).withRel("download-http"));
file.add(new Link(linkHttp + ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX).withRel("md5sum-http"));
file.add(new Link(linkHttp + DdiDlRestConstants.ARTIFACT_MD5_DWNL_SUFFIX).withRel("md5sum-http"));
}
if (artifactUrlHandler.protocolSupported(UrlProtocol.HTTPS)) {
final String linkHttps = artifactUrlHandler.getUrl(targetid, artifact.getSoftwareModule().getId(),
artifact.getFilename(), artifact.getSha1Hash(), UrlProtocol.HTTPS);
file.add(new Link(linkHttps).withRel("download"));
file.add(new Link(linkHttps + ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX).withRel("md5sum"));
file.add(new Link(linkHttps + DdiDlRestConstants.ARTIFACT_MD5_DWNL_SUFFIX).withRel("md5sum"));
}
return file;
}
static ControllerBase fromTarget(final Target target, final List<Action> actions,
static DdiControllerBase fromTarget(final Target target, final List<Action> actions,
final String defaultControllerPollTime, final TenantAware tenantAware) {
final ControllerBase result = new ControllerBase(new Config(new Polling(defaultControllerPollTime)));
final DdiControllerBase result = new DdiControllerBase(
new DdiConfig(new DdiPolling(defaultControllerPollTime)));
boolean addedUpdate = false;
boolean addedCancel = false;
@@ -119,21 +123,21 @@ public final class DataConversionHelper {
// have changed from 'soft' to 'forced' type and we need to
// change the payload of the
// response because of eTags.
result.add(linkTo(methodOn(RootController.class, tenantAware.getCurrentTenant())
.getControllerBasedeploymentAction(target.getControllerId(), action.getId(), actions.hashCode(),
null)).withRel(ControllerConstants.DEPLOYMENT_BASE_ACTION));
result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
.getControllerBasedeploymentAction(target.getControllerId(), action.getId(),
actions.hashCode())).withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION));
addedUpdate = true;
} else if (action.isCancelingOrCanceled() && !addedCancel) {
result.add(linkTo(methodOn(RootController.class, tenantAware.getCurrentTenant())
.getControllerCancelAction(target.getControllerId(), action.getId(), null))
.withRel(ControllerConstants.CANCEL_ACTION));
result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
.getControllerCancelAction(target.getControllerId(), action.getId()))
.withRel(DdiRestConstants.CANCEL_ACTION));
addedCancel = true;
}
}
if (target.getTargetInfo().isRequestControllerAttributes()) {
result.add(linkTo(methodOn(RootController.class, tenantAware.getCurrentTenant()).putConfigData(null,
target.getControllerId(), null)).withRel(ControllerConstants.CONFIG_DATA_ACTION));
result.add(linkTo(methodOn(DdiRootController.class, tenantAware.getCurrentTenant()).putConfigData(null,
target.getControllerId())).withRel(DdiRestConstants.CONFIG_DATA_ACTION));
}
return result;
}
@@ -149,7 +153,7 @@ public final class DataConversionHelper {
final StringBuilder header = new StringBuilder();
header.append("attachment;filename=");
header.append(fileName);
header.append(ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX);
header.append(DdiDlRestConstants.ARTIFACT_MD5_DWNL_SUFFIX);
response.setContentLength(content.length);
response.setHeader("Content-Disposition", header.toString());

View File

@@ -6,55 +6,51 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.cache.CacheWriteNotify;
import org.eclipse.hawkbit.ddi.dl.rest.api.DdiDlArtifactStoreControllerRestApi;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.eclipse.hawkbit.rest.util.RestResourceConversionHelper;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.util.IpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.web.bind.annotation.AuthenticationPrincipal;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
/**
* The {@link ArtifactStoreController} of the SP server controller API that is
* queried by the SP target in order to download artifacts independent of their
* own individual resource. This is offered in addition to the
* {@link RootController#downloadArtifact(String, Long, Long, javax.servlet.http.HttpServletResponse)}
* for legacy controllers that can not be fed with a download URI at runtime.
*
*
*
*
*
* The {@link DdiArtifactStoreController} of the HawkBit server controller API
* that is queried by the HawkBit target in order to download artifacts
* independent of their own individual resource. This is offered in addition to
* the {@link DdiRootController#downloadArtifact(String, Long, String)} for
* legacy controllers that can not be fed with a download URI at runtime.
*/
@RestController
@RequestMapping(ControllerConstants.ARTIFACTS_V1_REQUEST_MAPPING)
public class ArtifactStoreController {
private static final Logger LOG = LoggerFactory.getLogger(ArtifactStoreController.class);
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class DdiArtifactStoreController implements DdiDlArtifactStoreControllerRestApi {
private static final Logger LOG = LoggerFactory.getLogger(DdiArtifactStoreController.class);
@Autowired
private ArtifactManagement artifactManagement;
@@ -68,66 +64,71 @@ public class ArtifactStoreController {
@Autowired
private HawkbitSecurityProperties securityProperties;
/**
* Handles GET {@link Artifact} download request. This could be full or
* partial download request.
*
* @param fileName
* to search for
* @param response
* to write to
* @param request
* from the client
* @param targetid
* of authenticated target
*
* @return response of the servlet which in case of success is status code
* {@link HttpStatus#OK} or in case of partial download
* {@link HttpStatus#PARTIAL_CONTENT}.
*/
@RequestMapping(method = RequestMethod.GET, value = ControllerConstants.ARTIFACT_DOWNLOAD_BY_FILENAME
+ "/{fileName}")
@ResponseBody
public ResponseEntity<Void> downloadArtifactByFilename(@PathVariable final String fileName,
final HttpServletResponse response, final HttpServletRequest request,
@AuthenticationPrincipal final String targetid) {
ResponseEntity<Void> result;
@Autowired
private RequestResponseContextHolder requestResponseContextHolder;
@Override
public ResponseEntity<InputStream> downloadArtifactByFilename(@PathVariable("fileName") final String fileName,
@AuthenticationPrincipal final String targetid) {
final List<LocalArtifact> foundArtifacts = artifactManagement.findLocalArtifactByFilename(fileName);
if (foundArtifacts.isEmpty()) {
LOG.warn("Software artifact with name {} could not be found.", fileName);
result = new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else {
if (foundArtifacts.size() > 1) {
LOG.warn("Software artifact name {} is not unique. We will use the first entry.", fileName);
}
final LocalArtifact artifact = foundArtifacts.get(0);
final String ifMatch = request.getHeader("If-Match");
if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
} else {
final DbArtifact file = artifactManagement.loadLocalArtifactBinary(artifact);
// we set a download status only if we are aware of the
// targetid, i.e.
// authenticated and not anonymous
if (targetid != null && !"anonymous".equals(targetid)) {
final Action action = checkAndReportDownloadByTarget(request, targetid, artifact);
result = RestResourceConversionHelper.writeFileResponse(artifact, response, request, file,
cacheWriteNotify, action.getId());
} else {
result = RestResourceConversionHelper.writeFileResponse(artifact, response, request, file);
}
}
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
if (foundArtifacts.size() > 1) {
LOG.warn("Software artifact name {} is not unique. We will use the first entry.", fileName);
}
ResponseEntity<InputStream> result;
final LocalArtifact artifact = foundArtifacts.get(0);
final String ifMatch = requestResponseContextHolder.getHttpServletRequest().getHeader("If-Match");
if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
} else {
final DbArtifact file = artifactManagement.loadLocalArtifactBinary(artifact);
// we set a download status only if we are aware of the
// targetid, i.e. authenticated and not anonymous
if (targetid != null && !"anonymous".equals(targetid)) {
final Action action = checkAndReportDownloadByTarget(
requestResponseContextHolder.getHttpServletRequest(), targetid, artifact);
result = RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(),
requestResponseContextHolder.getHttpServletRequest(), file, cacheWriteNotify, action.getId());
} else {
result = RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(),
requestResponseContextHolder.getHttpServletRequest(), file);
}
}
return result;
}
@Override
public ResponseEntity<Void> downloadArtifactMD5ByFilename(@PathVariable("fileName") final String fileName) {
final List<LocalArtifact> foundArtifacts = artifactManagement.findLocalArtifactByFilename(fileName);
if (foundArtifacts.isEmpty()) {
LOG.warn("Softeare artifact with name {} could not be found.", fileName);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else if (foundArtifacts.size() > 1) {
LOG.error("Softeare artifact name {} is not unique.", fileName);
}
try {
DataConversionHelper.writeMD5FileResponse(fileName, requestResponseContextHolder.getHttpServletResponse(),
foundArtifacts.get(0));
} catch (final IOException e) {
LOG.error("Failed to stream MD5 File", e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(HttpStatus.OK);
}
private Action checkAndReportDownloadByTarget(final HttpServletRequest request, final String targetid,
final LocalArtifact artifact) {
final Target target = controllerManagement.updateLastTargetQuery(targetid,
@@ -153,38 +154,4 @@ public class ArtifactStoreController {
return action;
}
/**
* Handles GET {@link Artifact} MD5 checksum file download request.
*
* @param fileName
* to search for
* @param response
* to write to
*
* @return response of the servlet
*/
@RequestMapping(method = RequestMethod.GET, value = ControllerConstants.ARTIFACT_DOWNLOAD_BY_FILENAME
+ "/{fileName}" + ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX)
@ResponseBody
public ResponseEntity<Void> downloadArtifactMD5ByFilename(@PathVariable final String fileName,
final HttpServletResponse response) {
final List<LocalArtifact> foundArtifacts = artifactManagement.findLocalArtifactByFilename(fileName);
if (foundArtifacts.isEmpty()) {
LOG.warn("Softeare artifact with name {} could not be found.", fileName);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else if (foundArtifacts.size() > 1) {
LOG.error("Softeare artifact name {} is not unique.", fileName);
}
try {
DataConversionHelper.writeMD5FileResponse(fileName, response, foundArtifacts.get(0));
} catch (final IOException e) {
LOG.error("Failed to stream MD5 File", e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -6,28 +6,29 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
import org.eclipse.hawkbit.cache.CacheWriteNotify;
import org.eclipse.hawkbit.controller.model.ActionFeedback;
import org.eclipse.hawkbit.controller.model.Cancel;
import org.eclipse.hawkbit.controller.model.CancelActionToStop;
import org.eclipse.hawkbit.controller.model.Chunk;
import org.eclipse.hawkbit.controller.model.ConfigData;
import org.eclipse.hawkbit.controller.model.ControllerBase;
import org.eclipse.hawkbit.controller.model.Deployment;
import org.eclipse.hawkbit.controller.model.Deployment.HandlingType;
import org.eclipse.hawkbit.controller.model.DeploymentBase;
import org.eclipse.hawkbit.controller.model.Result.FinalResult;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiCancel;
import org.eclipse.hawkbit.ddi.json.model.DdiCancelActionToStop;
import org.eclipse.hawkbit.ddi.json.model.DdiChunk;
import org.eclipse.hawkbit.ddi.json.model.DdiConfigData;
import org.eclipse.hawkbit.ddi.json.model.DdiControllerBase;
import org.eclipse.hawkbit.ddi.json.model.DdiDeployment;
import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.HandlingType;
import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase;
import org.eclipse.hawkbit.ddi.json.model.DdiResult.FinalResult;
import org.eclipse.hawkbit.ddi.rest.api.DdiRootControllerRestApi;
import org.eclipse.hawkbit.repository.ArtifactManagement;
import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.SoftwareManagement;
@@ -35,12 +36,12 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.resource.helper.RestResourceConversionHelper;
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
import org.eclipse.hawkbit.rest.util.RestResourceConversionHelper;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.eclipse.hawkbit.util.IpUtil;
@@ -48,29 +49,27 @@ import org.hibernate.validator.constraints.NotEmpty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
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.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
/**
* The {@link RootController} of the SP server controller API that is queried by
* the SP controller in order to pull {@link Action}s that have to be fullfilled
* and report status updates concerning the {@link Action} processing.
* The {@link DdiRootController} of the hawkBit server DDI API that is queried
* by the hawkBit controller in order to pull {@link Action}s that have to be
* fulfilled and report status updates concerning the {@link Action} processing.
*
* Transactional (read-write) as all queries at least update the last poll time.
*
*/
@RestController
@RequestMapping(ControllerConstants.BASE_V1_REQUEST_MAPPING)
public class RootController {
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
public class DdiRootController implements DdiRootControllerRestApi {
private static final Logger LOG = LoggerFactory.getLogger(RootController.class);
private static final Logger LOG = LoggerFactory.getLogger(DdiRootController.class);
private static final String GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET = "given action ({}) is not assigned to given target ({}).";
@Autowired
@@ -94,20 +93,13 @@ public class RootController {
@Autowired
private ArtifactUrlHandler artifactUrlHandler;
/**
* Returns all artifacts of a given software module and target.
*
* @param targetid
* of the {@link Target} that matches to
* {@link Target#getControllerId()}
* @param softwareModuleId
* of the {@link SoftwareModule}
* @return the response
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}/softwaremodules/{softwareModuleId}/artifacts", produces = {
"application/hal+json", MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<List<org.eclipse.hawkbit.controller.model.Artifact>> getSoftwareModulesArtifacts(
@PathVariable final String targetid, @PathVariable final Long softwareModuleId) {
@Autowired
private RequestResponseContextHolder requestResponseContextHolder;
@Override
public ResponseEntity<List<org.eclipse.hawkbit.ddi.json.model.DdiArtifact>> getSoftwareModulesArtifacts(
@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId) {
LOG.debug("getSoftwareModulesArtifacts({})", targetid);
final SoftwareModule softwareModule = softwareManagement.findSoftwareModuleById(softwareModuleId);
@@ -122,30 +114,20 @@ public class RootController {
HttpStatus.OK);
}
/**
* Root resource for an individual {@link Target}.
*
* @param targetid
* of the {@link Target} that matches to
* {@link Target#getControllerId()}
* @param request
* the HTTP request injected by spring
* @return the response
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}", produces = { "application/hal+json",
MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<ControllerBase> getControllerBase(@PathVariable final String targetid,
final HttpServletRequest request) {
@Override
public ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("targetid") final String targetid) {
LOG.debug("getControllerBase({})", targetid);
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
if (target.getTargetInfo().getUpdateStatus() == TargetUpdateStatus.UNKNOWN) {
LOG.debug("target with {} extsisted but was in status UNKNOWN -> REGISTERED)", targetid);
controllerManagement.updateTargetStatus(target.getTargetInfo(), TargetUpdateStatus.REGISTERED,
System.currentTimeMillis(),
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
}
return new ResponseEntity<>(
@@ -154,33 +136,15 @@ public class RootController {
HttpStatus.OK);
}
/**
* Handles GET {@link Artifact} download request. This could be full or
* partial (as specified by RFC7233 (Range Requests)) download request.
*
* @param targetid
* of the related
* @param softwareModuleId
* of the parent {@link SoftwareModule}
* @param fileName
* of the related {@link LocalArtifact}
* @param response
* of the servlet
* @param request
* from the client
*
* @return response of the servlet which in case of success is status code
* {@link HttpStatus#OK} or in case of partial download
* {@link HttpStatus#PARTIAL_CONTENT}.
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}/softwaremodules/{softwareModuleId}/artifacts/{fileName}")
public ResponseEntity<Void> downloadArtifact(@PathVariable final String targetid,
@PathVariable final Long softwareModuleId, @PathVariable final String fileName,
final HttpServletResponse response, final HttpServletRequest request) {
ResponseEntity<Void> result;
@Override
public ResponseEntity<InputStream> downloadArtifact(@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("fileName") final String fileName) {
ResponseEntity<InputStream> result;
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
if (checkModule(fileName, module)) {
@@ -190,17 +154,17 @@ public class RootController {
final LocalArtifact artifact = module.getLocalArtifactByFilename(fileName).get();
final DbArtifact file = artifactManagement.loadLocalArtifactBinary(artifact);
final String ifMatch = request.getHeader("If-Match");
final String ifMatch = requestResponseContextHolder.getHttpServletRequest().getHeader("If-Match");
if (ifMatch != null && !RestResourceConversionHelper.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
} else {
final Action action = checkAndLogDownload(request, target, module);
result = RestResourceConversionHelper.writeFileResponse(artifact, response, request, file,
cacheWriteNotify, action.getId());
final Action action = checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), target,
module);
result = RestResourceConversionHelper.writeFileResponse(artifact,
requestResponseContextHolder.getHttpServletResponse(),
requestResponseContextHolder.getHttpServletRequest(), file, cacheWriteNotify, action.getId());
}
}
return result;
}
@@ -230,30 +194,13 @@ public class RootController {
return null == module || !module.getLocalArtifactByFilename(fileName).isPresent();
}
/**
* Handles GET {@link Artifact} MD5 checksum file download request.
*
* @param targetid
* of the related
* @param softwareModuleId
* of the parent {@link SoftwareModule}
* @param fileName
* of the related {@link LocalArtifact}
* @param response
* of the servlet
* @param request
* the HTTP request injected by spring
*
* @return {@link ResponseEntity} with status {@link HttpStatus#OK} if
* successful
*/
@RequestMapping(method = RequestMethod.GET, value = "/{targetid}/softwaremodules/{softwareModuleId}/artifacts/{fileName}"
+ ControllerConstants.ARTIFACT_MD5_DWNL_SUFFIX, produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable final String targetid,
@PathVariable final Long softwareModuleId, @PathVariable final String fileName,
final HttpServletResponse response, final HttpServletRequest request) {
@Override
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable("targetid") final String targetid,
@PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("fileName") final String fileName) {
controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final SoftwareModule module = softwareManagement.findSoftwareModuleById(softwareModuleId);
@@ -263,7 +210,7 @@ public class RootController {
}
try {
DataConversionHelper.writeMD5FileResponse(fileName, response,
DataConversionHelper.writeMD5FileResponse(fileName, requestResponseContextHolder.getHttpServletResponse(),
module.getLocalArtifactByFilename(fileName).get());
} catch (final IOException e) {
LOG.error("Failed to stream MD5 File", e);
@@ -273,33 +220,15 @@ public class RootController {
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* Resource for {@link SoftwareModule} {@link UpdateAction}s.
*
* @param targetid
* of the {@link Target} that matches to
* {@link Target#getControllerId()}
* @param actionId
* of the {@link DeploymentBase} that matches to
* {@link Target#getActiveActions()}
* @param resource
* an hashcode of the resource which indicates if the action has
* been changed, e.g. from 'soft' to 'force' and the eTag needs
* to be re-generated
* @param request
* the HTTP request injected by spring
* @return the response
*/
@RequestMapping(value = "/{targetid}/" + ControllerConstants.DEPLOYMENT_BASE_ACTION
+ "/{actionId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<DeploymentBase> getControllerBasedeploymentAction(
@PathVariable @NotEmpty final String targetid, @PathVariable @NotEmpty final Long actionId,
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource,
final HttpServletRequest request) {
@Override
public ResponseEntity<DdiDeploymentBase> getControllerBasedeploymentAction(
@PathVariable("targetid") final String targetid, @PathVariable("actionId") final Long actionId,
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource) {
LOG.debug("getControllerBasedeploymentAction({},{})", targetid, resource);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -309,17 +238,18 @@ public class RootController {
if (!action.isCancelingOrCanceled()) {
final List<Chunk> chunks = DataConversionHelper.createChunks(targetid, action, artifactUrlHandler);
final List<DdiChunk> chunks = DataConversionHelper.createChunks(targetid, action, artifactUrlHandler);
final HandlingType handlingType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT;
final DeploymentBase base = new DeploymentBase(Long.toString(action.getId()),
new Deployment(handlingType, handlingType, chunks));
final DdiDeploymentBase base = new DdiDeploymentBase(Long.toString(action.getId()),
new DdiDeployment(handlingType, handlingType, chunks));
LOG.debug("Found an active UpdateAction for target {}. returning deyploment: {}", targetid, base);
controllerManagement.registerRetrieved(action,
"Controller retrieved update action and should start now the download.");
ControllerManagement.SERVER_MESSAGE_PREFIX
+ "Target retrieved update action and should start now the download.");
return new ResponseEntity<>(base, HttpStatus.OK);
}
@@ -327,30 +257,14 @@ public class RootController {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
/**
* This is the feedback channel for the {@link DeploymentBase} action.
*
* @param feedback
* to provide
* @param targetid
* of the {@link Target} that matches to
* {@link Target#getControllerId()}
* @param actionId
* of the action we have feedback for
* @param request
* the HTTP request injected by spring
*
* @return the response
*/
@RequestMapping(value = "/{targetid}/" + ControllerConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}/"
+ ControllerConstants.FEEDBACK, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> postBasedeploymentActionFeedback(@Valid @RequestBody final ActionFeedback feedback,
@PathVariable final String targetid, @PathVariable @NotEmpty final Long actionId,
final HttpServletRequest request) {
@Override
public ResponseEntity<Void> postBasedeploymentActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
@PathVariable("targetid") final String targetid, @PathVariable("actionId") @NotEmpty final Long actionId) {
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", targetid, actionId, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
if (!actionId.equals(feedback.getId())) {
LOG.warn(
@@ -371,15 +285,15 @@ public class RootController {
return new ResponseEntity<>(HttpStatus.GONE);
}
controllerManagement.addUpdateActionStatus(generateUpdateStatus(feedback, targetid, feedback.getId(), action),
action);
controllerManagement.addUpdateActionStatus(
generateUpdateStatus(feedback, targetid, feedback.getId(), action), action);
return new ResponseEntity<>(HttpStatus.OK);
}
private ActionStatus generateUpdateStatus(final ActionFeedback feedback, final String targetid, final Long actionid,
final Action action) {
private ActionStatus generateUpdateStatus(final DdiActionFeedback feedback, final String targetid,
final Long actionid, final Action action) {
final ActionStatus actionStatus = new ActionStatus();
actionStatus.setAction(action);
@@ -418,7 +332,7 @@ public class RootController {
return actionStatus;
}
private static void handleDefaultUpdateStatus(final ActionFeedback feedback, final String targetid,
private static void handleDefaultUpdateStatus(final DdiActionFeedback feedback, final String targetid,
final Long actionid, final ActionStatus actionStatus) {
LOG.debug("Controller reported intermediate status (actionid: {}, targetid: {}) as we got {} report.", actionid,
targetid, feedback.getStatus().getExecution());
@@ -427,7 +341,7 @@ public class RootController {
ControllerManagement.SERVER_MESSAGE_PREFIX + "Target reported " + feedback.getStatus().getExecution());
}
private static void handleClosedUpdateStatus(final ActionFeedback feedback, final String targetid,
private static void handleClosedUpdateStatus(final DdiActionFeedback feedback, final String targetid,
final Long actionid, final ActionStatus actionStatus) {
LOG.debug("Controller reported closed (actionid: {}, targetid: {}) as we got {} report.", actionid, targetid,
feedback.getStatus().getExecution());
@@ -440,50 +354,27 @@ public class RootController {
}
}
/**
* This is the feedback channel for the config data action.
*
* @param configData
* as body
* @param targetid
* to provide data for
* @param request
* the HTTP request injected by spring
*
* @return status of the request
*/
@RequestMapping(value = "/{targetid}/"
+ ControllerConstants.CONFIG_DATA_ACTION, method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final ConfigData configData,
@PathVariable final String targetid, final HttpServletRequest request) {
@Override
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
@PathVariable("targetid") final String targetid) {
controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
controllerManagement.updateControllerAttributes(targetid, configData.getData());
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* {@link RequestMethod.GET} method for the {@link Cancel} action.
*
* @param targetid
* ID of the calling target
* @param actionId
* of the action
* @param request
* the HTTP request injected by spring
*
* @return the {@link Cancel} response
*/
@RequestMapping(value = "/{targetid}/" + ControllerConstants.CANCEL_ACTION
+ "/{actionId}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Cancel> getControllerCancelAction(@PathVariable @NotEmpty final String targetid,
@PathVariable @NotEmpty final Long actionId, final HttpServletRequest request) {
@Override
public ResponseEntity<DdiCancel> getControllerCancelAction(
@PathVariable("targetid") @NotEmpty final String targetid,
@PathVariable("actionId") @NotEmpty final Long actionId) {
LOG.debug("getControllerCancelAction({})", targetid);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
final Action action = findActionWithExceptionIfNotFound(actionId);
if (!action.getTarget().getId().equals(target.getId())) {
@@ -492,13 +383,13 @@ public class RootController {
}
if (action.isCancelingOrCanceled()) {
final Cancel cancel = new Cancel(String.valueOf(action.getId()),
new CancelActionToStop(String.valueOf(action.getId())));
final DdiCancel cancel = new DdiCancel(String.valueOf(action.getId()),
new DdiCancelActionToStop(String.valueOf(action.getId())));
LOG.debug("Found an active CancelAction for target {}. returning cancel: {}", targetid, cancel);
controllerManagement.registerRetrieved(action,
"Controller retrieved cancel action and should start now the cancelation.");
controllerManagement.registerRetrieved(action, ControllerManagement.SERVER_MESSAGE_PREFIX
+ "Target retrieved cancel action and should start now the cancelation.");
return new ResponseEntity<>(cancel, HttpStatus.OK);
}
@@ -506,31 +397,15 @@ public class RootController {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
/**
* {@link RequestMethod.POST} method receiving the {@link ActionFeedback}
* from the target.
*
* @param feedback
* the {@link ActionFeedback} from the target.
* @param targetid
* the ID of the calling target
* @param actionId
* of the action we have feedback for
* @param request
* the HTTP request injected by spring
*
* @return the {@link ActionFeedback} response
*/
@RequestMapping(value = "/{targetid}/" + ControllerConstants.CANCEL_ACTION + "/{actionId}/"
+ ControllerConstants.FEEDBACK, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> postCancelActionFeedback(@Valid @RequestBody final ActionFeedback feedback,
@PathVariable @NotEmpty final String targetid, @PathVariable @NotEmpty final Long actionId,
final HttpServletRequest request) {
@Override
public ResponseEntity<Void> postCancelActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
@PathVariable("targetid") @NotEmpty final String targetid,
@PathVariable("actionId") @NotEmpty final Long actionId) {
LOG.debug("provideCancelActionFeedback for target [{}]: {}", targetid, feedback);
final Target target = controllerManagement.updateLastTargetQuery(targetid,
IpUtil.getClientIpFromRequest(request, securityProperties.getClients().getRemoteIpHeader()));
IpUtil.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(),
securityProperties.getClients().getRemoteIpHeader()));
if (!actionId.equals(feedback.getId())) {
LOG.warn(
@@ -550,7 +425,7 @@ public class RootController {
return new ResponseEntity<>(HttpStatus.OK);
}
private static ActionStatus generateActionCancelStatus(final ActionFeedback feedback, final Target target,
private static ActionStatus generateActionCancelStatus(final DdiActionFeedback feedback, final Target target,
final Long actionid, final Action action) {
final ActionStatus actionStatus = new ActionStatus();
@@ -590,7 +465,7 @@ public class RootController {
}
private static void handleClosedCancelStatus(final ActionFeedback feedback, final ActionStatus actionStatus) {
private static void handleClosedCancelStatus(final DdiActionFeedback feedback, final ActionStatus actionStatus) {
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
actionStatus.setStatus(Status.ERROR);
} else {
@@ -605,5 +480,4 @@ public class RootController {
}
return findAction;
}
}

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.junit.Assert.assertTrue;
@@ -26,7 +26,6 @@ import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.WithUser;
import org.eclipse.hawkbit.eventbus.event.DownloadProgressEvent;
@@ -36,13 +35,13 @@ import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.junit.Test;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MvcResult;
import com.google.common.base.Charsets;
@@ -56,16 +55,13 @@ import ru.yandex.qatools.allure.annotations.Stories;
/**
* Test artifact downloads from the controller.
*
*/
@ActiveProfiles({ "im", "test" })
@Features("Component Tests - Direct Device Integration API")
@Stories("Artifact Download Resource")
public class ArtifactDownloadTest extends AbstractIntegrationTestWithMongoDB {
public class DdiArtifactDownloadTest extends AbstractRestIntegrationTestWithMongoDB {
public ArtifactDownloadTest() {
LOG = LoggerFactory.getLogger(ArtifactDownloadTest.class);
public DdiArtifactDownloadTest() {
LOG = LoggerFactory.getLogger(DdiArtifactDownloadTest.class);
}
private volatile int downLoadProgress = 0;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -22,27 +22,28 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.ArrayList;
import java.util.List;
import org.eclipse.hawkbit.AbstractIntegrationTest;
import org.eclipse.hawkbit.MockMvcResultPrinter;
import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.resource.JsonBuilder;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.junit.Test;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@ActiveProfiles({ "im", "test" })
/**
* Test cancel action from the controller.
*/
@Features("Component Tests - Direct Device Integration API")
@Stories("Cancel Action Resource")
public class CancelActionTest extends AbstractIntegrationTest {
public class DdiCancelActionTest extends AbstractRestIntegrationTest {
@Test
@Description("Test of the controller can continue a started update even after a cancel command if it so desires.")

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -22,9 +22,9 @@ import java.util.HashMap;
import java.util.Map;
import org.eclipse.hawkbit.AbstractIntegrationTest;
import org.eclipse.hawkbit.MockMvcResultPrinter;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.rest.resource.JsonBuilder;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.junit.Test;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
@@ -34,10 +34,13 @@ import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
/**
* Test config data from the controller.
*/
@ActiveProfiles({ "im", "test" })
@Features("Component Tests - Direct Device Integration API")
@Stories("Config Data Resource")
public class ConfigDataTest extends AbstractIntegrationTest {
public class DdiConfigDataTest extends AbstractIntegrationTest {
@Test
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -25,8 +25,6 @@ import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.MockMvcResultPrinter;
import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
@@ -36,7 +34,9 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.LocalArtifact;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.resource.JsonBuilder;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.fest.assertions.core.Condition;
import org.junit.Test;
import org.springframework.data.domain.PageRequest;
@@ -45,16 +45,20 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@ActiveProfiles({ "im", "test" })
/**
* Test deployment base from the controller.
*/
@Features("Component Tests - Direct Device Integration API")
@Stories("Deployment Action Resource")
public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
public class DdiDeploymentBaseTest extends AbstractRestIntegrationTestWithMongoDB {
private static final String HTTP_LOCALHOST = "http://localhost:8080/";
private static final String HTTPS_LOCALHOST = "https://localhost:8080/";
@Test()
@Description("Ensures that artifacts are not found, when softare module does not exists.")
@@ -170,24 +174,22 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
equalTo(artifact.getSha1Hash())))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.MD5SUM")))
@@ -200,23 +202,21 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
equalTo(artifactSignature.getSha1Hash())))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==bApp)][0].version",
@@ -315,12 +315,12 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0].hashes.sha1",
equalTo(artifact.getSha1Hash())))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.MD5SUM")))
@@ -333,23 +333,21 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
equalTo(artifactSignature.getSha1Hash())))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==bApp)][0].version",
@@ -445,23 +443,21 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
equalTo(artifact.getSha1Hash())))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.download-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[0]._links.md5sum-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].size", equalTo(5 * 1024)))
@@ -473,24 +469,22 @@ public class DeploymentBaseTest extends AbstractIntegrationTestWithMongoDB {
jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1].hashes.sha1",
equalTo(artifactSignature.getSha1Hash())))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum.href",
equalTo("https://localhost/" + tenantAware.getCurrentTenant()
equalTo(HTTPS_LOCALHOST + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature.MD5SUM")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.download-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature")))
.andExpect(jsonPath("$deployment.chunks[?(@.part==os)][0].artifacts[1]._links.md5sum-http.href",
equalTo("http://localhost/" + tenantAware.getCurrentTenant()
+ "/controller/v1/4712/softwaremodules/"
equalTo(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
+ findDistributionSetByAction.findFirstModuleByType(osType).getId()
+ "/artifacts/test1.signature.MD5SUM")))

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.controller;
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo;
@@ -22,8 +22,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.ArrayList;
import java.util.List;
import org.eclipse.hawkbit.AbstractIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.MockMvcResultPrinter;
import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.WithSpringAuthorityRule;
import org.eclipse.hawkbit.WithUser;
@@ -33,22 +31,25 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.resource.JsonBuilder;
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTestWithMongoDB;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationKey;
import org.eclipse.hawkbit.util.IpUtil;
import org.junit.Test;
import org.springframework.hateoas.MediaTypes;
import org.springframework.http.MediaType;
import org.springframework.test.context.ActiveProfiles;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Stories;
@ActiveProfiles({ "im", "test" })
/**
* Test the root controller resources.
*/
@Features("Component Tests - Direct Device Integration API")
@Stories("Root Poll Resource")
public class RootControllerTest extends AbstractIntegrationTestWithMongoDB {
public class DdiRootControllerTest extends AbstractRestIntegrationTestWithMongoDB {
@Test
@Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists but can be created if the tenant exists.")

View File

@@ -100,6 +100,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
amqpMessageDispatcherService.targetAssignDistributionSet(targetAssignDistributionSetEvent);
final Message sendMessage = createArgumentCapture(targetAssignDistributionSetEvent.getTargetAdress());
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
assertTrue("No softwaremmodule should be contained in the request",
downloadAndUpdateRequest.getSoftwareModules().isEmpty());
}
@@ -116,6 +117,7 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
assertEquals("Expecting a size of 3 software modules in the reuqest", 3,
downloadAndUpdateRequest.getSoftwareModules().size());
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
.getSoftwareModules()) {
assertTrue("Artifact list for softwaremodule should be empty", softwareModule.getArtifacts().isEmpty());
@@ -155,6 +157,8 @@ public class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTestWit
final DownloadAndUpdateRequest downloadAndUpdateRequest = assertDownloadAndInstallMessage(sendMessage);
assertEquals("DownloadAndUpdateRequest event should contains 3 software modules", 3,
downloadAndUpdateRequest.getSoftwareModules().size());
assertThat(downloadAndUpdateRequest.getTargetSecurityToken()).isEqualTo(TEST_TOKEN);
for (final org.eclipse.hawkbit.dmf.json.model.SoftwareModule softwareModule : downloadAndUpdateRequest
.getSoftwareModules()) {
if (!softwareModule.getModuleId().equals(module.getId())) {

View File

@@ -39,6 +39,8 @@ import ru.yandex.qatools.allure.annotations.Stories;
AmqpTestConfiguration.class })
public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTestWithMongoDB {
private static final String HTTPS_LOCALHOST = "https://localhost:8080/";
private static final String HTTP_LOCALHOST = "http://localhost:8080/";
@Autowired
private ArtifactUrlHandler urlHandlerProperties;
@Autowired
@@ -69,9 +71,8 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
UrlProtocol.HTTP);
assertEquals("http is build incorrect",
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
+ localArtifact.getFilename(),
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId + "/softwaremodules/"
+ localArtifact.getSoftwareModule().getId() + "/artifacts/" + localArtifact.getFilename(),
url);
}
@@ -81,7 +82,7 @@ public class PropertyBasedArtifactUrlHandlerTest extends AbstractIntegrationTest
final String url = urlHandlerProperties.getUrl(controllerId, softwareModuleId, fileName, sha1Hash,
UrlProtocol.HTTPS);
assertEquals("https is build incorrect",
"https://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
HTTPS_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
+ "/softwaremodules/" + localArtifact.getSoftwareModule().getId() + "/artifacts/"
+ localArtifact.getFilename(),
url);

View File

@@ -0,0 +1,14 @@
# Eclipse.IoT hawkBit - Mgmt API
This Management (Mgmt) API is used to manage and monitor the HawkBit Update Server via HTTP. This API allows Create/Read/Update/Delete operations for provisioning targets (i.e. devices) and repository content (i.e. software).
# Compile
#### Build hawkbit-mgmt-api
```
$ cd hawkbit/hawkbit-mgmt-api
$ mvn clean install
```

View File

@@ -16,15 +16,10 @@
<artifactId>hawkbit-parent</artifactId>
<version>0.2.0-SNAPSHOT</version>
</parent>
<artifactId>hawkbit-rest-api</artifactId>
<name>hawkBit :: REST API</name>
<artifactId>hawkbit-mgmt-api</artifactId>
<name>hawkBit :: Mgmt REST API</name>
<dependencies>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>
<artifactId>spring-hateoas</artifactId>
@@ -33,5 +28,26 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.easytesting</groupId>
<artifactId>fest-assert</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ru.yandex.qatools.allure</groupId>
<artifactId>allure-junit-adaptor</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.rest.resource.model;
package org.eclipse.hawkbit.mgmt.json.model;
import org.springframework.hateoas.ResourceSupport;
@@ -17,7 +17,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* A json annotated rest model for BaseEntity to RESTful API representation.
*
*/
public abstract class BaseEntityRest extends ResourceSupport {
public abstract class MgmtBaseEntity extends ResourceSupport {
@JsonProperty
private String createdBy;

View File

@@ -6,7 +6,7 @@
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.rest.resource.model;
package org.eclipse.hawkbit.mgmt.json.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -18,7 +18,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
*
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class IdRest {
public class MgmtId {
@JsonProperty
private Long id;

Some files were not shown because too many files have changed in this diff Show More