20250828 cleanup (#2639)

* Cleanup

* Refactor artifact management
This commit is contained in:
Avgustin Marinov
2025-09-02 16:08:14 +03:00
committed by GitHub
parent 4f0a8893c7
commit 2a636328a0
305 changed files with 2253 additions and 4566 deletions

View File

@@ -47,9 +47,7 @@ public class DdiActionHistory {
* @param messages is a list of messages retrieved from action history.
*/
@JsonCreator
public DdiActionHistory(
@JsonProperty("status") final String status,
@JsonProperty("messages") final List<String> messages) {
public DdiActionHistory(@JsonProperty("status") final String status, @JsonProperty("messages") final List<String> messages) {
this.status = status;
this.messages = messages;
}

View File

@@ -14,6 +14,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.lang.Nullable;
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
@@ -27,16 +28,10 @@ public class DdiActivateAutoConfirmation {
"confirming future actions", example = "exampleRemark")
private final String remark;
/**
* Constructor.
*
* @param initiator can be null
* @param remark can be null
*/
@JsonCreator
public DdiActivateAutoConfirmation(
@JsonProperty(value = "initiator") final String initiator,
@JsonProperty(value = "remark") final String remark) {
@Nullable @JsonProperty(value = "initiator") final String initiator,
@Nullable @JsonProperty(value = "remark") final String remark) {
this.initiator = initiator;
this.remark = remark;
}

View File

@@ -32,7 +32,7 @@ import org.springframework.hateoas.RepresentationModel;
* **download** - HTTPs Download resource for artifacts. The resource supports partial download as specified by RFC7233 (range requests). Keep in mind that the target needs to have the artifact assigned in order to be granted permission to download.
* **md5sum** - HTTPs Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for Linux based devices on order to check artifact consistency after download by using the md5sum command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself.
* **download-http** - HTTP Download resource for artifacts. The resource supports partial download as specified by RFC7233 (range requests). Keep in mind that the target needs to have the artifact assigned in order to be granted permission to download. (note: anonymous download needs to be enabled on the service account for non-TLS access)
* **md5sum-http** - HTTP Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for Linux based devices on order to check artifact consistency after download by using the md5sum command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself. (note: anonymous download needs to be enabled on the service account for non-TLS access)
* **md5sum-http** - HTTP Download resource for MD5SUM file is an optional auto generated artifact that is especially useful for Linux based devices on order to check artifact consistency after download by using the md5sum command line tool. The MD5 and SHA1 are in addition available as metadata in the deployment command itself. (note: anonymous download needs to be enabled on the service account for non-TLS access)
""", example = """
{
"filename" : "binaryFile",
@@ -47,10 +47,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/40/filename/binaryFile.MD5SUM"

View File

@@ -28,11 +28,6 @@ public class DdiConfig {
private final DdiPolling polling;
/**
* Constructor.
*
* @param polling configuration of the polling for the target
*/
@JsonCreator
public DdiConfig(@JsonProperty("polling") final DdiPolling polling) {
this.polling = polling;

View File

@@ -57,8 +57,7 @@ public class DdiConfirmationBase extends RepresentationModel<DdiConfirmationBase
private final DdiAutoConfirmationState autoConfirm;
@JsonCreator
public DdiConfirmationBase(
@JsonProperty(value = "autoConfirm", required = true) final DdiAutoConfirmationState autoConfirm) {
public DdiConfirmationBase(@JsonProperty(value = "autoConfirm", required = true) final DdiAutoConfirmationState autoConfirm) {
this.autoConfirm = autoConfirm;
}
}

View File

@@ -58,10 +58,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/binary.tgz"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/binary.tgz"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/binary.tgz"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/binary.tgz.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/binary.tgz.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/binary.tgz.MD5SUM"
@@ -80,10 +80,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/file.signature"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/file.signature"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/file.signature"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/file.signature.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/file.signature.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/17/filename/file.signature.MD5SUM"
@@ -107,10 +107,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/binary.tgz"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/binary.tgz"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/binary.tgz"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/binary.tgz.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/binary.tgz.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/binary.tgz.MD5SUM"
@@ -129,10 +129,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/file.signature"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/file.signature"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/file.signature"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/file.signature.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/file.signature.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/16/filename/file.signature.MD5SUM"
@@ -156,10 +156,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/binary.tgz"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/binary.tgz"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/binary.tgz"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/binary.tgz.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/binary.tgz.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/binary.tgz.MD5SUM"
@@ -178,10 +178,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/file.signature"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/file.signature"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/file.signature"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/file.signature.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/file.signature.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/18/filename/file.signature.MD5SUM"

View File

@@ -32,7 +32,7 @@ import org.springframework.hateoas.RepresentationModel;
**_links**: Actions that the server has for the target
* **deploymentBase** - Detailed deployment operation
* **installedBase** - Detailed operation of last successfully finished action
* **configData** - Link which is provided whenever the provisioning target or device is supposed to push its configuration data (aka. "controller attributes") to the server. Only shown for the initial configuration, after a successful update action, or if requested explicitly (e.g. via the management UI)
* **configData** - Link which is provided whenever the provisioning target or device is supposed to push its configuration data (aka. "controller attributes") to the server. Only shown for the initial configuration, after a successful update action, or if requested explicitly (e.g. via the management UI)
""",
example = """
{

View File

@@ -100,7 +100,7 @@ public class DdiDeployment {
*/
FORCED("forced");
private String name;
private final String name;
HandlingType(final String name) {
this.name = name;
@@ -128,7 +128,7 @@ public class DdiDeployment {
*/
UNAVAILABLE("unavailable");
private String status;
private final String status;
DdiMaintenanceWindowStatus(final String status) {
this.status = status;

View File

@@ -54,10 +54,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/binary.tgz"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/binary.tgz"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/binary.tgz"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/binary.tgz.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/binary.tgz.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/binary.tgz.MD5SUM"
@@ -76,10 +76,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/file.signature"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/file.signature"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/file.signature"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/file.signature.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/file.signature.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/23/filename/file.signature.MD5SUM"
@@ -103,10 +103,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/binary.tgz"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/binary.tgz"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/binary.tgz"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/binary.tgz.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/binary.tgz.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/binary.tgz.MD5SUM"
@@ -125,10 +125,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/file.signature"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/file.signature"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/file.signature"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/file.signature.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/file.signature.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/24/filename/file.signature.MD5SUM"
@@ -152,10 +152,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/binary.tgz"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/binary.tgz"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/binary.tgz"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/binary.tgz.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/binary.tgz.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/binary.tgz.MD5SUM"
@@ -174,10 +174,10 @@ import org.springframework.hateoas.RepresentationModel;
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/file.signature"
},
"download-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/file.signature"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/file.signature"
},
"md5sum-http" : {
"href" : "http://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/file.signature.MD5SUM"
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/file.signature.MD5SUM"
},
"md5sum" : {
"href" : "https://link-to-cdn.com/api/v1/TENANT_ID/download/controller/CONTROLLER_ID/softwaremodules/22/filename/file.signature.MD5SUM"

View File

@@ -67,7 +67,7 @@ public class DdiResult {
*/
NONE("none");
private String name;
private final String name;
FinalResult(final String name) {
this.name = name;

View File

@@ -13,8 +13,7 @@ package org.eclipse.hawkbit.ddi.json.model;
import com.fasterxml.jackson.annotation.JsonValue;
/**
* Enumerates the supported update modes. Each mode represents an attribute
* update strategy.
* Enumerates the supported update modes. Each mode represents an attribute update strategy.
*
* @see DdiConfigData
*/

View File

@@ -100,7 +100,7 @@ public interface DdiRootControllerRestApi {
retrieve actions that need to be executed. Those are provided as a list of links to give more detailed
information about the action. Links are only available for initial configuration, open actions, or the latest
installed action, respectively. The resource supports Etag based modification checks in order to save traffic.
Note: deployments have to be confirmed in order to move on to the next action. Cancellations have to be
confirmed or rejected.""")
@ApiResponses(value = {
@@ -214,7 +214,7 @@ public interface DdiRootControllerRestApi {
* the eTag needs to be re-generated
* @param actionHistoryMessageCount specifies the number of messages to be returned from action history. Regardless of the passed value,
* in order to restrict resource utilization by controllers, maximum number of
* messages that are retrieved from database is limited by {@link RepositoryConstants#MAX_ACTION_HISTORY_MSG_COUNT}.
* messages that are retrieved from database is limited by RepositoryConstants#MAX_ACTION_HISTORY_MSG_COUNT.
* actionHistoryMessageCount less than zero: retrieves the maximum allowed number of action status messages from history;
* actionHistoryMessageCount equal to zero: does not retrieve any message;
* actionHistoryMessageCount greater than zero: retrieves the specified number of messages, limited by maximum allowed number.
@@ -222,7 +222,7 @@ public interface DdiRootControllerRestApi {
*/
@Operation(summary = "Resource for software module (Deployment Base)", description = """
Core resource for deployment operations. Contains all information necessary in order to execute the operation.
Keep in mind that the provided download links for the artifacts are generated dynamically by the update server.
Host, port and path and not guaranteed to be similar to the provided examples below but will be defined at
runtime.
@@ -230,15 +230,14 @@ public interface DdiRootControllerRestApi {
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = """
Successfully retrieved
In case a device provides state information on the feedback channel and wont store it locally,
a query for, e.q, the last 10 messages, could be used which will include the previously provided by the
device,
feedback.
device, feedback.
In addition to the straight forward approach to inform the device to download and install the software
in one transaction hawkBit supports the separation of download and installation into separate steps.
This feature is called Maintenance Window where the device is informed to download the software first
and then when it enters a defined (maintenance) window the installation triggers follows as usual.
"""),
@@ -373,7 +372,7 @@ public interface DdiRootControllerRestApi {
*/
@Operation(summary = "Cancel an action", description = """
The Hawkbit server might cancel an operation, e.g. an unfinished update has a successor. It is up to the
provisioning target to decide to accept the cancelation or reject it.""")
provisioning target to decide to accept the cancellation or reject it.""")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Successfully retrieved"),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
@@ -450,7 +449,7 @@ public interface DdiRootControllerRestApi {
* @param actionId of the {@link DdiDeploymentBase} that matches to installed action.
* @param actionHistoryMessageCount specifies the number of messages to be returned from action
* history. Regardless of the passed value, in order to restrict resource utilization by controllers, maximum number of
* messages that are retrieved from database is limited by {@link RepositoryConstants#MAX_ACTION_HISTORY_MSG_COUNT}.
* messages that are retrieved from database is limited by RepositoryConstants#MAX_ACTION_HISTORY_MSG_COUNT.
* actionHistoryMessageCount less than zero: retrieves the maximum allowed number of action status messages from history;
* actionHistoryMessageCount equal to zero: does not retrieve any message;
* actionHistoryMessageCount greater than zero: retrieves the specified number of messages, limited by maximum allowed number.
@@ -461,7 +460,7 @@ public interface DdiRootControllerRestApi {
the already finished action, for example in case a re-installation is necessary. The response will be of
the same format as the deploymentBase operation, providing the previous action that has been finished
successfully. As the action is already finished, no further feedback is expected.
Keep in mind that the provided download links for the artifacts are generated dynamically by the update server.
Host, port and path are not guaranteed to be similar to the provided examples below but will be defined at
runtime.
@@ -470,7 +469,7 @@ public interface DdiRootControllerRestApi {
@ApiResponse(responseCode = "200", description = """
The response body includes the detailed operation for the already finished action in the same format as
for the deploymentBase operation.
In this case the (optional) query for the last 10 messages, previously provided by the device, are included.
"""),
@ApiResponse(responseCode = "400", description = "Bad Request - e.g. invalid parameters",
@@ -546,7 +545,7 @@ public interface DdiRootControllerRestApi {
* needs to be re-generated
* @param actionHistoryMessageCount specifies the number of messages to be returned from action history. Regardless of the passed value,
* in order to restrict resource utilization by controllers, maximum number of messages that are retrieved from database is limited
* by {@link RepositoryConstants#MAX_ACTION_HISTORY_MSG_COUNT}.
* by RepositoryConstants#MAX_ACTION_HISTORY_MSG_COUNT.
* actionHistoryMessageCount less than zero: retrieves the maximum allowed number of action status messages from history;
* actionHistoryMessageCount equal to zero: does not retrieve any message;
* actionHistoryMessageCount greater than zero: retrieves the specified number of messages, limited by maximum allowed number.
@@ -556,7 +555,7 @@ public interface DdiRootControllerRestApi {
Resource to receive information about a pending confirmation. The response will be of the same format as the
deploymentBase operation. The controller should provide feedback about the confirmation first, before
processing the deployment.
Keep in mind that the provided download links for the artifacts are generated dynamically by the update server.
Host, port and path are not guaranteed to be similar to the provided examples below but will be defined at
runtime.

View File

@@ -49,7 +49,7 @@ class DdiActionHistoryTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -50,7 +50,7 @@ class DdiArtifactHashTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -53,7 +53,7 @@ class DdiArtifactTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -47,7 +47,7 @@ class DdiCancelActionToStopTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -48,7 +48,7 @@ class DdiCancelTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -54,7 +54,7 @@ class DdiChunkTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -46,7 +46,7 @@ class DdiConfigTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -64,7 +64,7 @@ class DdiConfirmationBaseTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -47,7 +47,7 @@ class DdiControllerBaseTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -58,7 +58,7 @@ class DdiDeploymentBaseTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -52,7 +52,7 @@ class DdiDeploymentTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -48,7 +48,7 @@ class DdiMetadataTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -45,7 +45,7 @@ class DdiPollingTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -46,7 +46,7 @@ class DdiProgressTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -49,7 +49,7 @@ class DdiResultTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -55,7 +55,7 @@ class DdiStatusTest {
}
/**
* Verify the correct deserialization of a model with a additional unknown property
* Verify the correct deserialization of a model with an additional unknown property
*/
@Test
void shouldDeserializeObjectWithUnknownProperty() throws IOException {

View File

@@ -14,10 +14,8 @@ import java.util.Map;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler;
import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder;
import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder.SoftwareData;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver.DownloadDescriptor;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
import org.eclipse.hawkbit.ddi.json.model.DdiArtifactHash;
import org.eclipse.hawkbit.ddi.json.model.DdiAutoConfirmationState;
@@ -121,6 +119,7 @@ public final class DataConversionHelper {
result.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
// doesn't really call the putConfigData with null, just create the link
.putConfigData(null, tenantAware.getCurrentTenant(), target.getControllerId()))
.withRel(DdiRestConstants.CONFIG_DATA_ACTION).expand());
}
@@ -130,7 +129,7 @@ public final class DataConversionHelper {
static List<DdiChunk> createChunks(
final Target target, final Action uAction,
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
final ArtifactUrlResolver artifactUrlHandler, final SystemManagement systemManagement,
final HttpRequest request, final ControllerManagement controllerManagement) {
final Map<Long, Map<String, String>> metadata = controllerManagement
.findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream()
@@ -146,7 +145,7 @@ public final class DataConversionHelper {
}
static List<DdiArtifact> createArtifacts(final Target target, final SoftwareModule module,
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
final ArtifactUrlResolver artifactUrlHandler, final SystemManagement systemManagement,
final HttpRequest request) {
return new ResponseList<>(module.getArtifacts().stream()
@@ -171,7 +170,7 @@ public final class DataConversionHelper {
}
private static DdiArtifact createArtifact(
final Target target, final ArtifactUrlHandler artifactUrlHandler,
final Target target, final ArtifactUrlResolver artifactUrlHandler,
final Artifact artifact, final SystemManagement systemManagement, final HttpRequest request) {
final DdiArtifact file = new DdiArtifact(
artifact.getFilename(),
@@ -180,13 +179,11 @@ public final class DataConversionHelper {
final TenantMetaData tenantMetadata = systemManagement.getTenantMetadataWithoutDetails();
artifactUrlHandler
.getUrls(new URLPlaceholder(
tenantMetadata.getTenant(), tenantMetadata.getId(), target.getControllerId(), target.getId(),
new SoftwareData(
artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getId(),
artifact.getSha1Hash())),
ApiType.DDI, request.getURI())
.forEach(entry -> file.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand()));
.getUrls(new DownloadDescriptor(
tenantMetadata.getTenant(), target.getControllerId(),
artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getSha1Hash()),
ArtifactUrlResolver.ApiType.DDI, request.getURI())
.forEach(entry -> file.add(Link.of(entry.ref()).withRel(entry.rel()).expand()));
return file;
}

View File

@@ -17,11 +17,10 @@ import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Controller;
/**
* Enable {@link ComponentScan} in the resource package to setup all
* {@link Controller} annotated classes and setup the REST-Resources for the
* Enable {@link ComponentScan} in the resource package to set up all {@link Controller} annotated classes and set up the REST-Resources for the
* Direct Device Integration API.
*/
@Configuration
@ComponentScan
@Import({ RestConfiguration.class, OpenApi.class, DdiOpenApiConfiguration.class })
public class DdiApiConfiguration {}
public class DdiApiConfiguration {}

View File

@@ -21,6 +21,8 @@ import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.hawkbit.artifact.model.ArtifactStream;
import org.eclipse.hawkbit.artifact.urlresolver.ArtifactUrlResolver;
import org.eclipse.hawkbit.audit.AuditLog;
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory;
@@ -50,13 +52,10 @@ import org.eclipse.hawkbit.repository.ControllerManagement;
import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.UpdateMode;
import org.eclipse.hawkbit.repository.artifact.model.DbArtifact;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler;
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException;
import org.eclipse.hawkbit.repository.exception.SoftwareModuleNotAssignedToTargetException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate;
import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate.ActionStatusCreateBuilder;
@@ -99,7 +98,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
private final ControllerManagement controllerManagement;
private final ConfirmationManagement confirmationManagement;
private final ArtifactManagement artifactManagement;
private final ArtifactUrlHandler artifactUrlHandler;
private final ArtifactUrlResolver artifactUrlHandler;
private final SystemManagement systemManagement;
private final ApplicationEventPublisher eventPublisher;
private final HawkbitSecurityProperties securityProperties;
@@ -108,7 +107,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
@SuppressWarnings("java:S107")
public DdiRootController(
final ControllerManagement controllerManagement, final ConfirmationManagement confirmationManagement,
final ArtifactManagement artifactManagement, final ArtifactUrlHandler artifactUrlHandler,
final ArtifactManagement artifactManagement, final ArtifactUrlResolver artifactUrlHandler,
final SystemManagement systemManagement,
final ApplicationEventPublisher eventPublisher,
final HawkbitSecurityProperties securityProperties, final TenantAware tenantAware) {
@@ -131,11 +130,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
final Target target = findTarget(controllerId);
final SoftwareModule softwareModule = controllerManagement.getSoftwareModule(softwareModuleId)
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
final SoftwareModule softwareModule = controllerManagement.getSoftwareModule(softwareModuleId);
return new ResponseEntity<>(
DataConversionHelper.createArtifacts(target, softwareModule, artifactUrlHandler, systemManagement,
DataConversionHelper.createArtifacts(
target, softwareModule, artifactUrlHandler, systemManagement,
new ServletServerHttpRequest(RequestResponseContextHolder.getHttpServletRequest())),
HttpStatus.OK);
}
@@ -147,7 +145,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(
controllerId, IpUtil.getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties));
final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null);
final Action installedAction = controllerManagement.getInstalledActionByTarget(target).orElse(null);
final Action installedAction = controllerManagement.findInstalledActionByTarget(target).orElse(null);
checkAndCancelExpiredAction(activeAction);
@@ -170,16 +168,14 @@ public class DdiRootController implements DdiRootControllerRestApi {
final ResponseEntity<InputStream> result;
final Target target = findTarget(controllerId);
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId);
if (checkModule(fileName, module)) {
log.warn("Software module with id {} could not be found (1).", softwareModuleId);
result = ResponseEntity.notFound().build();
} else {
// Artifact presence is ensured in 'checkModule'
final Artifact artifact = module.getArtifactByFilename(fileName).orElseThrow(NoSuchElementException::new);
final DbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash(), module.getId(), module.isEncrypted());
final ArtifactStream file = artifactManagement.getArtifactStream(artifact.getSha1Hash(), module.getId(), module.isEncrypted());
final String ifMatch = RequestResponseContextHolder.getHttpServletRequest().getHeader(HttpHeaders.IF_MATCH);
if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
@@ -212,9 +208,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
final String fileName) {
final Target target = findTarget(controllerId);
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId);
if (checkModule(fileName, module)) {
log.warn("Software module with id {} could not be found (2).", softwareModuleId);
return ResponseEntity.notFound().build();
@@ -596,9 +590,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
}
private ActionStatus logDownload(final HttpServletRequest request, final Target target, final Long module) {
final Action action = controllerManagement
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module)
.orElseThrow(() -> new SoftwareModuleNotAssignedToTargetException(module, target.getControllerId()));
final Action action = controllerManagement.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module);
return controllerManagement.addInformationalActionStatus(
ActionStatusCreate.builder()
.actionId(action.getId())
@@ -750,16 +742,16 @@ public class DdiRootController implements DdiRootControllerRestApi {
}
private Optional<DdiActionHistory> generateDdiActionHistory(final Action action, final Integer actionHistoryMessageCount) {
final List<String> actionHistoryMsgs = controllerManagement.getActionHistoryMessages(
final List<String> actionHistoryMessages = controllerManagement.getActionHistoryMessages(
action.getId(),
actionHistoryMessageCount == null ? Integer.parseInt(DdiRestConstants.NO_ACTION_HISTORY) : actionHistoryMessageCount);
return actionHistoryMsgs.isEmpty()
return actionHistoryMessages.isEmpty()
? Optional.empty()
: Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs));
: Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMessages));
}
private DdiAutoConfirmationState getAutoConfirmationState(final String controllerId) {
return confirmationManagement.getStatus(controllerId).map(status -> {
return confirmationManagement.findStatus(controllerId).map(status -> {
final DdiAutoConfirmationState state = new DdiAutoConfirmationState(
true, status.getInitiator(), status.getRemark(), status.getActivatedAt());
log.trace("Returning state auto-conf state active [initiator='{}' | activatedAt={}] for device {}",

View File

@@ -39,12 +39,8 @@ import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
import org.eclipse.hawkbit.ddi.json.model.DdiProgress;
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.JpaRepositoryConfiguration;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.specifications.DistributionSetSpecification;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -171,7 +167,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher, final String... values)
throws Exception {
return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType)
return mvc.perform(MockMvcRequestBuilders.get(url, (Object[]) values).accept(mediaType)
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher)
@@ -281,14 +277,12 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
}
protected String getJsonClosedDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(
DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, Collections.singletonList("closed"));
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, Collections.singletonList("closed"));
}
protected String getJsonActionFeedback(
final DdiStatus.ExecutionStatus executionStatus, final DdiResult.FinalResult finalResult) throws JsonProcessingException {
return getJsonActionFeedback(
executionStatus, finalResult, Collections.singletonList(randomString(1000)));
return getJsonActionFeedback(executionStatus, finalResult, Collections.singletonList(randomString(1000)));
}
protected String getJsonActionFeedback(
@@ -376,10 +370,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
contains(artifact.getSha256Hash())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + "/download")))
"/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + "/download.MD5SUM")))
"/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + ".MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE)))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename",
contains(artifactSignature.getFilename())))
@@ -391,10 +385,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
contains(artifactSignature.getSha256Hash())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download")))
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download.MD5SUM")))
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + ".MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version",
contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist())

View File

@@ -57,8 +57,8 @@ import org.springframework.test.web.servlet.MvcResult;
@SpringBootTest(classes = { DownloadTestConfiguration.class })
class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
private static volatile int downloadProgress = 0;
private static volatile long shippedBytes = 0;
private static int downloadProgress = 0;
private static long shippedBytes = 0;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
@@ -68,7 +68,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
}
/**
* Tests non allowed requests on the artifact ressource, e.g. invalid URI, wrong if-match, wrong command.
* Tests not allowed requests on the artifact resource, e.g. invalid URI, wrong if-match, wrong command.
*/
@Test
void invalidRequestsOnArtifactResource() throws Exception {
@@ -83,7 +83,8 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
final int artifactSize = 5 * 1024;
final byte[] random = nextBytes(artifactSize);
final Artifact artifact = artifactManagement.create(new ArtifactUpload(
new ByteArrayInputStream(random), findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize));
new ByteArrayInputStream(random), null, artifactSize, null,
findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false));
assignDistributionSet(ds, targets);
@@ -163,8 +164,10 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
@Test
@WithUser(principal = "4712", authorities = "ROLE_CONTROLLER", allSpPermissions = true)
void downloadArtifactThroughFileName() throws Exception {
downloadProgress = 1;
shippedBytes = 0;
synchronized (DdiArtifactDownloadTest.class) {
downloadProgress = 1;
shippedBytes = 0;
}
assertThat(softwareModuleManagement.findAll(PAGE)).isEmpty();
// create target
@@ -177,8 +180,9 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// create artifact
final int artifactSize = (int) quotaManagement.getMaxArtifactSize();
final byte[] random = nextBytes(artifactSize);
final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random),
findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize));
final Artifact artifact = artifactManagement.create(new ArtifactUpload(
new ByteArrayInputStream(random), null, artifactSize, null,
findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false));
// download fails as artifact is not yet assigned
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
@@ -197,12 +201,13 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
.andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename()))
.andReturn();
assertArrayEquals(result.getResponse().getContentAsByteArray(), random,
"The same file that was uploaded is expected when downloaded");
assertArrayEquals(result.getResponse().getContentAsByteArray(), random, "The same file that was uploaded is expected when downloaded");
// download complete
assertThat(downloadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(artifactSize);
synchronized (DdiArtifactDownloadTest.class) {
assertThat(downloadProgress).isEqualTo(10);
assertThat(shippedBytes).isEqualTo(artifactSize);
}
}
/**
@@ -219,8 +224,9 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// create artifact
final int artifactSize = 5 * 1024;
final byte[] random = nextBytes(artifactSize);
final Artifact artifact = artifactManagement.create(
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, artifactSize));
final Artifact artifact = artifactManagement.create(new ArtifactUpload(
new ByteArrayInputStream(random), null, artifactSize, null,
getOsModule(ds), "file1", false));
assignDistributionSet(ds, target);
@@ -254,8 +260,9 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// create artifact
final byte[] random = nextBytes(resultLength);
final Artifact artifact = artifactManagement.create(
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, resultLength));
final Artifact artifact = artifactManagement.create(new ArtifactUpload(
new ByteArrayInputStream(random), null, resultLength, null,
getOsModule(ds), "file1", false));
assertThat(random).hasSize(resultLength);
@@ -379,8 +386,10 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
@EventListener(classes = DownloadProgressEvent.class)
void listen(final DownloadProgressEvent event) {
downloadProgress++;
shippedBytes += event.getShippedBytesSinceLast();
synchronized (DdiArtifactDownloadTest.class) {
downloadProgress++;
shippedBytes += event.getShippedBytesSinceLast();
}
}
}
}

View File

@@ -139,18 +139,18 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.andExpect(status().isOk());
// check database after test
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow())
.isEqualTo(ds);
assertThat(deploymentManagement.getInstalledDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
assertThat(deploymentManagement.findInstalledDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow())
.isEqualTo(ds);
assertThat(
targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getInstallationDate())
targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getInstallationDate())
.isGreaterThanOrEqualTo(current);
}
/**
* Test for cancel operation of a update action.
* Test for cancel operation of an update action.
*/
@Test
void rootRsCancelAction() throws Exception {
@@ -171,7 +171,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId)));
final long timeAfterFirstPoll = System.currentTimeMillis() + 1;
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery())
.isBetween(timeBeforeFirstPoll, timeAfterFirstPoll);
// Retrieved is reported
@@ -202,7 +202,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId())));
final long timeAfter2ndPoll = System.currentTimeMillis() + 1;
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery())
.isBetween(timeBefore2ndPoll, timeAfter2ndPoll);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
@@ -212,7 +212,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId))));
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
assertThat(targetManagement.getByControllerId(TestdataFactory.DEFAULT_CONTROLLER_ID).getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
// controller confirmed cancelled action, should not be active anymore
@@ -226,7 +226,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)
.getContent();
assertThat(activeActionsByTarget).isEmpty();
final Action canceledAction = deploymentManagement.findAction(cancelAction.getId()).get();
final Action canceledAction = deploymentManagement.findAction(cancelAction.getId()).orElseThrow();
assertThat(canceledAction.isActive()).isFalse();
assertThat(canceledAction.getStatus()).isEqualTo(Status.CANCELED);
@@ -355,6 +355,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
/**
* Tests the feeback chanel of for multiple open cancel operations on the same target.
*/
@SuppressWarnings("java:S5961")
@Test
void multipleCancelActionFeedback() throws Exception {
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
@@ -363,14 +364,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = testdataFactory.createTarget();
final Long actionId = getFirstAssignedActionId(
assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID));
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID));
implicitLock(ds);
final Long actionId2 = getFirstAssignedActionId(
assignDistributionSet(ds2.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID));
final Long actionId2 = getFirstAssignedActionId(assignDistributionSet(ds2.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID));
implicitLock(ds2);
final Long actionId3 = getFirstAssignedActionId(
assignDistributionSet(ds3.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID));
final Long actionId3 = getFirstAssignedActionId(assignDistributionSet(ds3.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID));
implicitLock(ds3);
assertThat(countActionStatusAll()).isEqualTo(3);
@@ -383,8 +381,9 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(3);
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
mvc.perform(get(
"/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -442,8 +441,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(9);
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
.isEqualTo(ds3);
assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()).isEqualTo(ds3);
mvc.perform(
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
tenantAware.getCurrentTenant()))
@@ -459,11 +457,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// action is in cancelling state
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId(), PAGE)).hasSize(1);
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
.isEqualTo(ds3);
assertThat(deploymentManagement.findAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).orElseThrow()).isEqualTo(ds3);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
mvc.perform(get(
"/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction3.getId(),
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))

View File

@@ -72,11 +72,11 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
}
@Test
/**
* We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) are requested only once from the device.")
*/
@SuppressWarnings("squid:S2925")
@Test
void requestConfigDataIfEmpty() throws Exception {
final Target savedTarget = testdataFactory.createTarget("4712");
@@ -90,10 +90,10 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
Thread.sleep(1); // is required: otherwise processing the next line is
// often too fast and // the following assert will fail
assertThat(targetManagement.getByControllerId("4712").orElseThrow(NoSuchElementException::new)
assertThat(targetManagement.getByControllerId("4712")
.getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(targetManagement.getByControllerId("4712").orElseThrow(NoSuchElementException::new)
assertThat(targetManagement.getByControllerId("4712")
.getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
@@ -140,7 +140,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
/**
* We verify that the config data (i.e. device attributes like serial number, hardware revision etc.)
* upload quota is enforced to protect the server from malicious attempts.""")
* upload quota is enforced to protect the server from malicious attempts.
*/
@Test
void putTooMuchConfigData() throws Exception {

View File

@@ -113,13 +113,12 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)))
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getLastTargetQuery()).isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(actionStatusRepository.count()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).orElseThrow();
getAndVerifyConfirmationBasePayload(
DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
@@ -142,7 +141,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = testdataFactory.createTarget();
final DistributionSet distributionSet = testdataFactory.createDistributionSet("");
final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId();
final Long softwareModuleId = distributionSet.getModules().stream().findAny().orElseThrow().getId();
testdataFactory.createArtifacts(softwareModuleId);
assignDistributionSet(distributionSet.getId(), target.getName());
@@ -359,7 +358,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(confirmationManagement.getStatus(controllerId)).hasValueSatisfying(status -> {
assertThat(confirmationManagement.findStatus(controllerId)).hasValueSatisfying(status -> {
assertThat(status.getInitiator()).isEqualTo(initiator);
assertThat(status.getRemark()).isEqualTo(remark);
assertThat(status.getCreatedBy()).isEqualTo("bumlux");
@@ -379,7 +378,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(confirmationManagement.getStatus(controllerId)).isEmpty();
assertThat(confirmationManagement.findStatus(controllerId)).isEmpty();
}
/**

View File

@@ -41,7 +41,6 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
import org.eclipse.hawkbit.repository.jpa.specifications.ActionSpecifications;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.Action.Status;
@@ -89,7 +88,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = testdataFactory.createTarget();
final DistributionSet distributionSet = testdataFactory.createDistributionSet("");
final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId();
final Long softwareModuleId = distributionSet.getModules().stream().findAny().orElseThrow().getId();
testdataFactory.createArtifacts(softwareModuleId);
assignDistributionSet(distributionSet.getId(), target.getName());
@@ -128,7 +127,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = testdataFactory.createTarget();
final DistributionSet distributionSet = testdataFactory.createDistributionSet("");
final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId();
final Long softwareModuleId = distributionSet.getModules().stream().findAny().orElseThrow().getId();
testdataFactory.createArtifacts(softwareModuleId);
assignDistributionSet(distributionSet.getId(), target.getName());
@@ -181,10 +180,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath(
"$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertLastTargetQueryUpdated(current);
assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
@@ -281,10 +277,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertLastTargetQueryUpdated(current);
assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
@@ -338,10 +331,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertLastTargetQueryUpdated(current);
assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
@@ -398,15 +388,11 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Run test
final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID)
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertLastTargetQueryUpdated(current);
assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = findDsByAction(action.getId()).get();
@@ -490,7 +476,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
}
/**
* The server protects itself against too large feedback bodies. The test verifies that
* The server protects itself against too large feedback bodies. The test verifies that
* it is not possible to exceed the configured maximum number of feedback details.
*/
@Test
@@ -560,7 +546,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
DistributionSet ds = testdataFactory.createDistributionSet("");
final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
assignDistributionSet(ds, Collections.singletonList(savedTarget));
final Action action = actionRepository
.findAll(byDistributionSetId(ds.getId()), PAGE)
@@ -576,8 +562,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assertTargetCountByStatus(0, 1, 0);
// redo
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
assignDistributionSet(ds, Collections.singletonList(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID).get()));
ds = distributionSetManagement.getWithDetails(ds.getId());
assignDistributionSet(ds, Collections.singletonList(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID)));
final Action action2 = deploymentManagement.findActiveActionsByTarget(DEFAULT_CONTROLLER_ID, PAGE).getContent().get(0);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(), status().isOk());
findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds));
@@ -741,9 +727,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds.getId(), "1080");
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
final String missingFinishedResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED,
new DdiResult(null, null),
Collections.singletonList("test"));
final String missingFinishedResultInFeedback = getJsonActionFeedback(
DdiStatus.ExecutionStatus.CLOSED, new DdiResult(null, null), Collections.singletonList("test"));
postDeploymentFeedback("1080", action.getId(), missingFinishedResultInFeedback, status().isBadRequest())
.andExpect(jsonPath("$.*", hasSize(3)))
@@ -766,15 +751,14 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
}
private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) {
final Target target = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
final Target target = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID);
assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
assertTargetCountByStatus(1, 0, 0);
assertThat(deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE)).hasSize(1);
assertThat(countActionStatusAll()).isEqualTo(actionStatusCount);
assertThat(findActionStatusAll(PAGE).getContent())
.haveAtLeast(minActionStatusCountInPage, new ActionStatusCondition(Status.RUNNING));
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(minActionStatusCountInPage, new ActionStatusCondition(Status.RUNNING));
}
private Target createTargetAndAssertNoActiveActions() {
@@ -796,11 +780,11 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Optional<DistributionSet> ds,
final TargetUpdateStatus updateStatus, final int activeActions,
final Optional<DistributionSet> installedDs) {
final Target myT = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
final Target myT = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID);
assertThat(myT.getUpdateStatus()).isEqualTo(updateStatus);
assertThat(deploymentManagement.findActiveActionsByTarget(myT.getControllerId(), PAGE)).hasSize(activeActions);
assertThat(deploymentManagement.getAssignedDistributionSet(myT.getControllerId())).isEqualTo(ds);
assertThat(deploymentManagement.getInstalledDistributionSet(myT.getControllerId())).isEqualTo(installedDs);
assertThat(deploymentManagement.findAssignedDistributionSet(myT.getControllerId())).isEqualTo(ds);
assertThat(deploymentManagement.findInstalledDistributionSet(myT.getControllerId())).isEqualTo(installedDs);
}
private void assertTargetCountByStatus(final int pending, final int error, final int inSync) {
@@ -811,16 +795,26 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
private void assertActionStatusCount(final int total, final int running, final int warning, final int finished, final int canceled) {
assertThat(countActionStatusAll()).isEqualTo(total);
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(running, new ActionStatusCondition(Status.RUNNING));
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(warning, new ActionStatusCondition(Status.WARNING));
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(canceled, new ActionStatusCondition(Status.CANCELED));
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(finished, new ActionStatusCondition(Status.FINISHED));
assertThat(findActionStatusAll(PAGE).getContent()).satisfies(findActionStatusAll -> {
assertThat(findActionStatusAll).haveAtLeast(running, new ActionStatusCondition(Status.RUNNING));
assertThat(findActionStatusAll).haveAtLeast(warning, new ActionStatusCondition(Status.WARNING));
assertThat(findActionStatusAll).haveAtLeast(canceled, new ActionStatusCondition(Status.CANCELED));
assertThat(findActionStatusAll).haveAtLeast(finished, new ActionStatusCondition(Status.FINISHED));
});
}
private void assertLastTargetQueryUpdated(final long current) {
assertThat(targetManagement.getByControllerId(DEFAULT_CONTROLLER_ID)).satisfies(target -> {
assertThat(target.getLastTargetQuery()).isGreaterThanOrEqualTo(current);
assertThat(target.getLastTargetQuery()).isLessThanOrEqualTo(System.currentTimeMillis());
});
}
private void assertStatusAndActiveActionsCount(final TargetUpdateStatus status, final int activeActions) {
final Target target = targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
assertThat(target.getUpdateStatus()).isEqualTo(status);
assertThat(deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE)).hasSize(activeActions);
assertThat(targetManagement.getByControllerId(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID)).satisfies(target -> {
assertThat(target.getUpdateStatus()).isEqualTo(status);
assertThat(deploymentManagement.findActiveActionsByTarget(target.getControllerId(), PAGE)).hasSize(activeActions);
});
}
private Page<ActionStatus> findActionStatusAll(final Pageable pageable) {

View File

@@ -109,7 +109,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// update assigned version
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isCreated());
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()).isEqualTo(ds.getId());
assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).get().getId()).isEqualTo(ds.getId());
// update assigned version while version already assigned
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isOk());
@@ -127,7 +127,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// get installed base
putInstalledBase(target.getControllerId(), getJsonInstalledBase(dsName, dsVersion), status().isNotFound());
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue();
assertThat(deploymentManagement.findAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue();
}
/**

View File

@@ -10,8 +10,8 @@
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.hawkbit.im.authentication.SpRole.CONTROLLER_ROLE_ANONYMOUS;
import static org.eclipse.hawkbit.im.authentication.SpPermission.TENANT_CONFIGURATION;
import static org.eclipse.hawkbit.im.authentication.SpRole.CONTROLLER_ROLE_ANONYMOUS;
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs;
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.getAs;
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withController;
@@ -125,7 +125,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final String knownTargetControllerId = "target1";
final String knownCreatedBy = "knownPrincipal";
testdataFactory.createTarget(knownTargetControllerId);
final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId).get();
final Target findTargetByControllerID = targetManagement.getByControllerId(knownTargetControllerId);
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
// make a poll, audit information should not be changed, run as controller principal!
callAs(withController("controller", CONTROLLER_ROLE_ANONYMOUS),
@@ -136,7 +136,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
return null;
});
// verify that audit information has not changed
final Target targetVerify = targetManagement.getByControllerId(knownTargetControllerId).get();
final Target targetVerify = targetManagement.getByControllerId(knownTargetControllerId);
assertThat(targetVerify.getCreatedBy()).isEqualTo(findTargetByControllerID.getCreatedBy());
assertThat(targetVerify.getCreatedAt()).isEqualTo(findTargetByControllerID.getCreatedAt());
assertThat(targetVerify.getLastModifiedBy()).isEqualTo(findTargetByControllerID.getLastModifiedBy());
@@ -170,10 +170,10 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
assertThat(targetManagement.getByControllerId(controllerId).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(controllerId).get().getUpdateStatus())
.isEqualTo(TargetUpdateStatus.REGISTERED);
assertThat(targetManagement.getByControllerId(controllerId)).satisfies(target -> {
assertThat(target.getLastTargetQuery()).isGreaterThanOrEqualTo(current);
assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.REGISTERED);
});
// not allowed methods
mvc.perform(post(CONTROLLER_BASE, "default-tenant", controllerId))
@@ -265,7 +265,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotModified());
final Target target = targetManagement.getByControllerId(controllerId).get();
final Target target = targetManagement.getByControllerId(controllerId);
final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds.getId(), controllerId);
@@ -338,19 +338,18 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
void rootRsPreCommissioned() throws Exception {
final String controllerId = "4711";
testdataFactory.createTarget(controllerId);
assertThat(targetManagement.getByControllerId(controllerId).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
assertThat(targetManagement.getByControllerId(controllerId).getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
final long current = System.currentTimeMillis();
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
assertThat(targetManagement.getByControllerId(controllerId).get().getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(targetManagement.getByControllerId(controllerId).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current);
assertThat(targetManagement.getByControllerId(controllerId).get().getUpdateStatus())
.isEqualTo(TargetUpdateStatus.REGISTERED);
assertThat(targetManagement.getByControllerId(controllerId)).satisfies(target -> {
assertThat(target.getLastTargetQuery()).isLessThanOrEqualTo(System.currentTimeMillis());
assertThat(target.getLastTargetQuery()).isGreaterThanOrEqualTo(current);
assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.REGISTERED);
});
}
/**
@@ -374,12 +373,13 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
return null;
});
// verify
final Target target = targetManagement.getByControllerId(knownControllerId1).get();
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1").toString());
assertThat(target.getCreatedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY");
assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create);
assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY");
assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create);
assertThat(targetManagement.getByControllerId(knownControllerId1)).satisfies(target -> {
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1").toString());
assertThat(target.getCreatedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY");
assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create);
assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY");
assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create);
});
}
/**
@@ -397,7 +397,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
// verify
final Target target = targetManagement.getByControllerId(knownControllerId1).get();
final Target target = targetManagement.getByControllerId(knownControllerId1);
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("***").toString());
securityProperties.getClients().setTrackRemoteIp(true);
}

View File

@@ -30,7 +30,7 @@
</dependency>
<dependency>
<groupId>org.eclipse.hawkbit</groupId>
<artifactId>hawkbit-artifact-repository-filesystem</artifactId>
<artifactId>hawkbit-artifact-fs</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>