hawkBit rest docs (management & DDI API) (#688)
* hawkBit REST docs. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fiy gitignore. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Add to website. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Switch to generated docs. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix typos. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Review findings. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Otimizations. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Revert accidental checkin. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Add security link.
This commit is contained in:
16
hawkbit-rest/hawkbit-ddi-api/README.md
Normal file
16
hawkbit-rest/hawkbit-ddi-api/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Eclipse.IoT hawkBit - Direct Device Integration API - Model and Resources
|
||||
|
||||
The Direct Device Integration (DDI) API is used by devices for communicating with the HawkBit Update Server through HTTP.
|
||||
|
||||
# Version 1
|
||||
|
||||
The model follows [semantic versioning](http://semver.org) with MAJOR version, i.e. breaking changes will result in a new MAJOR version.
|
||||
|
||||
# Compile
|
||||
|
||||
#### Build hawkbit-ddi-api
|
||||
|
||||
```
|
||||
$ cd hawkbit/hawkbit-ddi-api
|
||||
$ mvn clean install
|
||||
```
|
||||
37
hawkbit-rest/hawkbit-ddi-api/pom.xml
Normal file
37
hawkbit-rest/hawkbit-ddi-api/pom.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<!--
|
||||
|
||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
which accompanies this distribution, and is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
|
||||
<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-rest-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-ddi-api</artifactId>
|
||||
<name>hawkBit :: REST :: 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>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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 javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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>
|
||||
* The answer header would look like: { "id": "51659181", "time":
|
||||
* "20140511T121314", "status": { "execution": "closed", "result": { "final":
|
||||
* "success", "progress": {} } "details": [], } }
|
||||
* </p>
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DdiActionFeedback {
|
||||
private final Long id;
|
||||
private final String time;
|
||||
|
||||
@NotNull
|
||||
@Valid
|
||||
private final DdiStatus status;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param id
|
||||
* of the actions the feedback is for
|
||||
* @param time
|
||||
* of the feedback
|
||||
* @param status
|
||||
* is the feedback itself
|
||||
*/
|
||||
@JsonCreator
|
||||
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;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public DdiStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ActionFeedback [id=" + id + ", time=" + time + ", status=" + status + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) Siemens AG, 2017
|
||||
*
|
||||
* 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 java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRootControllerRestApi;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
/**
|
||||
* Provide action history information to the controller as part of response to
|
||||
* {@link DdiRootControllerRestApi#getControllerBasedeploymentAction}: 1.
|
||||
* Current action status at the server; 2. List of messages from action history
|
||||
* that were sent to server earlier by the controller using
|
||||
* {@link DdiActionFeedback}.
|
||||
*/
|
||||
|
||||
@JsonPropertyOrder({ "status", "messages" })
|
||||
public class DdiActionHistory {
|
||||
|
||||
@JsonProperty("status")
|
||||
private final String actionStatus;
|
||||
|
||||
@JsonProperty("messages")
|
||||
private final List<String> messages;
|
||||
|
||||
/**
|
||||
* Parameterized constructor for creating {@link DdiActionHistory}.
|
||||
*
|
||||
* @param actionStatus
|
||||
* is the current action status at the server
|
||||
* @param messages
|
||||
* is a list of messages retrieved from action history.
|
||||
*/
|
||||
@JsonCreator
|
||||
public DdiActionHistory(@JsonProperty("status") final String actionStatus,
|
||||
@JsonProperty("messages") List<String> messages) {
|
||||
this.actionStatus = actionStatus;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Action history [" + "status=" + actionStatus + ", messages={" + messages.toString() + "}]";
|
||||
}
|
||||
}
|
||||
@@ -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 javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Download information for all artifacts related to a specific {@link DdiChunk}
|
||||
* .
|
||||
*/
|
||||
public class DdiArtifact extends ResourceSupport {
|
||||
|
||||
@NotNull
|
||||
@JsonProperty
|
||||
private String filename;
|
||||
|
||||
@JsonProperty
|
||||
private DdiArtifactHash hashes;
|
||||
|
||||
@JsonProperty
|
||||
private Long size;
|
||||
|
||||
public DdiArtifactHash getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
public void setHashes(final DdiArtifactHash hashes) {
|
||||
this.hashes = hashes;
|
||||
}
|
||||
|
||||
public String getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
public void setFilename(final String fileName) {
|
||||
filename = fileName;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public void setSize(final Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* 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() {
|
||||
// needed for json create
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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 javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* Cancel action to be provided to the target.
|
||||
*/
|
||||
public class DdiCancel {
|
||||
|
||||
private final String id;
|
||||
|
||||
@NotNull
|
||||
private final DdiCancelActionToStop cancelAction;
|
||||
|
||||
/**
|
||||
* Parameterized constructor.
|
||||
*
|
||||
* @param id
|
||||
* of the cancel action
|
||||
* @param cancelAction
|
||||
* the action
|
||||
*/
|
||||
public DdiCancel(final String id, final DdiCancelActionToStop cancelAction) {
|
||||
this.id = id;
|
||||
this.cancelAction = cancelAction;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public DdiCancelActionToStop getCancelAction() {
|
||||
return cancelAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Cancel [id=" + id + ", cancelAction=" + cancelAction + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.json.model;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* The action that has to be stopped by the target.
|
||||
*/
|
||||
public class DdiCancelActionToStop {
|
||||
|
||||
@NotNull
|
||||
private final String stopId;
|
||||
|
||||
/**
|
||||
* Parameterized constructor.
|
||||
*
|
||||
* @param stopId
|
||||
* ID of the action to be stoppedW
|
||||
*/
|
||||
public DdiCancelActionToStop(final String stopId) {
|
||||
this.stopId = stopId;
|
||||
}
|
||||
|
||||
public String getStopId() {
|
||||
return stopId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CancelAction [stopId=" + stopId + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 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 java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Deployment chunks.
|
||||
*/
|
||||
public class DdiChunk {
|
||||
|
||||
@JsonProperty("part")
|
||||
@NotNull
|
||||
private String part;
|
||||
|
||||
@JsonProperty("version")
|
||||
@NotNull
|
||||
private String version;
|
||||
|
||||
@JsonProperty("name")
|
||||
@NotNull
|
||||
private String name;
|
||||
|
||||
@JsonProperty("artifacts")
|
||||
private List<DdiArtifact> artifacts;
|
||||
|
||||
@JsonProperty("metadata")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private List<DdiMetadata> metadata;
|
||||
|
||||
public DdiChunk() {
|
||||
// needed for json create
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param part
|
||||
* of the deployment chunk
|
||||
* @param version
|
||||
* of the artifact
|
||||
* @param name
|
||||
* of the artifact
|
||||
* @param artifacts
|
||||
* download information
|
||||
* @param metadata
|
||||
* optional as additional information for the target/device
|
||||
*/
|
||||
public DdiChunk(final String part, final String version, final String name, final List<DdiArtifact> artifacts,
|
||||
final List<DdiMetadata> metadata) {
|
||||
this.part = part;
|
||||
this.version = version;
|
||||
this.name = name;
|
||||
this.artifacts = artifacts;
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public String getPart() {
|
||||
return part;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<DdiArtifact> getArtifacts() {
|
||||
if (artifacts == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(artifacts);
|
||||
}
|
||||
|
||||
public List<DdiMetadata> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 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.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DdiConfig {
|
||||
|
||||
@JsonProperty
|
||||
private DdiPolling polling;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param polling
|
||||
* configuration of the SP target
|
||||
*/
|
||||
public DdiConfig(final DdiPolling polling) {
|
||||
this.polling = polling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public DdiConfig() {
|
||||
// needed for json create.
|
||||
}
|
||||
|
||||
public DdiPolling getPolling() {
|
||||
return polling;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* 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 java.util.Map;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Feedback channel for ConfigData action.
|
||||
*/
|
||||
public class DdiConfigData extends DdiActionFeedback {
|
||||
|
||||
@NotEmpty
|
||||
private final Map<String, String> data;
|
||||
|
||||
private final DdiUpdateMode mode;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param id
|
||||
* of the actions the feedback is for
|
||||
* @param time
|
||||
* of the feedback
|
||||
* @param status
|
||||
* is the feedback itself
|
||||
* @param data
|
||||
* contains the attributes.
|
||||
*/
|
||||
@JsonCreator
|
||||
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,
|
||||
@JsonProperty(value = "mode") final DdiUpdateMode mode) {
|
||||
super(id, time, status);
|
||||
this.data = data;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public Map<String, String> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public DdiUpdateMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ConfigData [data=" + data + ", mode=" + mode + ", toString()=" + super.toString() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
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) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public DdiControllerBase() {
|
||||
// needed for json create
|
||||
}
|
||||
|
||||
public DdiConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* 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 java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Detailed update action information.
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class DdiDeployment {
|
||||
|
||||
private HandlingType download;
|
||||
|
||||
private HandlingType update;
|
||||
|
||||
@JsonProperty("chunks")
|
||||
@NotNull
|
||||
private List<DdiChunk> chunks;
|
||||
|
||||
private DdiMaintenanceWindowStatus maintenanceWindow;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public DdiDeployment() {
|
||||
// needed for json create.
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param download
|
||||
* handling type
|
||||
* @param update
|
||||
* handling type
|
||||
* @param chunks
|
||||
* to handle.
|
||||
* @param maintenanceWindow
|
||||
* specifying whether there is a maintenance schedule associated.
|
||||
* If it is, the value is either 'available' (i.e. the
|
||||
* maintenance window is now available as per defined schedule
|
||||
* and the update can progress) or 'unavailable' (implying that
|
||||
* maintenance window is not available now and update should not
|
||||
* be attempted). If there is no maintenance schedule defined,
|
||||
* the parameter is null.
|
||||
*/
|
||||
public DdiDeployment(final HandlingType download, final HandlingType update, final List<DdiChunk> chunks,
|
||||
final DdiMaintenanceWindowStatus maintenanceWindow) {
|
||||
this.download = download;
|
||||
this.update = update;
|
||||
this.chunks = chunks;
|
||||
this.maintenanceWindow = maintenanceWindow;
|
||||
}
|
||||
|
||||
public HandlingType getDownload() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public HandlingType getUpdate() {
|
||||
return update;
|
||||
}
|
||||
|
||||
public List<DdiChunk> getChunks() {
|
||||
if (chunks == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(chunks);
|
||||
}
|
||||
|
||||
public DdiMaintenanceWindowStatus getMaintenanceWindow() {
|
||||
return this.maintenanceWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* The handling type for the update action.
|
||||
*/
|
||||
public enum HandlingType {
|
||||
|
||||
/**
|
||||
* Not necessary for the command.
|
||||
*/
|
||||
SKIP("skip"),
|
||||
|
||||
/**
|
||||
* Try to execute (local applications may intervene by SP control API).
|
||||
*/
|
||||
ATTEMPT("attempt"),
|
||||
|
||||
/**
|
||||
* Execution independent of local intervention attempts.
|
||||
*/
|
||||
FORCED("forced");
|
||||
|
||||
private String name;
|
||||
|
||||
HandlingType(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Status of the maintenance window for action.
|
||||
*/
|
||||
public enum DdiMaintenanceWindowStatus {
|
||||
/**
|
||||
* A window is currently available, target can go ahead with
|
||||
* installation.
|
||||
*/
|
||||
AVAILABLE("available"),
|
||||
|
||||
/**
|
||||
* A window is not available, target should wait and skip the
|
||||
* installation.
|
||||
*/
|
||||
UNAVAILABLE("unavailable");
|
||||
|
||||
private String status;
|
||||
|
||||
DdiMaintenanceWindowStatus(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return status of maintenance window.
|
||||
*/
|
||||
@JsonValue
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Deployment [download=" + download + ", update=" + update + ", chunks=" + chunks
|
||||
+ (maintenanceWindow == null ? "]" : (", maintenanceWindow=" + maintenanceWindow + "]"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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 javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
/**
|
||||
* Update action resource.
|
||||
*/
|
||||
@JsonPropertyOrder({ "id", "deployment", "actionHistory" })
|
||||
public class DdiDeploymentBase extends ResourceSupport {
|
||||
|
||||
@JsonProperty("id")
|
||||
@NotNull
|
||||
private final String deplyomentId;
|
||||
|
||||
@JsonProperty("deployment")
|
||||
@NotNull
|
||||
private final DdiDeployment deployment;
|
||||
|
||||
/**
|
||||
* Action history containing current action status and a list of feedback
|
||||
* messages received earlier from the controller.
|
||||
*/
|
||||
@JsonProperty("actionHistory")
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private final DdiActionHistory actionHistory;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param id
|
||||
* of the update action
|
||||
* @param deployment
|
||||
* details
|
||||
* @param actionHistory
|
||||
* containing current action status and a list of feedback
|
||||
* messages received earlier from the controller.
|
||||
*/
|
||||
@JsonCreator
|
||||
public DdiDeploymentBase(@JsonProperty("id") final String id,
|
||||
@JsonProperty("deplyomentId") final DdiDeployment deployment,
|
||||
@JsonProperty("actionHistory") final DdiActionHistory actionHistory) {
|
||||
this.deplyomentId = id;
|
||||
this.deployment = deployment;
|
||||
this.actionHistory = actionHistory;
|
||||
}
|
||||
|
||||
public DdiDeployment getDeployment() {
|
||||
return deployment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action history containing current action status and a list of
|
||||
* feedback messages received earlier from the controller.
|
||||
*
|
||||
* @return {@link DdiActionHistory}
|
||||
*/
|
||||
public DdiActionHistory getActionHistory() {
|
||||
return actionHistory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeploymentBase [id=" + deplyomentId + ", deployment=" + deployment + " actionHistory="
|
||||
+ actionHistory + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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 javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Additional metadata to be provided for the target/device.
|
||||
*
|
||||
*/
|
||||
public class DdiMetadata {
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
private final String key;
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
private final String value;
|
||||
|
||||
public DdiMetadata(final String key, final String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.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.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class DdiPolling {
|
||||
|
||||
@JsonProperty
|
||||
private String sleep;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param sleep
|
||||
* between polls
|
||||
*/
|
||||
public DdiPolling(final String sleep) {
|
||||
this.sleep = sleep;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
*/
|
||||
public DdiPolling() {
|
||||
// needed for json create
|
||||
}
|
||||
|
||||
public String getSleep() {
|
||||
return sleep;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.ddi.json.model;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Action fulfillment progress by means of gives the achieved amount of maximal
|
||||
* of possible levels.
|
||||
*/
|
||||
public class DdiProgress {
|
||||
|
||||
@NotNull
|
||||
private final Integer cnt;
|
||||
|
||||
private final Integer of;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param cnt
|
||||
* achieved amount
|
||||
* @param of
|
||||
* maximum levels
|
||||
*/
|
||||
@JsonCreator
|
||||
public DdiProgress(@JsonProperty("cnt") final Integer cnt, @JsonProperty("of") final Integer of) {
|
||||
this.cnt = cnt;
|
||||
this.of = of;
|
||||
}
|
||||
|
||||
public Integer getCnt() {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
public Integer getOf() {
|
||||
return of;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Progress [cnt=" + cnt + ", of=" + of + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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 javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Result information of the action progress which can by an intermediate or
|
||||
* final update.
|
||||
*/
|
||||
public class DdiResult {
|
||||
|
||||
@NotNull
|
||||
@Valid
|
||||
private final FinalResult finished;
|
||||
|
||||
private final DdiProgress progress;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param finished
|
||||
* as final result
|
||||
* @param progress
|
||||
* if not yet finished
|
||||
*/
|
||||
@JsonCreator
|
||||
public DdiResult(@JsonProperty("finished") final FinalResult finished,
|
||||
@JsonProperty("progress") final DdiProgress progress) {
|
||||
this.finished = finished;
|
||||
this.progress = progress;
|
||||
}
|
||||
|
||||
public FinalResult getFinished() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public DdiProgress getProgress() {
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defined status of the final result.
|
||||
*
|
||||
*/
|
||||
public enum FinalResult {
|
||||
/**
|
||||
* Execution was successful.
|
||||
*/
|
||||
SUCESS("success"),
|
||||
|
||||
/**
|
||||
* Execution terminated with errors or without the expected result.
|
||||
*/
|
||||
FAILURE("failure"),
|
||||
|
||||
/**
|
||||
* No final result could be determined (yet).
|
||||
*/
|
||||
NONE("none");
|
||||
|
||||
private String name;
|
||||
|
||||
FinalResult(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Result [finished=" + finished + ", progress=" + progress + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/**
|
||||
* 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 java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Details status information concerning the action processing.
|
||||
*/
|
||||
public class DdiStatus {
|
||||
|
||||
@NotNull
|
||||
@Valid
|
||||
private final ExecutionStatus execution;
|
||||
|
||||
@NotNull
|
||||
@Valid
|
||||
private final DdiResult result;
|
||||
|
||||
private final List<String> details;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param execution
|
||||
* status
|
||||
* @param result
|
||||
* information
|
||||
* @param details
|
||||
* as optional addition
|
||||
*/
|
||||
@JsonCreator
|
||||
public DdiStatus(@JsonProperty("execution") final ExecutionStatus execution,
|
||||
@JsonProperty("result") final DdiResult result, @JsonProperty("details") final List<String> details) {
|
||||
this.execution = execution;
|
||||
this.result = result;
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public ExecutionStatus getExecution() {
|
||||
return execution;
|
||||
}
|
||||
|
||||
public DdiResult getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<String> getDetails() {
|
||||
if (details == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(details);
|
||||
}
|
||||
|
||||
/**
|
||||
* The element status contains information about the execution of the
|
||||
* operation.
|
||||
*
|
||||
*/
|
||||
public enum ExecutionStatus {
|
||||
/**
|
||||
* Execution of the action has finished.
|
||||
*/
|
||||
CLOSED("closed"),
|
||||
|
||||
/**
|
||||
* Execution has started but has not yet finished.
|
||||
*/
|
||||
PROCEEDING("proceeding"),
|
||||
|
||||
/**
|
||||
* Execution was suspended from outside.
|
||||
*/
|
||||
CANCELED("canceled"),
|
||||
|
||||
/**
|
||||
* Action has been noticed and is intended to run.
|
||||
*/
|
||||
SCHEDULED("scheduled"),
|
||||
|
||||
/**
|
||||
* Action was not accepted.
|
||||
*/
|
||||
REJECTED("rejected"),
|
||||
|
||||
/**
|
||||
* Action is started after a reset, power loss, etc.
|
||||
*/
|
||||
RESUMED("resumed"),
|
||||
|
||||
/**
|
||||
* The action has been downloaded by the target.
|
||||
*/
|
||||
DOWNLOADED("downloaded"),
|
||||
|
||||
/**
|
||||
* Target starts to download.
|
||||
*/
|
||||
DOWNLOAD("download");
|
||||
|
||||
private String name;
|
||||
|
||||
ExecutionStatus(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Status [execution=" + execution + ", result=" + result + ", details=" + details + "]";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Copyright (c) 2018 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.JsonValue;
|
||||
|
||||
/**
|
||||
* Enumerates the supported update modes. Each mode represents an attribute
|
||||
* update strategy.
|
||||
*
|
||||
* @see DdiConfigData
|
||||
*/
|
||||
public enum DdiUpdateMode {
|
||||
|
||||
/**
|
||||
* Merge update strategy
|
||||
*/
|
||||
MERGE("merge"),
|
||||
|
||||
/**
|
||||
* Replacement update strategy
|
||||
*/
|
||||
REPLACE("replace"),
|
||||
|
||||
/**
|
||||
* Removal update strategy
|
||||
*/
|
||||
REMOVE("remove");
|
||||
|
||||
private String name;
|
||||
|
||||
DdiUpdateMode(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
package org.eclipse.hawkbit.ddi.rest.api;
|
||||
|
||||
/**
|
||||
* Constants for the direct device integration rest resources.
|
||||
*/
|
||||
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";
|
||||
|
||||
/**
|
||||
* Deployment action resources.
|
||||
*/
|
||||
public static final String DEPLOYMENT_BASE_ACTION = "deploymentBase";
|
||||
|
||||
/**
|
||||
* Cancel action resources.
|
||||
*/
|
||||
public static final String CANCEL_ACTION = "cancelAction";
|
||||
|
||||
/**
|
||||
* Feedback channel.
|
||||
*/
|
||||
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";
|
||||
|
||||
/**
|
||||
* Default value specifying that no action history to be sent as part of
|
||||
* response to deploymentBase
|
||||
* {@link DdiRootControllerRestApi#getControllerBasedeploymentAction}.
|
||||
*/
|
||||
public static final String NO_ACTION_HISTORY = "0";
|
||||
|
||||
private DdiRestConstants() {
|
||||
// constant class, private constructor.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 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 javax.validation.constraints.NotEmpty;
|
||||
|
||||
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.springframework.hateoas.MediaTypes;
|
||||
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.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 tenant
|
||||
* of the client
|
||||
* @param controllerId
|
||||
* of the target that matches to controller id
|
||||
* @param softwareModuleId
|
||||
* of the software module
|
||||
* @return the response
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<DdiArtifact>> getSoftwareModulesArtifacts(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId);
|
||||
|
||||
/**
|
||||
* Root resource for an individual {@link Target}.
|
||||
*
|
||||
* @param tenant
|
||||
* of the request
|
||||
* @param controllerId
|
||||
* of the target that matches to controller id
|
||||
* @param request
|
||||
* the HTTP request injected by spring
|
||||
* @return the response
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{controllerId}", produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId);
|
||||
|
||||
/**
|
||||
* Handles GET {@link DdiArtifact} download request. This could be full or
|
||||
* partial (as specified by RFC7233 (Range Requests)) download request.
|
||||
*
|
||||
* @param tenant
|
||||
* of the request
|
||||
* @param controllerId
|
||||
* of the 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 = "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}")
|
||||
ResponseEntity<InputStream> downloadArtifact(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@PathVariable("fileName") final String fileName);
|
||||
|
||||
/**
|
||||
* Handles GET {@link DdiArtifact} MD5 checksum file download request.
|
||||
*
|
||||
* @param tenant
|
||||
* of the request
|
||||
* @param controllerId
|
||||
* of the 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 = "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{fileName}"
|
||||
+ DdiRestConstants.ARTIFACT_MD5_DWNL_SUFFIX, produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
ResponseEntity<Void> downloadArtifactMd5(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@PathVariable("fileName") final String fileName);
|
||||
|
||||
/**
|
||||
* Resource for software module.
|
||||
*
|
||||
* @param tenant
|
||||
* of the request
|
||||
* @param controllerId
|
||||
* of the target
|
||||
* @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 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}.
|
||||
* actionHistoryMessageCount < 0, retrieves the maximum allowed
|
||||
* number of action status messages from history;
|
||||
* actionHistoryMessageCount = 0, does not retrieve any message;
|
||||
* and actionHistoryMessageCount > 0, retrieves the specified
|
||||
* number of messages, limited by maximum allowed number.
|
||||
* @param request
|
||||
* the HTTP request injected by spring
|
||||
* @return the response
|
||||
*/
|
||||
@RequestMapping(value = "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION
|
||||
+ "/{actionId}", method = RequestMethod.GET, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<DdiDeploymentBase> getControllerBasedeploymentAction(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") @NotEmpty final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId,
|
||||
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource,
|
||||
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount);
|
||||
|
||||
/**
|
||||
* This is the feedback channel for the {@link DdiDeploymentBase} action.
|
||||
*
|
||||
* @param tenant
|
||||
* of the client
|
||||
* @param feedback
|
||||
* to provide
|
||||
* @param controllerId
|
||||
* 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 = "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}/"
|
||||
+ DdiRestConstants.FEEDBACK, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
ResponseEntity<Void> postBasedeploymentActionFeedback(@Valid final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId);
|
||||
|
||||
/**
|
||||
* This is the feedback channel for the config data action.
|
||||
*
|
||||
* @param tenant
|
||||
* of the client
|
||||
* @param configData
|
||||
* as body
|
||||
* @param controllerId
|
||||
* to provide data for
|
||||
* @param request
|
||||
* the HTTP request injected by spring
|
||||
*
|
||||
* @return status of the request
|
||||
*/
|
||||
@RequestMapping(value = "/{controllerId}/"
|
||||
+ DdiRestConstants.CONFIG_DATA_ACTION, method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
ResponseEntity<Void> putConfigData(@Valid final DdiConfigData configData,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId);
|
||||
|
||||
/**
|
||||
* RequestMethod.GET method for the {@link DdiCancel} action.
|
||||
*
|
||||
* @param tenant
|
||||
* of the request
|
||||
* @param controllerId
|
||||
* 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 = "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION
|
||||
+ "/{actionId}", method = RequestMethod.GET, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<DdiCancel> getControllerCancelAction(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") @NotEmpty final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId);
|
||||
|
||||
/**
|
||||
* RequestMethod.POST method receiving the {@link DdiActionFeedback} from
|
||||
* the target.
|
||||
*
|
||||
* @param tenant
|
||||
* of the client
|
||||
* @param feedback
|
||||
* the {@link DdiActionFeedback} from the target.
|
||||
* @param controllerId
|
||||
* 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 = "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + "/{actionId}/"
|
||||
+ DdiRestConstants.FEEDBACK, method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
ResponseEntity<Void> postCancelActionFeedback(@Valid final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") @NotEmpty final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId);
|
||||
|
||||
}
|
||||
13
hawkbit-rest/hawkbit-ddi-resource/README.md
Normal file
13
hawkbit-rest/hawkbit-ddi-resource/README.md
Normal 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
|
||||
```
|
||||
|
||||
131
hawkbit-rest/hawkbit-ddi-resource/pom.xml
Normal file
131
hawkbit-rest/hawkbit-ddi-resource/pom.xml
Normal file
@@ -0,0 +1,131 @@
|
||||
<!--
|
||||
|
||||
Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
which accompanies this distribution, and is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
|
||||
-->
|
||||
|
||||
<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-rest-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-ddi-resource</artifactId>
|
||||
<name>hawkBit :: REST :: 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-rest-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.plugin</groupId>
|
||||
<artifactId>spring-plugin-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-test</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.hawkbit</groupId>
|
||||
<artifactId>hawkbit-rest-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<classifier>tests</classifier>
|
||||
<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-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>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>
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.hawkbit.api.ApiType;
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.api.URLPlaceholder;
|
||||
import org.eclipse.hawkbit.api.URLPlaceholder.SoftwareData;
|
||||
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.DdiMetadata;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiPolling;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
import org.eclipse.hawkbit.repository.ControllerManagement;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.rest.data.ResponseList;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.mvc.ControllerLinkBuilder;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Utility class for the DDI API.
|
||||
*/
|
||||
public final class DataConversionHelper {
|
||||
// utility class, private constructor.
|
||||
private DataConversionHelper() {
|
||||
|
||||
}
|
||||
|
||||
static List<DdiChunk> createChunks(final Target target, final Action uAction,
|
||||
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
|
||||
final HttpRequest request, final ControllerManagement controllerManagement) {
|
||||
|
||||
final Map<Long, List<SoftwareModuleMetadata>> metadata = controllerManagement
|
||||
.findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream()
|
||||
.map(SoftwareModule::getId).collect(Collectors.toList()));
|
||||
|
||||
return uAction.getDistributionSet().getModules().stream()
|
||||
.map(module -> new DdiChunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
|
||||
module.getName(),
|
||||
createArtifacts(target, module, artifactUrlHandler, systemManagement, request),
|
||||
mapMetadata(metadata.get(module.getId()))))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
}
|
||||
|
||||
private static List<DdiMetadata> mapMetadata(final List<SoftwareModuleMetadata> metadata) {
|
||||
return CollectionUtils.isEmpty(metadata) ? null
|
||||
: metadata.stream().map(md -> new DdiMetadata(md.getKey(), md.getValue())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static String mapChunkLegacyKeys(final String key) {
|
||||
if ("application".equals(key)) {
|
||||
return "bApp";
|
||||
}
|
||||
if ("runtime".equals(key)) {
|
||||
return "jvm";
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static List<DdiArtifact> createArtifacts(final Target target, final SoftwareModule module,
|
||||
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
|
||||
final HttpRequest request) {
|
||||
|
||||
return new ResponseList<>(module.getArtifacts().stream()
|
||||
.map(artifact -> createArtifact(target, artifactUrlHandler, artifact, systemManagement, request))
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private static DdiArtifact createArtifact(final Target target, final ArtifactUrlHandler artifactUrlHandler,
|
||||
final Artifact artifact, final SystemManagement systemManagement, final HttpRequest request) {
|
||||
final DdiArtifact file = new DdiArtifact();
|
||||
file.setHashes(new DdiArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash()));
|
||||
file.setFilename(artifact.getFilename());
|
||||
file.setSize(artifact.getSize());
|
||||
|
||||
artifactUrlHandler
|
||||
.getUrls(new URLPlaceholder(systemManagement.getTenantMetadata().getTenant(),
|
||||
systemManagement.getTenantMetadata().getId(), target.getControllerId(), target.getId(),
|
||||
new SoftwareData(artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getId(),
|
||||
artifact.getSha1Hash())),
|
||||
ApiType.DDI, request.getURI())
|
||||
.forEach(entry -> file.add(new Link(entry.getRef()).withRel(entry.getRel())));
|
||||
|
||||
return file;
|
||||
|
||||
}
|
||||
|
||||
static DdiControllerBase fromTarget(final Target target, final Action action,
|
||||
final String defaultControllerPollTime, final TenantAware tenantAware) {
|
||||
final DdiControllerBase result = new DdiControllerBase(
|
||||
new DdiConfig(new DdiPolling(defaultControllerPollTime)));
|
||||
|
||||
if (action != null) {
|
||||
if (action.isCancelingOrCanceled()) {
|
||||
result.add(ControllerLinkBuilder
|
||||
.linkTo(ControllerLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||
.getControllerCancelAction(tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
action.getId()))
|
||||
.withRel(DdiRestConstants.CANCEL_ACTION));
|
||||
} else {
|
||||
// we need to add the hashcode here of the actionWithStatus
|
||||
// because the action might
|
||||
// have changed from 'soft' to 'forced' type and we need to
|
||||
// change the payload of the
|
||||
// response because of eTags.
|
||||
result.add(ControllerLinkBuilder
|
||||
.linkTo(ControllerLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||
.getControllerBasedeploymentAction(tenantAware.getCurrentTenant(),
|
||||
target.getControllerId(), action.getId(), calculateEtag(action), null))
|
||||
.withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION));
|
||||
}
|
||||
}
|
||||
|
||||
if (target.isRequestControllerAttributes()) {
|
||||
result.add(ControllerLinkBuilder
|
||||
.linkTo(ControllerLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||
.putConfigData(null, tenantAware.getCurrentTenant(), target.getControllerId()))
|
||||
.withRel(DdiRestConstants.CONFIG_DATA_ACTION));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates an etag for the given {@link Action} based on the entities
|
||||
* hashcode and the {@link Action#isHitAutoForceTime(long)} to reflect a
|
||||
* force switch.
|
||||
*
|
||||
* @param action
|
||||
* to calculate the etag for
|
||||
* @return the etag
|
||||
*/
|
||||
private static int calculateEtag(final Action action) {
|
||||
final int prime = 31;
|
||||
int result = action.hashCode();
|
||||
int offsetPrime = action.isHitAutoForceTime(System.currentTimeMillis()) ? 1231 : 1237;
|
||||
offsetPrime = (action.hasMaintenanceSchedule() && action.isMaintenanceWindowAvailable()) ? 1249 : offsetPrime;
|
||||
|
||||
result = prime * result + offsetPrime;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.RestConfiguration;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
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
|
||||
* Direct Device Integration API.
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@Import(RestConfiguration.class)
|
||||
public class DdiApiConfiguration {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,596 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
|
||||
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.DdiDeployment.DdiMaintenanceWindowStatus;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult.FinalResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiUpdateMode;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
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.EntityFactory;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.SystemManagement;
|
||||
import org.eclipse.hawkbit.repository.UpdateMode;
|
||||
import org.eclipse.hawkbit.repository.builder.ActionStatusCreate;
|
||||
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.ArtifactBinaryNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.SoftwareModuleNotAssignedToTargetException;
|
||||
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.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.rest.util.FileStreamingUtil;
|
||||
import org.eclipse.hawkbit.rest.util.HttpUtil;
|
||||
import org.eclipse.hawkbit.rest.util.RequestResponseContextHolder;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
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.ApplicationContext;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.server.ServletServerHttpRequest;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* 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
|
||||
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
|
||||
public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
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
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
@Autowired
|
||||
private ControllerManagement controllerManagement;
|
||||
|
||||
@Autowired
|
||||
private ArtifactManagement artifactManagement;
|
||||
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
@Autowired
|
||||
private TenantAware tenantAware;
|
||||
|
||||
@Autowired
|
||||
private SystemManagement systemManagement;
|
||||
|
||||
@Autowired
|
||||
private ArtifactUrlHandler artifactUrlHandler;
|
||||
|
||||
@Autowired
|
||||
private RequestResponseContextHolder requestResponseContextHolder;
|
||||
|
||||
@Autowired
|
||||
private EntityFactory entityFactory;
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<DdiArtifact>> getSoftwareModulesArtifacts(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId) {
|
||||
LOG.debug("getSoftwareModulesArtifacts({})", controllerId);
|
||||
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
final SoftwareModule softwareModule = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
|
||||
return new ResponseEntity<>(
|
||||
DataConversionHelper.createArtifacts(target, softwareModule, artifactUrlHandler, systemManagement,
|
||||
new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest())),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId) {
|
||||
LOG.debug("getControllerBase({})", controllerId);
|
||||
|
||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotexist(controllerId, IpUtil
|
||||
.getClientIpFromRequest(requestResponseContextHolder.getHttpServletRequest(), securityProperties));
|
||||
final Action action = controllerManagement.findOldestActiveActionByTarget(controllerId).orElse(null);
|
||||
|
||||
checkAndCancelExpiredAction(action);
|
||||
|
||||
return new ResponseEntity<>(
|
||||
DataConversionHelper.fromTarget(target, action,
|
||||
action == null ? controllerManagement.getPollingTime()
|
||||
: controllerManagement.getPollingTimeForAction(action.getId()),
|
||||
tenantAware),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<InputStream> downloadArtifact(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@PathVariable("fileName") final String fileName) {
|
||||
final ResponseEntity<InputStream> result;
|
||||
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
|
||||
if (checkModule(fileName, module)) {
|
||||
LOG.warn("Softare module with id {} could not be found.", softwareModuleId);
|
||||
result = ResponseEntity.notFound().build();
|
||||
} else {
|
||||
|
||||
// Exception squid:S3655 - Optional access is checked in checkModule
|
||||
// subroutine
|
||||
@SuppressWarnings("squid:S3655")
|
||||
final Artifact artifact = module.getArtifactByFilename(fileName).get();
|
||||
|
||||
final AbstractDbArtifact file = artifactManagement.loadArtifactBinary(artifact.getSha1Hash())
|
||||
.orElseThrow(() -> new ArtifactBinaryNotFoundException(artifact.getSha1Hash()));
|
||||
|
||||
final String ifMatch = requestResponseContextHolder.getHttpServletRequest().getHeader(HttpHeaders.IF_MATCH);
|
||||
if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
|
||||
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
|
||||
} else {
|
||||
final ActionStatus action = checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(),
|
||||
target, module.getId());
|
||||
|
||||
final Long statusId = action.getId();
|
||||
|
||||
result = FileStreamingUtil.writeFileResponse(file, artifact.getFilename(), artifact.getCreatedAt(),
|
||||
requestResponseContextHolder.getHttpServletResponse(),
|
||||
requestResponseContextHolder.getHttpServletRequest(),
|
||||
(length, shippedSinceLastEvent, total) -> eventPublisher
|
||||
.publishEvent(new DownloadProgressEvent(tenantAware.getCurrentTenant(), statusId,
|
||||
shippedSinceLastEvent, applicationContext.getId())));
|
||||
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ActionStatus checkAndLogDownload(final HttpServletRequest request, final Target target, final Long module) {
|
||||
final Action action = controllerManagement
|
||||
.getActionForDownloadByTargetAndSoftwareModule(target.getControllerId(), module)
|
||||
.orElseThrow(() -> new SoftwareModuleNotAssignedToTargetException(module, target.getControllerId()));
|
||||
final String range = request.getHeader("Range");
|
||||
|
||||
String message;
|
||||
if (range != null) {
|
||||
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads range " + range + " of: "
|
||||
+ request.getRequestURI();
|
||||
} else {
|
||||
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI();
|
||||
}
|
||||
|
||||
return controllerManagement.addInformationalActionStatus(
|
||||
entityFactory.actionStatus().create(action.getId()).status(Status.DOWNLOAD).message(message));
|
||||
}
|
||||
|
||||
private static boolean checkModule(final String fileName, final SoftwareModule module) {
|
||||
return null == module || !module.getArtifactByFilename(fileName).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
// Exception squid:S3655 - Optional access is checked in checkModule
|
||||
// subroutine
|
||||
@SuppressWarnings("squid:S3655")
|
||||
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@PathVariable("fileName") final String fileName) {
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
|
||||
if (checkModule(fileName, module)) {
|
||||
LOG.warn("Software module with id {} could not be found.", softwareModuleId);
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
final Artifact artifact = module.getArtifactByFilename(fileName)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Artifact.class, fileName));
|
||||
|
||||
checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), target, module.getId());
|
||||
|
||||
try {
|
||||
FileStreamingUtil.writeMD5FileResponse(requestResponseContextHolder.getHttpServletResponse(),
|
||||
artifact.getMd5Hash(), fileName);
|
||||
} catch (final IOException e) {
|
||||
LOG.error("Failed to stream MD5 File", e);
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<DdiDeploymentBase> getControllerBasedeploymentAction(
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("actionId") final Long actionId,
|
||||
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource,
|
||||
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
|
||||
LOG.debug("getControllerBasedeploymentAction({},{})", controllerId, resource);
|
||||
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
LOG.warn(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
checkAndCancelExpiredAction(action);
|
||||
|
||||
if (!action.isCancelingOrCanceled()) {
|
||||
|
||||
final List<DdiChunk> chunks = DataConversionHelper.createChunks(target, action, artifactUrlHandler,
|
||||
systemManagement,
|
||||
new ServletServerHttpRequest(requestResponseContextHolder.getHttpServletRequest()),
|
||||
controllerManagement);
|
||||
|
||||
final List<String> actionHistoryMsgs = controllerManagement.getActionHistoryMessages(action.getId(),
|
||||
actionHistoryMessageCount == null ? Integer.parseInt(DdiRestConstants.NO_ACTION_HISTORY)
|
||||
: actionHistoryMessageCount);
|
||||
|
||||
final DdiActionHistory actionHistory = actionHistoryMsgs.isEmpty() ? null
|
||||
: new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs);
|
||||
|
||||
final HandlingType downloadType = action.isForce() ? HandlingType.FORCED : HandlingType.ATTEMPT;
|
||||
final HandlingType updateType = calculateUpdateType(action, downloadType);
|
||||
|
||||
final DdiMaintenanceWindowStatus maintenanceWindow = calculateMaintenanceWindow(action);
|
||||
|
||||
final DdiDeploymentBase base = new DdiDeploymentBase(Long.toString(action.getId()),
|
||||
new DdiDeployment(downloadType, updateType, chunks, maintenanceWindow), actionHistory);
|
||||
|
||||
LOG.debug("Found an active UpdateAction for target {}. returning deyploment: {}", controllerId, base);
|
||||
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved update action and should start now the download.");
|
||||
|
||||
return new ResponseEntity<>(base, HttpStatus.OK);
|
||||
}
|
||||
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
private static DdiMaintenanceWindowStatus calculateMaintenanceWindow(final Action action) {
|
||||
if (action.hasMaintenanceSchedule()) {
|
||||
return action.isMaintenanceWindowAvailable() ? DdiMaintenanceWindowStatus.AVAILABLE
|
||||
: DdiMaintenanceWindowStatus.UNAVAILABLE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static HandlingType calculateUpdateType(final Action action, final HandlingType downloadType) {
|
||||
if (action.hasMaintenanceSchedule()) {
|
||||
return action.isMaintenanceWindowAvailable() ? downloadType : HandlingType.SKIP;
|
||||
}
|
||||
return downloadType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> postBasedeploymentActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId) {
|
||||
LOG.debug("provideBasedeploymentActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback);
|
||||
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
if (!actionId.equals(feedback.getId())) {
|
||||
LOG.warn(
|
||||
"provideBasedeploymentActionFeedback: action in payload ({}) was not identical to action in path ({}).",
|
||||
feedback.getId(), actionId);
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
LOG.warn(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
if (!action.isActive()) {
|
||||
LOG.warn("Updating action {} with feedback {} not possible since action not active anymore.",
|
||||
action.getId(), feedback.getId());
|
||||
return new ResponseEntity<>(HttpStatus.GONE);
|
||||
}
|
||||
|
||||
controllerManagement.addUpdateActionStatus(generateUpdateStatus(feedback, controllerId, feedback.getId()));
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
|
||||
}
|
||||
|
||||
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId,
|
||||
final Long actionid) {
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
|
||||
if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) {
|
||||
messages.addAll(feedback.getStatus().getDetails());
|
||||
}
|
||||
|
||||
Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
LOG.debug("Controller confirmed cancel (actionid: {}, controllerId: {}) as we got {} report.", actionid,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.CANCELED;
|
||||
addMessageIfEmpty("Target confirmed cancelation.", messages);
|
||||
break;
|
||||
case REJECTED:
|
||||
LOG.info("Controller reported internal error (actionid: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.WARNING;
|
||||
addMessageIfEmpty("Target REJECTED update", messages);
|
||||
break;
|
||||
case CLOSED:
|
||||
status = handleClosedCase(feedback, controllerId, actionid, messages);
|
||||
break;
|
||||
case DOWNLOAD:
|
||||
LOG.debug("Controller confirmed status of download (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.DOWNLOAD;
|
||||
addMessageIfEmpty("Target confirmed download start", messages);
|
||||
break;
|
||||
case DOWNLOADED:
|
||||
LOG.debug("Controller confirmed download (actionId: {}, controllerId: {}) as we got {} report.", actionid,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.DOWNLOADED;
|
||||
addMessageIfEmpty("Target confirmed download finished", messages);
|
||||
break;
|
||||
default:
|
||||
status = handleDefaultCase(feedback, controllerId, actionid, messages);
|
||||
break;
|
||||
}
|
||||
|
||||
return entityFactory.actionStatus().create(actionid).status(status).messages(messages);
|
||||
}
|
||||
|
||||
private static void addMessageIfEmpty(final String text, final List<String> messages) {
|
||||
if (messages != null && messages.isEmpty()) {
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + text + ".");
|
||||
}
|
||||
}
|
||||
|
||||
private Status handleDefaultCase(final DdiActionFeedback feedback, final String controllerId, final Long actionid,
|
||||
final List<String> messages) {
|
||||
Status status;
|
||||
LOG.debug("Controller reported intermediate status (actionid: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, controllerId, feedback.getStatus().getExecution());
|
||||
status = Status.RUNNING;
|
||||
addMessageIfEmpty("Target reported " + feedback.getStatus().getExecution(), messages);
|
||||
return status;
|
||||
}
|
||||
|
||||
private Status handleClosedCase(final DdiActionFeedback feedback, final String controllerId, final Long actionid,
|
||||
final List<String> messages) {
|
||||
Status status;
|
||||
LOG.debug("Controller reported closed (actionid: {}, controllerId: {}) as we got {} report.", actionid,
|
||||
controllerId, feedback.getStatus().getExecution());
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
status = Status.ERROR;
|
||||
addMessageIfEmpty("Target reported CLOSED with ERROR!", messages);
|
||||
} else {
|
||||
status = Status.FINISHED;
|
||||
addMessageIfEmpty("Target reported CLOSED with OK!", messages);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) {
|
||||
|
||||
controllerManagement.updateControllerAttributes(controllerId, configData.getData(), getUpdateMode(configData));
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<DdiCancel> getControllerCancelAction(@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") @NotEmpty final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId) {
|
||||
LOG.debug("getControllerCancelAction({})", controllerId);
|
||||
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
LOG.warn(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
if (action.isCancelingOrCanceled()) {
|
||||
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: {}", controllerId, cancel);
|
||||
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved cancel action and should start now the cancelation.");
|
||||
|
||||
return new ResponseEntity<>(cancel, HttpStatus.OK);
|
||||
}
|
||||
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> postCancelActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") @NotEmpty final String controllerId,
|
||||
@PathVariable("actionId") @NotEmpty final Long actionId) {
|
||||
LOG.debug("provideCancelActionFeedback for target [{}]: {}", controllerId, feedback);
|
||||
|
||||
final Target target = controllerManagement.getByControllerId(controllerId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||
|
||||
if (!actionId.equals(feedback.getId())) {
|
||||
LOG.warn(
|
||||
"provideBasedeploymentActionFeedback: action in payload ({}) was not identical to action in path ({}).",
|
||||
feedback.getId(), actionId);
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
final Action action = findActionWithExceptionIfNotFound(actionId);
|
||||
if (!action.getTarget().getId().equals(target.getId())) {
|
||||
LOG.warn(GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET, action.getId(), target.getId());
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
controllerManagement
|
||||
.addCancelActionStatus(generateActionCancelStatus(feedback, target, feedback.getId(), entityFactory));
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
private static ActionStatusCreate generateActionCancelStatus(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionid, final EntityFactory entityFactory) {
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
status = handleCaseCancelCanceled(feedback, target, actionid, messages);
|
||||
break;
|
||||
case REJECTED:
|
||||
LOG.info("Target rejected the cancelation request (actionid: {}, controllerId: {}).", actionid,
|
||||
target.getControllerId());
|
||||
status = Status.CANCEL_REJECTED;
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancelation request.");
|
||||
break;
|
||||
case CLOSED:
|
||||
status = handleCancelClosedCase(feedback, messages);
|
||||
break;
|
||||
default:
|
||||
status = Status.RUNNING;
|
||||
break;
|
||||
}
|
||||
|
||||
if (feedback.getStatus().getDetails() != null) {
|
||||
messages.addAll(feedback.getStatus().getDetails());
|
||||
}
|
||||
|
||||
return entityFactory.actionStatus().create(actionid).status(status).messages(messages);
|
||||
|
||||
}
|
||||
|
||||
private static Status handleCancelClosedCase(final DdiActionFeedback feedback, final List<String> messages) {
|
||||
Status status;
|
||||
if (feedback.getStatus().getResult().getFinished() == FinalResult.FAILURE) {
|
||||
status = Status.ERROR;
|
||||
addMessageIfEmpty("Target was not able to complete cancelation", messages);
|
||||
} else {
|
||||
status = Status.CANCELED;
|
||||
addMessageIfEmpty("Cancelation confirmed", messages);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
private static Status handleCaseCancelCanceled(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionid, final List<String> messages) {
|
||||
Status status;
|
||||
LOG.error(
|
||||
"Target reported cancel for a cancel which is not supported by the server (actionid: {}, controllerId: {}) as we got {} report.",
|
||||
actionid, target.getControllerId(), feedback.getStatus().getExecution());
|
||||
status = Status.WARNING;
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target reported cancel for a cancel which is not supported by the server.");
|
||||
return status;
|
||||
}
|
||||
|
||||
private Action findActionWithExceptionIfNotFound(final Long actionId) {
|
||||
return controllerManagement.findActionWithDetails(actionId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* If the action has a maintenance schedule defined but is no longer valid,
|
||||
* cancel the action.
|
||||
*
|
||||
* @param action
|
||||
* is the {@link Action} to check.
|
||||
*/
|
||||
private void checkAndCancelExpiredAction(final Action action) {
|
||||
if (action != null && action.hasMaintenanceSchedule() && action.isMaintenanceScheduleLapsed()) {
|
||||
try {
|
||||
controllerManagement.cancelAction(action.getId());
|
||||
} catch (final CancelActionNotAllowedException e) {
|
||||
LOG.info("Cancel action not allowed exception :{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the update mode from the given update message.
|
||||
*/
|
||||
private static UpdateMode getUpdateMode(final DdiConfigData configData) {
|
||||
final DdiUpdateMode mode = configData.getMode();
|
||||
if (mode != null) {
|
||||
return UpdateMode.valueOf(mode.name());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
@SpringApplicationConfiguration(classes = { DdiApiConfiguration.class })
|
||||
@TestPropertySource(locations = "classpath:/ddi-test.properties")
|
||||
public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrationTest {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test artifact downloads from the controller.
|
||||
*/
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Artifact Download Resource")
|
||||
@SpringApplicationConfiguration(classes = DownloadTestConfiguration.class)
|
||||
public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
private static volatile int downLoadProgress = 0;
|
||||
private static volatile long shippedBytes = 0;
|
||||
|
||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH);
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests non allowed requests on the artifact ressource, e.g. invalid URI, wrong if-match, wrong command.")
|
||||
public void invalidRequestsOnArtifactResource() throws Exception {
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final List<Target> targets = Arrays.asList(target);
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
assignDistributionSet(ds, targets);
|
||||
|
||||
// create artifact
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random),
|
||||
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize);
|
||||
|
||||
// no artifact available
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/123455",
|
||||
target.getControllerId(), getOsModule(ds))).andExpect(status().isNotFound());
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/123455.MD5SUM",
|
||||
target.getControllerId(), getOsModule(ds))).andExpect(status().isNotFound());
|
||||
|
||||
// SM does not exist
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/1234567890/artifacts/{filename}",
|
||||
target.getControllerId(), artifact.getFilename())).andExpect(status().isNotFound());
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/1234567890/artifacts/{filename}.MD5SUM",
|
||||
target.getControllerId(), artifact.getFilename())).andExpect(status().isNotFound());
|
||||
|
||||
// test now consistent data to test allowed methods
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||
.header(HttpHeaders.IF_MATCH, artifact.getSha1Hash()))
|
||||
.andExpect(status().isOk());
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// test failed If-match
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||
.header(HttpHeaders.IF_MATCH, "fsjkhgjfdhg"))
|
||||
.andExpect(status().isPreconditionFailed());
|
||||
|
||||
// test invalid range
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||
.header("Range", "bytes=1-10,hdsfjksdh"))
|
||||
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
|
||||
.andExpect(status().isRequestedRangeNotSatisfiable());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||
.header("Range", "bytes=100-10"))
|
||||
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
|
||||
.andExpect(status().isRequestedRangeNotSatisfiable());
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "4712", authorities = "ROLE_CONTROLLER", allSpPermissions = true)
|
||||
@Description("Tests valid downloads through the artifact resource by identifying the artifact not by ID but file name.")
|
||||
public void downloadArtifactThroughFileName() throws Exception {
|
||||
downLoadProgress = 1;
|
||||
shippedBytes = 0;
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(0);
|
||||
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final List<Target> targets = Arrays.asList(target);
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
// create artifact
|
||||
final int artifactSize = 5 * 1024 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random),
|
||||
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize);
|
||||
|
||||
// download fails as artifact is not yet assigned
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
target.getControllerId(), getOsModule(ds), artifact.getFilename())).andExpect(status().isNotFound());
|
||||
|
||||
// now assign and download successful
|
||||
assignDistributionSet(ds, targets);
|
||||
final MvcResult result = mvc.perform(get(
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename()))
|
||||
.andReturn();
|
||||
|
||||
assertTrue("The same file that was uploaded is expected when downloaded",
|
||||
Arrays.equals(result.getResponse().getContentAsByteArray(), random));
|
||||
|
||||
// download complete
|
||||
assertThat(downLoadProgress).isEqualTo(10);
|
||||
assertThat(shippedBytes).isEqualTo(artifactSize);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests valid MD5SUm file downloads through the artifact resource by identifying the artifact by ID.")
|
||||
public void downloadMd5sumThroughControllerApi() throws Exception {
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds, target);
|
||||
|
||||
// create artifact
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "file1",
|
||||
false, artifactSize);
|
||||
|
||||
// download
|
||||
final MvcResult result = mvc.perform(get(
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isOk()).andExpect(header().string("Content-Disposition",
|
||||
"attachment;filename=" + artifact.getFilename() + ".MD5SUM"))
|
||||
.andReturn();
|
||||
|
||||
assertThat(result.getResponse().getContentAsByteArray())
|
||||
.isEqualTo((artifact.getMd5Hash() + " " + artifact.getFilename()).getBytes(Charsets.US_ASCII));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(principal = TestdataFactory.DEFAULT_CONTROLLER_ID, authorities = "ROLE_CONTROLLER", allSpPermissions = true)
|
||||
@Description("Test various HTTP range requests for artifact download, e.g. chunk download or download resume.")
|
||||
public void rangeDownloadArtifact() throws Exception {
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final List<Target> targets = Arrays.asList(target);
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
final int resultLength = 5 * 1000 * 1024;
|
||||
|
||||
// create artifact
|
||||
final byte random[] = RandomUtils.nextBytes(resultLength);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "file1",
|
||||
false, resultLength);
|
||||
|
||||
assertThat(random.length).isEqualTo(resultLength);
|
||||
|
||||
// now assign and download successful
|
||||
assignDistributionSet(ds, targets);
|
||||
|
||||
final int range = 100 * 1024;
|
||||
|
||||
// full file download with standard range request
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < resultLength / range; i++) {
|
||||
final String rangeString = "" + i * range + "-" + ((i + 1) * range - 1);
|
||||
|
||||
final MvcResult result = mvc.perform(get(
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range",
|
||||
"bytes=" + rangeString))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().longValue("Content-Length", range))
|
||||
.andExpect(header().string("Content-Range", "bytes " + rangeString + "/" + resultLength))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
|
||||
outputStream.write(result.getResponse().getContentAsByteArray());
|
||||
}
|
||||
|
||||
assertThat(outputStream.toByteArray()).isEqualTo(random);
|
||||
|
||||
// return last 1000 Bytes
|
||||
MvcResult result = mvc.perform(
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=-1000"))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().longValue("Content-Length", 1000))
|
||||
.andExpect(header().string("Content-Range",
|
||||
"bytes " + (resultLength - 1000) + "-" + (resultLength - 1) + "/" + resultLength))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
|
||||
assertThat(result.getResponse().getContentAsByteArray())
|
||||
.isEqualTo(Arrays.copyOfRange(random, resultLength - 1000, resultLength));
|
||||
|
||||
// skip first 1000 Bytes and return the rest
|
||||
result = mvc.perform(
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=1000-"))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().longValue("Content-Length", resultLength - 1000))
|
||||
.andExpect(header().string("Content-Range",
|
||||
"bytes " + 1000 + "-" + (resultLength - 1) + "/" + resultLength))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
|
||||
assertThat(result.getResponse().getContentAsByteArray())
|
||||
.isEqualTo(Arrays.copyOfRange(random, 1000, resultLength));
|
||||
|
||||
// Start download from file end fails
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=" + random.length + "-"))
|
||||
.andExpect(status().isRequestedRangeNotSatisfiable())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().string("Content-Range", "bytes */" + random.length))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1"));
|
||||
|
||||
// multipart download - first 20 bytes in 2 parts
|
||||
result = mvc.perform(
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=0-9,10-19"))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART"))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
|
||||
outputStream.reset();
|
||||
|
||||
outputStream.write("\r\n--THIS_STRING_SEPARATES_MULTIPART\r\n".getBytes(StandardCharsets.ISO_8859_1));
|
||||
outputStream.write(("Content-Range: bytes 0-9/" + resultLength + "\r\n").getBytes(StandardCharsets.ISO_8859_1));
|
||||
outputStream.write(Arrays.copyOfRange(random, 0, 10));
|
||||
outputStream.write("\r\n--THIS_STRING_SEPARATES_MULTIPART\r\n".getBytes(StandardCharsets.ISO_8859_1));
|
||||
outputStream
|
||||
.write(("Content-Range: bytes 10-19/" + resultLength + "\r\n").getBytes(StandardCharsets.ISO_8859_1));
|
||||
outputStream.write(Arrays.copyOfRange(random, 10, 20));
|
||||
outputStream.write("\r\n--THIS_STRING_SEPARATES_MULTIPART--".getBytes(StandardCharsets.ISO_8859_1));
|
||||
|
||||
assertThat(result.getResponse().getContentAsByteArray()).isEqualTo(outputStream.toByteArray());
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class DownloadTestConfiguration {
|
||||
|
||||
@Bean
|
||||
public Listener cancelEventHandlerStubBean() {
|
||||
return new Listener();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class Listener {
|
||||
|
||||
@EventListener(classes = DownloadProgressEvent.class)
|
||||
public static void listen(final DownloadProgressEvent event) {
|
||||
downLoadProgress++;
|
||||
shippedBytes += event.getShippedBytesSinceLast();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
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.repository.test.util.TestdataFactory;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test cancel action from the controller.
|
||||
*/
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Cancel Action Resource")
|
||||
public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test of the controller can continue a started update even after a cancel command if it so desires.")
|
||||
public void rootRsCancelActionButContinueAnyway() throws Exception {
|
||||
// prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget();
|
||||
|
||||
final Long actionId = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getActions().get(0);
|
||||
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
// controller rejects cancelation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "rejected"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
|
||||
// get update action anyway
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId,
|
||||
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].version",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].version",
|
||||
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].version",
|
||||
contains(ds.findFirstModuleByType(appType).get().getVersion())));
|
||||
|
||||
// and finish it
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
||||
+ actionId + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(actionId.toString(), "closed", "success"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
// check database after test
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||
.isEqualTo(ds);
|
||||
assertThat(deploymentManagement.getInstalledDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||
.isEqualTo(ds);
|
||||
assertThat(
|
||||
targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getInstallationDate())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test for cancel operation of a update action.")
|
||||
public void rootRsCancelAction() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget();
|
||||
|
||||
final Long actionId = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getActions().get(0);
|
||||
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(APPLICATION_JSON_HAL_UTF))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId)));
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
// Retrieved is reported
|
||||
|
||||
List<Action> activeActionsByTarget = deploymentManagement
|
||||
.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent();
|
||||
|
||||
assertThat(activeActionsByTarget).hasSize(1);
|
||||
assertThat(activeActionsByTarget.get(0).getStatus()).isEqualTo(Status.RUNNING);
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent();
|
||||
|
||||
// the canceled action should still be active!
|
||||
assertThat(cancelAction.isActive()).isTrue();
|
||||
assertThat(activeActionsByTarget).hasSize(1);
|
||||
assertThat(activeActionsByTarget.get(0).getStatus()).isEqualTo(Status.CANCELING);
|
||||
|
||||
current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId())));
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
current = System.currentTimeMillis();
|
||||
assertThat(targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
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_UTF8))
|
||||
.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())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
|
||||
// controller confirmed cancelled action, should not be active anymore
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)
|
||||
.content(JsonBuilder.cancelActionFeedback(actionId.toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent();
|
||||
assertThat(activeActionsByTarget).hasSize(0);
|
||||
final Action canceledAction = deploymentManagement.findAction(cancelAction.getId()).get();
|
||||
assertThat(canceledAction.isActive()).isFalse();
|
||||
assertThat(canceledAction.getStatus()).isEqualTo(Status.CANCELED);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests various bad requests and if the server handles them as expected.")
|
||||
public void badCancelAction() throws Exception {
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
createCancelAction("34534543");
|
||||
|
||||
// wrong media type
|
||||
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotAcceptable());
|
||||
|
||||
}
|
||||
|
||||
private Action createCancelAction(final String targetid) {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet(targetid);
|
||||
final Target savedTarget = testdataFactory.createTarget(targetid);
|
||||
final List<Target> toAssign = new ArrayList<>();
|
||||
toAssign.add(savedTarget);
|
||||
final Long actionId = assignDistributionSet(ds, toAssign).getActions().get(0);
|
||||
|
||||
return deploymentManagement.cancelAction(actionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the feedback channel of the cancel operation.")
|
||||
public void rootRsCancelActionFeedback() throws Exception {
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget();
|
||||
|
||||
final Long actionId = assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID).getActions()
|
||||
.get(0);
|
||||
|
||||
// cancel action manually
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "proceeding"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(3);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "resumed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(4);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "scheduled"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(5);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
// cancellation canceled -> should remove the action from active
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "canceled"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
// cancellation rejected -> action still active until controller close
|
||||
// it
|
||||
// with finished or
|
||||
// error
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "rejected"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(7);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
// update closed -> should remove the action from active
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the feeback chanel of for multiple open cancel operations on the same target.")
|
||||
public void multipleCancelActionFeedback() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("3", true);
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget();
|
||||
|
||||
final Long actionId = assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID).getActions()
|
||||
.get(0);
|
||||
final Long actionId2 = assignDistributionSet(ds2.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID).getActions()
|
||||
.get(0);
|
||||
final Long actionId3 = assignDistributionSet(ds3.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID).getActions()
|
||||
.get(0);
|
||||
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(3);
|
||||
|
||||
// 3 update actions, 0 cancel actions
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(3);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(3);
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
final Action cancelAction2 = deploymentManagement.cancelAction(actionId2);
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).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))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId))));
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction.getId())));
|
||||
|
||||
// now lets return feedback for the first cancelation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(7);
|
||||
|
||||
// 1 update actions, 1 cancel actions
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId2))));
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
equalTo("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
+ TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" + cancelAction2.getId())));
|
||||
|
||||
// now lets return feedback for the second cancelation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction2.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(9);
|
||||
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||
.isEqualTo(ds3);
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
|
||||
tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(10);
|
||||
|
||||
// 1 update actions, 0 cancel actions
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action cancelAction3 = deploymentManagement.cancelAction(actionId3);
|
||||
|
||||
// action is in cancelling state
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||
.isEqualTo(ds3);
|
||||
|
||||
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_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId3))));
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(12);
|
||||
|
||||
// now lets return feedback for the third cancelation
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction3.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(13);
|
||||
|
||||
// final status
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(0);
|
||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the feeback channel closing for too many feedbacks, i.e. denial of service prevention.")
|
||||
public void tooMuchCancelActionFeedback() throws Exception {
|
||||
testdataFactory.createTarget();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Long actionId = assignDistributionSet(ds.getId(), TestdataFactory.DEFAULT_CONTROLLER_ID).getActions()
|
||||
.get(0);
|
||||
|
||||
final Action cancelAction = deploymentManagement.cancelAction(actionId);
|
||||
|
||||
final String feedback = JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "proceeding");
|
||||
// assignDistributionSet creates an ActionStatus and cancel action
|
||||
// stores an action status, so
|
||||
// only 97 action status left
|
||||
for (int i = 0; i < 98; i++) {
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("test the correct rejection of various invalid feedback requests")
|
||||
public void badCancelActionFeedback() throws Exception {
|
||||
final Action cancelAction = createCancelAction(TestdataFactory.DEFAULT_CONTROLLER_ID);
|
||||
final Action cancelAction2 = createCancelAction("4715");
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// bad content type
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_ATOM_XML).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||
|
||||
// bad body
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "546456456"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// invalid action
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback("sdfsdfsdfs", "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback("1234", "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// right action but for wrong target
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction2.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// finally get it right :)
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
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 com.google.common.collect.Maps;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Step;
|
||||
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 DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("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")
|
||||
public void requestConfigDataIfEmpty() throws Exception {
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(APPLICATION_JSON_HAL_UTF))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.configData.href", equalTo(
|
||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
final Map<String, String> attributes = Maps.newHashMapWithExpectedSize(1);
|
||||
attributes.put("dsafsdf", "sdsds");
|
||||
|
||||
final Target updateControllerAttributes = controllerManagement
|
||||
.updateControllerAttributes(savedTarget.getControllerId(), attributes, null);
|
||||
// request controller attributes need to be false because we don't want
|
||||
// to request the controller attributes again
|
||||
assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse();
|
||||
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(APPLICATION_JSON_HAL_UTF))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.configData.href").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "can be uploaded correctly by the controller.")
|
||||
public void putConfigData() throws Exception {
|
||||
testdataFactory.createTarget("4717");
|
||||
|
||||
// initial
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("dsafsdf", "sdsds");
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(targetManagement.getControllerAttributes("4717")).isEqualTo(attributes);
|
||||
|
||||
// update
|
||||
attributes.put("sdsds", "123412");
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
assertThat(targetManagement.getControllerAttributes("4717")).isEqualTo(attributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("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.")
|
||||
public void putTooMuchConfigData() throws Exception {
|
||||
testdataFactory.createTarget("4717");
|
||||
|
||||
// initial
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) {
|
||||
attributes.put("dsafsdf" + i, "sdsds" + i);
|
||||
}
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
attributes = new HashMap<>();
|
||||
attributes.put("on too many", "sdsds");
|
||||
mvc.perform(put("/{tenant}/controller/v1/4717/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "resource behaves as exptected in cae of invalid request attempts.")
|
||||
public void badConfigData() throws Exception {
|
||||
testdataFactory.createTarget("4712");
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).//
|
||||
andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// bad content type
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("dsafsdf", "sdsds");
|
||||
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// bad body
|
||||
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
||||
.content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).")
|
||||
public void putConfigDataWithDifferentUpdateModes() throws Exception {
|
||||
|
||||
// create a target
|
||||
final String controllerId = "4717";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
final String configDataPath = "/{tenant}/controller/v1/" + controllerId + "/configData";
|
||||
|
||||
// no update mode
|
||||
putConfigDataWithoutUpdateMode(controllerId, configDataPath);
|
||||
|
||||
// update mode REPLACE
|
||||
putConfigDataWithUpdateModeReplace(controllerId, configDataPath);
|
||||
|
||||
// update mode MERGE
|
||||
putConfigDataWithUpdateModeMerge(controllerId, configDataPath);
|
||||
|
||||
// update mode REMOVE
|
||||
putConfigDataWithUpdateModeRemove(controllerId, configDataPath);
|
||||
|
||||
// invalid update mode
|
||||
putConfigDataWithInvalidUpdateMode(configDataPath);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithInvalidUpdateMode(final String configDataPath) throws Exception {
|
||||
|
||||
// create some attriutes
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("k0", "v0");
|
||||
attributes.put("k1", "v1");
|
||||
|
||||
// use an invalid update mode
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed", "KJHGKJHGKJHG"))
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeRemove(final String controllerId, final String configDataPath)
|
||||
throws Exception {
|
||||
|
||||
// get the current attributes
|
||||
final int previousSize = targetManagement.getControllerAttributes(controllerId).size();
|
||||
|
||||
// update the attributes using update mode REMOVE
|
||||
final Map<String, String> removeAttributes = new HashMap<>();
|
||||
removeAttributes.put("k1", "foo");
|
||||
removeAttributes.put("k3", "bar");
|
||||
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", removeAttributes, "closed", "remove"))
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute removal
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(previousSize - 2);
|
||||
assertThat(updatedAttributes).doesNotContainKeys("k1", "k3");
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeMerge(final String controllerId, final String configDataPath)
|
||||
throws Exception {
|
||||
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(controllerId));
|
||||
|
||||
// update the attributes using update mode MERGE
|
||||
final Map<String, String> mergeAttributes = new HashMap<>();
|
||||
mergeAttributes.put("k1", "v1_modified_again");
|
||||
mergeAttributes.put("k4", "v4");
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", mergeAttributes, "closed", "merge"))
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute merge
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(4);
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes);
|
||||
assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified_again");
|
||||
attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeReplace(final String controllerId, final String configDataPath)
|
||||
throws Exception {
|
||||
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(controllerId));
|
||||
|
||||
// update the attributes using update mode REPLACE
|
||||
final Map<String, String> replacementAttributes = new HashMap<>();
|
||||
replacementAttributes.put("k1", "v1_modified");
|
||||
replacementAttributes.put("k2", "v2");
|
||||
replacementAttributes.put("k3", "v3");
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", replacementAttributes, "closed", "replace"))
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute replacement
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(replacementAttributes.size());
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes);
|
||||
assertThat(updatedAttributes.get("k1")).isEqualTo("v1_modified");
|
||||
attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithoutUpdateMode(final String controllerId, final String configDataPath)
|
||||
throws Exception {
|
||||
|
||||
// create some attriutes
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("k0", "v0");
|
||||
attributes.put("k1", "v1");
|
||||
|
||||
// set the initial attributes
|
||||
mvc.perform(put(configDataPath, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData("", attributes, "closed")).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
// verify the initial parameters
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(controllerId);
|
||||
assertThat(updatedAttributes.size()).isEqualTo(attributes.size());
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(attributes);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,985 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.lang3.RandomUtils;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test deployment base from the controller.
|
||||
*/
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Deployment Action Resource")
|
||||
public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
private static final String HTTP_LOCALHOST = "http://localhost:8080/";
|
||||
|
||||
@Test
|
||||
@Description("Ensures that artifacts are not found, when softare module does not exists.")
|
||||
public void artifactsNotFound() throws Exception {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final Long softwareModuleIdNotExist = 1l;
|
||||
mvc.perform(get("/{tenant}/controller/v1/{targetNotExist}/softwaremodules/{softwareModuleId}/artifacts",
|
||||
tenantAware.getCurrentTenant(), target.getName(), softwareModuleIdNotExist))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that artifacts are found, when software module exists.")
|
||||
public void artifactsExists() throws Exception {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), target.getName());
|
||||
|
||||
final Long softwareModuleId = distributionSet.getModules().stream().findAny().get().getId();
|
||||
mvc.perform(get("/{tenant}/controller/v1/{targetNotExist}/softwaremodules/{softwareModuleId}/artifacts",
|
||||
tenantAware.getCurrentTenant(), target.getName(), softwareModuleId)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$", hasSize(0)));
|
||||
|
||||
testdataFactory.createArtifacts(softwareModuleId);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/{targetNotExist}/softwaremodules/{softwareModuleId}/artifacts",
|
||||
tenantAware.getCurrentTenant(), target.getName(), softwareModuleId)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$", hasSize(3)))
|
||||
.andExpect(jsonPath("$.[?(@.filename==filename0)]", hasSize(1)))
|
||||
.andExpect(jsonPath("$.[?(@.filename==filename1)]", hasSize(1)))
|
||||
.andExpect(jsonPath("$.[?(@.filename==filename2)]", hasSize(1)));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Forced deployment to a controller. Checks if the resource reponse payload for a given deployment is as expected.")
|
||||
public void deplomentForceAction() throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1",
|
||||
false, artifactSize);
|
||||
final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
|
||||
"test1.signature", false, artifactSize);
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(0);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(0);
|
||||
|
||||
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.FORCED,
|
||||
RepositoryModelConstants.NO_FORCE_TIME, Arrays.asList(savedTarget.getControllerId()))
|
||||
.getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
saved = assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
current = System.currentTimeMillis();
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].name",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].version",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].name",
|
||||
contains(ds.findFirstModuleByType(osType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].version",
|
||||
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].filename", contains("test1")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.md5",
|
||||
contains(artifact.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.sha1",
|
||||
contains(artifact.getSha1Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0]._links.download-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0]._links.md5sum-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1.MD5SUM")))
|
||||
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].filename",
|
||||
contains("test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].hashes.md5",
|
||||
contains(artifactSignature.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].hashes.sha1",
|
||||
contains(artifactSignature.getSha1Hash())))
|
||||
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1]._links.download-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1]._links.md5sum-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1.signature.MD5SUM")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].version",
|
||||
contains(ds.findFirstModuleByType(appType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name",
|
||||
contains(ds.findFirstModuleByType(appType).get().getName())));
|
||||
|
||||
// Retrieved is reported
|
||||
final Iterable<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
.findActionStatusByAction(new PageRequest(0, 100, Direction.DESC, "id"), uaction.getId());
|
||||
assertThat(actionStatusMessages).hasSize(2);
|
||||
final ActionStatus actionStatusMessage = actionStatusMessages.iterator().next();
|
||||
assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Checks that the deployementBase URL changes when the action is switched from soft to forced in TIMEFORCED case.")
|
||||
public void changeEtagIfActionSwitchesFromSoftToForced() throws Exception {
|
||||
// Prepare test data
|
||||
final Target target = testdataFactory.createTarget("4712");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
|
||||
final Long actionId = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.TIMEFORCED,
|
||||
System.currentTimeMillis() + 2_000, Arrays.asList(target.getControllerId())).getActions().get(0);
|
||||
|
||||
MvcResult mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)).andReturn();
|
||||
|
||||
final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
|
||||
.read(mvcResult.getResponse().getContentAsString()).toString();
|
||||
|
||||
// Time is not yet over, so we should see the same URL
|
||||
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)).andReturn();
|
||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).isEqualTo(urlBeforeSwitch)
|
||||
.startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/deploymentBase/" + actionId);
|
||||
|
||||
// After the time is over we should see a new etag
|
||||
TimeUnit.MILLISECONDS.sleep(2_000);
|
||||
|
||||
mvcResult = mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF)).andReturn();
|
||||
|
||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).isNotEqualTo(urlBeforeSwitch);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Attempt/soft deployment to a controller. Checks if the resource reponse payload for a given deployment is as expected.")
|
||||
public void deplomentAttemptAction() throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final String visibleMetadataOsKey = "metaDataVisible";
|
||||
final String visibleMetadataOsValue = "withValue";
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1",
|
||||
false, artifactSize);
|
||||
final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
|
||||
"test1.signature", false, artifactSize);
|
||||
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
|
||||
.key(visibleMetadataOsKey).value(visibleMetadataOsValue).targetVisible(true));
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
|
||||
.key("metaDataNotVisible").value("withValue").targetVisible(false));
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(0);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(0);
|
||||
|
||||
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.SOFT,
|
||||
RepositoryModelConstants.NO_FORCE_TIME, Arrays.asList(savedTarget.getControllerId()))
|
||||
.getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
saved = assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712/deploymentBase/" + uaction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("attempt")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("attempt")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].name",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].version",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].name",
|
||||
contains(ds.findFirstModuleByType(osType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].version",
|
||||
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].metadata[0].key").value(visibleMetadataOsKey))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part==os)].metadata[0].value").value(visibleMetadataOsValue))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].filename", contains("test1")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.md5",
|
||||
contains(artifact.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.sha1",
|
||||
contains(artifact.getSha1Hash())))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0]._links.download-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/"
|
||||
+ getOsModule(findDistributionSetByAction) + "/artifacts/test1")))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0]._links.md5sum-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/"
|
||||
+ getOsModule(findDistributionSetByAction) + "/artifacts/test1.MD5SUM")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].filename",
|
||||
contains("test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].hashes.md5",
|
||||
contains(artifactSignature.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].hashes.sha1",
|
||||
contains(artifactSignature.getSha1Hash())))
|
||||
.andExpect(
|
||||
jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1]._links.download-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/"
|
||||
+ getOsModule(findDistributionSetByAction) + "/artifacts/test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1]._links.md5sum-http.href",
|
||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4712/softwaremodules/" + getOsModule(findDistributionSetByAction)
|
||||
+ "/artifacts/test1.signature.MD5SUM")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].version",
|
||||
contains(ds.findFirstModuleByType(appType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].metadata").doesNotExist())
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name")
|
||||
.value(ds.findFirstModuleByType(appType).get().getName()));
|
||||
|
||||
// Retrieved is reported
|
||||
final List<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
.findActionStatusByAction(new PageRequest(0, 100, Direction.DESC, "id"), uaction.getId()).getContent();
|
||||
assertThat(actionStatusMessages).hasSize(2);
|
||||
final ActionStatus actionStatusMessage = actionStatusMessages.iterator().next();
|
||||
assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Attempt/soft deployment to a controller including automated switch to hard. Checks if the resource reponse payload for a given deployment is as expected.")
|
||||
public void deplomentAutoForceAction() throws Exception {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "test1",
|
||||
false, artifactSize);
|
||||
final Artifact artifactSignature = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds),
|
||||
"test1.signature", false, artifactSize);
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(0);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(0);
|
||||
|
||||
List<Target> saved = deploymentManagement.assignDistributionSet(ds.getId(), ActionType.TIMEFORCED,
|
||||
System.currentTimeMillis(), Arrays.asList(savedTarget.getControllerId())).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
saved = assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
|
||||
long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href", startsWith("http://localhost/"
|
||||
+ tenantAware.getCurrentTenant() + "/controller/v1/4712/deploymentBase/" + uaction.getId())));
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
current = System.currentTimeMillis();
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/{actionId}", tenantAware.getCurrentTenant(),
|
||||
uaction.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(action.getId()))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].name",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==jvm)].version",
|
||||
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].name",
|
||||
contains(ds.findFirstModuleByType(osType).get().getName())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].version",
|
||||
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].filename", contains("test1")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.md5",
|
||||
contains(artifact.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0].hashes.sha1",
|
||||
contains(artifact.getSha1Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0]._links.download-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[0]._links.md5sum-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1.MD5SUM")))
|
||||
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].size", contains(5 * 1024)))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].filename",
|
||||
contains("test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].hashes.md5",
|
||||
contains(artifactSignature.getMd5Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1].hashes.sha1",
|
||||
contains(artifactSignature.getSha1Hash())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1]._links.download-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1.signature")))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==os)].artifacts[1]._links.md5sum-http.href",
|
||||
contains(
|
||||
HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/4712/softwaremodules/"
|
||||
+ findDistributionSetByAction.findFirstModuleByType(osType).get().getId()
|
||||
+ "/artifacts/test1.signature.MD5SUM")))
|
||||
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].version",
|
||||
contains(ds.findFirstModuleByType(appType).get().getVersion())))
|
||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part==bApp)].name",
|
||||
contains(ds.findFirstModuleByType(appType).get().getName())));
|
||||
|
||||
// Retrieved is reported
|
||||
final Iterable<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
.findActionStatusByAction(new PageRequest(0, 100, Direction.DESC, "id"), uaction.getId()).getContent();
|
||||
assertThat(actionStatusMessages).hasSize(2);
|
||||
final ActionStatus actionStatusMessage = actionStatusMessages.iterator().next();
|
||||
assertThat(actionStatusMessage.getStatus()).isEqualTo(Status.RETRIEVED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test various invalid access attempts to the deployment resource und the expected behaviour of the server.")
|
||||
public void badDeploymentAction() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("4712");
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/1", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/4712/deploymentBase/1", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/4712/deploymentBase/1", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(get("/{tenant}/controller/v1/4715/deploymentBase/1", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// no deployment
|
||||
mvc.perform(get("/controller/v1/4712/deploymentBase/1", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// wrong media type
|
||||
final List<Target> toAssign = Arrays.asList(target);
|
||||
final DistributionSet savedSet = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Long actionId = assignDistributionSet(savedSet, toAssign).getActions().get(0);
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/" + actionId, tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/" + actionId, tenantAware.getCurrentTenant())
|
||||
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotAcceptable());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("The server protects itself against to many feedback upload attempts. The test verfies that "
|
||||
+ "it is not possible to exceed the configured maximum number of feedback uplods.")
|
||||
public void tooMuchDeplomentActionFeedback() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("4712");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "4712");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding");
|
||||
// assign distribution set creates an action status, so only 99 left
|
||||
for (int i = 0; i < 99; i++) {
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(feedback).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(feedback).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("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.")
|
||||
public void tooMuchDeploymentActionMessagesInFeedback() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("4712");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "4712");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
for (int i = 0; i < 51; i++) {
|
||||
messages.add(String.valueOf(i));
|
||||
}
|
||||
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding", "none",
|
||||
messages);
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(feedback).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Multiple uploads of deployment status feedback to the server.")
|
||||
public void multipleDeplomentActionFeedback() throws Exception {
|
||||
final Target savedTarget1 = testdataFactory.createTarget("4712");
|
||||
testdataFactory.createTarget("4713");
|
||||
testdataFactory.createTarget("4714");
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("3", true);
|
||||
|
||||
final List<Target> toAssign = new ArrayList<>();
|
||||
toAssign.add(savedTarget1);
|
||||
|
||||
final Long actionId1 = assignDistributionSet(ds1.getId(), "4712").getActions().get(0);
|
||||
final Long actionId2 = assignDistributionSet(ds2.getId(), "4712").getActions().get(0);
|
||||
final Long actionId3 = assignDistributionSet(ds3.getId(), "4712").getActions().get(0);
|
||||
|
||||
Target myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(3);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(myT.getControllerId()).get()).isEqualTo(ds3);
|
||||
assertThat(deploymentManagement.getInstalledDistributionSet(myT.getControllerId())).isNotPresent();
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.UNKNOWN)).hasSize(2);
|
||||
|
||||
// action1 done
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + actionId1 + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(actionId1.toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(myT.getControllerId()).get()).isEqualTo(ds3);
|
||||
assertThat(deploymentManagement.getInstalledDistributionSet(myT.getControllerId()).get()).isEqualTo(ds1);
|
||||
|
||||
Iterable<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
.findActionStatusAll(new PageRequest(0, 100, Direction.DESC, "id")).getContent();
|
||||
assertThat(actionStatusMessages).hasSize(4);
|
||||
assertThat(actionStatusMessages.iterator().next().getStatus()).isEqualTo(Status.FINISHED);
|
||||
|
||||
// action2 done
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + actionId2 + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(actionId2.toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(myT.getControllerId()).get()).isEqualTo(ds3);
|
||||
assertThat(deploymentManagement.getInstalledDistributionSet(myT.getControllerId()).get()).isEqualTo(ds2);
|
||||
actionStatusMessages = deploymentManagement.findActionStatusAll(new PageRequest(0, 100, Direction.DESC, "id"))
|
||||
.getContent();
|
||||
assertThat(actionStatusMessages).hasSize(5);
|
||||
assertThat(actionStatusMessages).haveAtLeast(1, new ActionStatusCondition(Status.FINISHED));
|
||||
|
||||
// action3 done
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + actionId3 + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(actionId3.toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(0);
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(myT.getControllerId()).get()).isEqualTo(ds3);
|
||||
assertThat(deploymentManagement.getInstalledDistributionSet(myT.getControllerId()).get()).isEqualTo(ds3);
|
||||
actionStatusMessages = deploymentManagement.findActionStatusAll(new PageRequest(0, 100, Direction.DESC, "id"))
|
||||
.getContent();
|
||||
assertThat(actionStatusMessages).hasSize(6);
|
||||
assertThat(actionStatusMessages).haveAtLeast(1, new ActionStatusCondition(Status.FINISHED));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that an update action is correctly set to error if the controller provides error feedback.")
|
||||
public void rootRsSingleDeplomentActionWithErrorFeedback() throws Exception {
|
||||
DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
final List<Target> toAssign = new ArrayList<>();
|
||||
toAssign.add(savedTarget);
|
||||
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
assignDistributionSet(ds, toAssign);
|
||||
final Action action = deploymentManagement.findActionsByDistributionSet(PAGE, ds.getId()).getContent().get(0);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "closed", "failure",
|
||||
"error message"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
Target myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(targetManagement.getByControllerID("4712").get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.ERROR);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.PENDING)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(1);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(0);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(0);
|
||||
assertThat(deploymentManagement.countActionsByTarget(myT.getControllerId())).isEqualTo(1);
|
||||
final Iterable<ActionStatus> actionStatusMessages = deploymentManagement
|
||||
.findActionStatusAll(new PageRequest(0, 100, Direction.DESC, "id")).getContent();
|
||||
assertThat(actionStatusMessages).hasSize(2);
|
||||
assertThat(actionStatusMessages).haveAtLeast(1, new ActionStatusCondition(Status.ERROR));
|
||||
|
||||
// redo
|
||||
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
|
||||
assignDistributionSet(ds, Arrays.asList(targetManagement.getByControllerID("4712").get()));
|
||||
final Action action2 = deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId()).getContent()
|
||||
.get(0);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action2.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action2.getId().toString(), "closed", "success"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.PENDING)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(1);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(0);
|
||||
assertThat(deploymentManagement.findInActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(4);
|
||||
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action.getId()).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.ERROR));
|
||||
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action2.getId()).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.FINISHED));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies that the controller can provided as much feedback entries as necessry as long as it is in the configured limites.")
|
||||
public void rootRsSingleDeplomentActionFeedback() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
final List<Target> toAssign = Arrays.asList(savedTarget);
|
||||
|
||||
Target myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
assignDistributionSet(ds, toAssign);
|
||||
final Action action = deploymentManagement.findActionsByDistributionSet(PAGE, ds.getId()).getContent().get(0);
|
||||
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(targetManagement.findByInstalledDistributionSet(PAGE, ds.getId())).hasSize(0);
|
||||
assertThat(targetManagement.findByAssignedDistributionSet(PAGE, ds.getId())).hasSize(1);
|
||||
|
||||
// Now valid Feedback
|
||||
for (int i = 0; i < 4; i++) {
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "proceeding"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.PENDING)).hasSize(1);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(0);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(5);
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(5,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "scheduled"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.PENDING)).hasSize(1);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(0);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(5,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "resumed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.PENDING)).hasSize(1);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(0);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(7);
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(6,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "canceled"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(1);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.PENDING)).hasSize(1);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(0);
|
||||
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(8);
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(7,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.CANCELED));
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "rejected"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(1);
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(9);
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(6,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.WARNING));
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.CANCELED));
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(action.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
myT = targetManagement.getByControllerID("4712").get();
|
||||
assertThat(myT.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, myT.getControllerId())).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.ERROR)).hasSize(0);
|
||||
assertThat(targetManagement.findByUpdateStatus(new PageRequest(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(1);
|
||||
|
||||
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(10);
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(7,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.WARNING));
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.CANCELED));
|
||||
assertThat(deploymentManagement.findActionStatusAll(PAGE).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.FINISHED));
|
||||
|
||||
assertThat(targetManagement.findByInstalledDistributionSet(PAGE, ds.getId())).hasSize(1);
|
||||
assertThat(targetManagement.findByAssignedDistributionSet(PAGE, ds.getId())).hasSize(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Various forbidden request appempts on the feedback resource. Ensures correct answering behaviour as expected to these kind of errors.")
|
||||
public void badDeplomentActionFeedback() throws Exception {
|
||||
final DistributionSet savedSet = testdataFactory.createDistributionSet("");
|
||||
final DistributionSet savedSet2 = testdataFactory.createDistributionSet("1");
|
||||
|
||||
// target does not exist
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/1234/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionInProgressFeedback("1234")).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
Target savedTarget = testdataFactory.createTarget("4712");
|
||||
final Target savedTarget2 = testdataFactory.createTarget("4713");
|
||||
|
||||
// Action does not exists
|
||||
mvc.perform(post("/{tenant}/controller/v1/4712/deploymentBase/1234/feedback", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionInProgressFeedback("1234")).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
final List<Target> toAssign = Arrays.asList(savedTarget);
|
||||
final List<Target> toAssign2 = Arrays.asList(savedTarget2);
|
||||
|
||||
savedTarget = assignDistributionSet(savedSet, toAssign).getAssignedEntity().iterator().next();
|
||||
assignDistributionSet(savedSet2, toAssign2);
|
||||
|
||||
final Action updateAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
// action exists but is not assigned to this target
|
||||
mvc.perform(post("/{tenant}/controller/v1/4713/deploymentBase/" + updateAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionInProgressFeedback(updateAction.getId().toString()))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/deploymentBase/2/feedback", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put("/{tenant}/controller/v1/4712/deploymentBase/2/feedback", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/4712/deploymentBase/2/feedback", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an invalid id in feedback body returns a bad request.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void invalidIdInFeedbackReturnsBadRequest() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/1080/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(JsonBuilder.deploymentActionInProgressFeedback("AAAA"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a missing feedback result in feedback body returns a bad request.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void missingResultAttributeInFeedbackReturnsBadRequest() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final String missingResultInFeedback = JsonBuilder.missingResultInFeedback(action.getId().toString(), "closed",
|
||||
"test");
|
||||
mvc.perform(post("/{tenant}/controller/v1/1080/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(missingResultInFeedback).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a missing finished result in feedback body returns a bad request.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
public void missingFinishedAttributeInFeedbackReturnsBadRequest() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final String missingFinishedResultInFeedback = JsonBuilder
|
||||
.missingFinishedResultInFeedback(action.getId().toString(), "closed", "test");
|
||||
mvc.perform(post("/{tenant}/controller/v1/1080/deploymentBase/" + action.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(missingFinishedResultInFeedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
private class ActionStatusCondition extends Condition<ActionStatus> {
|
||||
private final Status status;
|
||||
|
||||
public ActionStatusCondition(final Status status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(final ActionStatus actionStatus) {
|
||||
return actionStatus.getStatus() == status;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,590 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.CONTROLLER_ROLE_ANONYMOUS;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SpringEvalExpressions.SYSTEM_ROLE;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetTypeCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleTypeCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
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.repository.test.matcher.Expect;
|
||||
import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.eclipse.hawkbit.util.IpUtil;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test the root controller resources.
|
||||
*/
|
||||
@Features("Component Tests - Direct Device Integration API")
|
||||
@Stories("Root Poll Resource")
|
||||
public class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
private static final String TARGET_COMPLETED_INSTALLATION_MSG = "Target completed installation.";
|
||||
private static final String TARGET_PROCEEDING_INSTALLATION_MSG = "Target proceeding installation.";
|
||||
private static final String TARGET_SCHEDULED_INSTALLATION_MSG = "Target scheduled installation.";
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
@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.")
|
||||
@WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = { CONTROLLER_ROLE,
|
||||
SYSTEM_ROLE }, autoCreateTenant = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetTypeCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleTypeCreatedEvent.class, count = 2) })
|
||||
public void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception {
|
||||
|
||||
mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// create tenant -- creates softwaremoduletypes and distributionsettypes
|
||||
systemManagement.getTenantMetadata("tenantDoesNotExists");
|
||||
|
||||
mvc.perform(get("/{}/controller/v1/aControllerId", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
// delete tenant again, will also deleted target aControllerId
|
||||
systemManagement.deleteTenant("tenantDoesNotExists");
|
||||
|
||||
mvc.perform(get("/{}/controller/v1/aControllerId", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target poll request does not change audit data on the entity.")
|
||||
@WithUser(principal = "knownPrincipal", authorities = { SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET,
|
||||
SpPermission.CREATE_TARGET }, allSpPermissions = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void targetPollDoesNotModifyAuditData() throws Exception {
|
||||
// create target first with "knownPrincipal" user and audit data
|
||||
final String knownTargetControllerId = "target1";
|
||||
final String knownCreatedBy = "knownPrincipal";
|
||||
testdataFactory.createTarget(knownTargetControllerId);
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId).get();
|
||||
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
|
||||
assertThat(findTargetByControllerID.getCreatedAt()).isNotNull();
|
||||
|
||||
// make a poll, audit information should not be changed, run as
|
||||
// controller principal!
|
||||
securityRule.runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + knownTargetControllerId, tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
|
||||
// verify that audit information has not changed
|
||||
final Target targetVerify = targetManagement.getByControllerID(knownTargetControllerId).get();
|
||||
assertThat(targetVerify.getCreatedBy()).isEqualTo(findTargetByControllerID.getCreatedBy());
|
||||
assertThat(targetVerify.getCreatedAt()).isEqualTo(findTargetByControllerID.getCreatedAt());
|
||||
assertThat(targetVerify.getLastModifiedBy()).isEqualTo(findTargetByControllerID.getLastModifiedBy());
|
||||
assertThat(targetVerify.getLastModifiedAt()).isEqualTo(findTargetByControllerID.getLastModifiedAt());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that server returns a not found response in case of empty controlloer ID.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
public void rootRsWithoutId() throws Exception {
|
||||
mvc.perform(get("/controller/v1/")).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the system creates a new target in plug and play manner, i.e. target is authenticated but does not exist yet.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsPlugAndPlay() throws Exception {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/default-tenant/controller/v1/4711")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
|
||||
assertThat(targetManagement.getByControllerID("4711").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
assertThat(targetManagement.getByControllerID("4711").get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.REGISTERED);
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post("/default-tenant/controller/v1/4711")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put("/default-tenant/controller/v1/4711")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/default-tenant/controller/v1/4711")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that tenant specific polling time, which is saved in the db, is delivered to the controller.")
|
||||
@WithUser(principal = "knownpricipal", allSpPermissions = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void pollWithModifiedGloablPollingTime() throws Exception {
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:02:00");
|
||||
return null;
|
||||
});
|
||||
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that etag check results in not modified response if provided etag by client is identical to entity in repository.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 6),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6) })
|
||||
public void rootRsNotModified() throws Exception {
|
||||
final String etag = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))).andReturn().getResponse()
|
||||
.getHeader("ETag");
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()).header("If-None-Match", etag))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
||||
|
||||
final Target target = targetManagement.getByControllerID("4711").get();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "4711");
|
||||
|
||||
final Action updateAction = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
final String etagWithFirstUpdate = mvc
|
||||
.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4711/deploymentBase/" + updateAction.getId())))
|
||||
.andReturn().getResponse().getHeader("ETag");
|
||||
|
||||
assertThat(etagWithFirstUpdate).isNotNull();
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()).header("If-None-Match",
|
||||
etagWithFirstUpdate)).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
||||
|
||||
// now lets finish the update
|
||||
mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + updateAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(updateAction.getId().toString(), "closed"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
// we are again at the original state
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()).header("If-None-Match", etag))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
||||
|
||||
// Now another deployment
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2");
|
||||
|
||||
assignDistributionSet(ds2.getId(), "4711");
|
||||
|
||||
final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header("If-None-Match", etagWithFirstUpdate).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant()
|
||||
+ "/controller/v1/4711/deploymentBase/" + updateAction2.getId())))
|
||||
.andReturn().getResponse().getHeader("ETag");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the target state machine of a precomissioned target switches from "
|
||||
+ "UNKNOWN to REGISTERED when the target polls for the first time.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsPrecommissioned() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("4711");
|
||||
|
||||
assertThat(targetManagement.getByControllerID("4711").get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(APPLICATION_JSON_HAL_UTF))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
|
||||
|
||||
assertThat(targetManagement.getByControllerID("4711").get().getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
assertThat(targetManagement.getByControllerID("4711").get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
assertThat(targetManagement.getByControllerID("4711").get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.REGISTERED);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the source IP address of the polling target is correctly stored in repository")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsPlugAndPlayIpAddress() throws Exception {
|
||||
// test
|
||||
final String knownControllerId1 = "0815";
|
||||
final long create = System.currentTimeMillis();
|
||||
|
||||
// make a poll, audit information should be set on plug and play
|
||||
securityRule.runAs(WithSpringAuthorityRule.withController("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(), knownControllerId1))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
|
||||
// verify
|
||||
final Target target = targetManagement.getByControllerID(knownControllerId1).get();
|
||||
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("127.0.0.1"));
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the source IP address of the polling target is not stored in repository if disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
public void rootRsIpAddressNotStoredIfDisabled() throws Exception {
|
||||
securityProperties.getClients().setTrackRemoteIp(false);
|
||||
|
||||
// test
|
||||
final String knownControllerId1 = "0815";
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(), knownControllerId1))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
// verify
|
||||
final Target target = targetManagement.getByControllerID(knownControllerId1).get();
|
||||
assertThat(target.getAddress()).isEqualTo(IpUtil.createHttpUri("***"));
|
||||
|
||||
securityProperties.getClients().setTrackRemoteIp(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller trys to finish an update process after it has been finished by an error action status.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator()
|
||||
.next();
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "proceeding"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(
|
||||
JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "closed", "failure"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(
|
||||
JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "closed", "success"))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isGone());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void testActionHistoryCount() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator()
|
||||
.next();
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "scheduled",
|
||||
TARGET_SCHEDULED_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "proceeding",
|
||||
TARGET_PROCEEDING_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "closed",
|
||||
"success", TARGET_COMPLETED_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "?actionHistory=3",
|
||||
tenantAware.getCurrentTenant()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_PROCEEDING_INSTALLATION_MSG))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that a zero input value of actionHistory results in no action history appended for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void testActionHistoryZeroInput() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator()
|
||||
.next();
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "scheduled",
|
||||
TARGET_SCHEDULED_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "proceeding",
|
||||
TARGET_PROCEEDING_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "closed",
|
||||
"success", TARGET_COMPLETED_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "?actionHistory=-2",
|
||||
tenantAware.getCurrentTenant()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that entire action history is returned if the input value for actionHistory is -1, for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
|
||||
public void testActionHistoryNegativeInput() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator()
|
||||
.next();
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "scheduled",
|
||||
TARGET_SCHEDULED_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "proceeding",
|
||||
TARGET_PROCEEDING_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(post("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.deploymentActionFeedback(savedAction.getId().toString(), "closed",
|
||||
"success", TARGET_COMPLETED_INSTALLATION_MSG))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/911/deploymentBase/" + savedAction.getId() + "?actionHistory=-1",
|
||||
tenantAware.getCurrentTenant()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_PROCEEDING_INSTALLATION_MSG))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(TARGET_COMPLETED_INSTALLATION_MSG))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test the polling time based on different maintenance window start and end time.")
|
||||
public void sleepTimeResponseForDifferentMaintenanceWindowParameters() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
securityRule.runAs(WithSpringAuthorityRule.withUser("tenantadmin", HAS_AUTH_TENANT_CONFIGURATION), () -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:05:00");
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL,
|
||||
"00:01:00");
|
||||
return null;
|
||||
});
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget("1911");
|
||||
assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(), getTestSchedule(16),
|
||||
getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get("/default-tenant/controller/v1/1911/")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", greaterThanOrEqualTo("00:05:00")));
|
||||
|
||||
final Target savedTarget1 = testdataFactory.createTarget("2911");
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("1");
|
||||
assignDistributionSetWithMaintenanceWindow(ds1.getId(), savedTarget1.getControllerId(), getTestSchedule(10),
|
||||
getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get("/default-tenant/controller/v1/2911/")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", lessThan("00:05:00")))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", greaterThanOrEqualTo("00:03:00")));
|
||||
|
||||
final Target savedTarget2 = testdataFactory.createTarget("3911");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2");
|
||||
assignDistributionSetWithMaintenanceWindow(ds2.getId(), savedTarget2.getControllerId(), getTestSchedule(5),
|
||||
getTestDuration(5), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get("/default-tenant/controller/v1/3911/")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", lessThan("00:02:00")));
|
||||
|
||||
final Target savedTarget3 = testdataFactory.createTarget("4911");
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("3");
|
||||
assignDistributionSetWithMaintenanceWindow(ds3.getId(), savedTarget3.getControllerId(), getTestSchedule(-5),
|
||||
getTestDuration(15), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get("/default-tenant/controller/v1/4911/")).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:05:00")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test download and update values before maintenance window start time.")
|
||||
public void downloadAndUpdateStatusBeforeMaintenanceWindowStartTime() throws Exception {
|
||||
Target savedTarget = testdataFactory.createTarget("1911");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
savedTarget = assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(),
|
||||
getTestSchedule(2), getTestDuration(1), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get("/default-tenant/controller/v1/1911/")).andExpect(status().isOk());
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/1911/deploymentBase/{actionId}", tenantAware.getCurrentTenant(),
|
||||
action.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("skip")))
|
||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test download and update values after maintenance window start time.")
|
||||
public void downloadAndUpdateStatusDuringMaintenanceWindow() throws Exception {
|
||||
Target savedTarget = testdataFactory.createTarget("1911");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
savedTarget = assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(),
|
||||
getTestSchedule(-5), getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get("/default-tenant/controller/v1/1911/")).andExpect(status().isOk());
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/1911/deploymentBase/{actionId}", tenantAware.getCurrentTenant(),
|
||||
action.getId()).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available")));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* 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.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
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.rest.filter.ExcludePathAwareShallowETagFilter;
|
||||
import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.security.DosFilter;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
import ru.yandex.qatools.allure.annotations.Description;
|
||||
import ru.yandex.qatools.allure.annotations.Features;
|
||||
import ru.yandex.qatools.allure.annotations.Stories;
|
||||
|
||||
/**
|
||||
* Test potential DOS attack scenarios and check if the filter prevents them.
|
||||
*
|
||||
*/
|
||||
@ActiveProfiles({ "test" })
|
||||
@Features("Component Tests - REST Security")
|
||||
@Stories("Denial of Service protection filter")
|
||||
public class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Override
|
||||
protected DefaultMockMvcBuilder createMvcWebAppContext(final WebApplicationContext context) {
|
||||
return MockMvcBuilders.webAppContextSetup(context)
|
||||
.addFilter(new DosFilter(null, 10, 10, "127\\.0\\.0\\.1|\\[0:0:0:0:0:0:0:1\\]", "(^192\\.168\\.)",
|
||||
"X-Forwarded-For"))
|
||||
.addFilter(new ExcludePathAwareShallowETagFilter(
|
||||
"/rest/v1/softwaremodules/{smId}/artifacts/{artId}/download",
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/**",
|
||||
"/api/v1/downloadserver/**"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that clients that are on the blacklist are forbidded ")
|
||||
public void blackListedClientIsForbidden() throws Exception {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 ")).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a READ DoS attempt is blocked ")
|
||||
public void getFloddingAttackThatisPrevented() throws Exception {
|
||||
|
||||
MvcResult result = null;
|
||||
|
||||
int requests = 0;
|
||||
do {
|
||||
result = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1")).andReturn();
|
||||
requests++;
|
||||
|
||||
// we give up after 1.000 requests
|
||||
assertThat(requests).isLessThan(1_000);
|
||||
} while (result.getResponse().getStatus() != HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
|
||||
// the filter shuts down after 100 GET requests
|
||||
assertThat(requests).isGreaterThanOrEqualTo(10);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an assumed READ DoS attempt is not blocked as the client (with IPv4 address) is on a whitelist")
|
||||
public void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "127.0.0.1")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an assumed READ DoS attempt is not blocked as the client (with IPv6 address) is on a whitelist")
|
||||
public void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "0:0:0:0:0:0:0:1")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
|
||||
public void acceptableGetLoad() throws Exception {
|
||||
|
||||
for (int x = 0; x < 3; x++) {
|
||||
// sleep for one second
|
||||
Thread.sleep(1100);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1")).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a WRITE DoS attempt is blocked ")
|
||||
public void putPostFloddingAttackThatisPrevented() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
|
||||
MvcResult result = null;
|
||||
int requests = 0;
|
||||
do {
|
||||
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||
tenantAware.getCurrentTenant()).header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1").content(feedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
requests++;
|
||||
|
||||
// we give up after 500 requests
|
||||
assertThat(requests).isLessThan(500);
|
||||
} while (result.getResponse().getStatus() != HttpStatus.TOO_MANY_REQUESTS.value());
|
||||
|
||||
// the filter shuts down after 10 POST requests
|
||||
assertThat(requests).isGreaterThanOrEqualTo(10);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
|
||||
public void acceptablePutPostLoad() throws Exception {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = JsonBuilder.deploymentActionFeedback(actionId.toString(), "proceeding");
|
||||
|
||||
for (int x = 0; x < 5; x++) {
|
||||
// sleep for one second
|
||||
Thread.sleep(1100);
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||
tenantAware.getCurrentTenant()).header(HttpHeaders.X_FORWARDED_FOR, "10.0.0.1")
|
||||
.content(feedback).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Long prepareDeploymentBase() {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("test");
|
||||
final Target target = testdataFactory.createTarget("4711");
|
||||
final List<Target> toAssign = Arrays.asList(target);
|
||||
|
||||
final Iterable<Target> saved = assignDistributionSet(ds, toAssign).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(1);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
|
||||
return uaction.getId();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
#
|
||||
# All rights reserved. This program and the accompanying materials
|
||||
# are made available under the terms of the Eclipse Public License v1.0
|
||||
# which accompanies this distribution, and is available at
|
||||
# http://www.eclipse.org/legal/epl-v10.html
|
||||
#
|
||||
|
||||
# DDI configuration - START
|
||||
hawkbit.controller.pollingTime=00:01:00
|
||||
hawkbit.controller.pollingOverdueTime=00:01:00
|
||||
hawkbit.controller.minPollingTime=00:00:30
|
||||
|
||||
hawkbit.controller.maintenanceWindowPollCount=3
|
||||
# DDI configuration - END
|
||||
|
||||
# Upload configuration - START
|
||||
spring.http.multipart.max-file-size=5MB
|
||||
# Upload configuration - END
|
||||
|
||||
# Quota - START
|
||||
hawkbit.server.security.dos.maxStatusEntriesPerAction=100
|
||||
hawkbit.server.security.dos.maxAttributeEntriesPerTarget=10
|
||||
# Quota - END
|
||||
17
hawkbit-rest/hawkbit-mgmt-api/README.md
Normal file
17
hawkbit-rest/hawkbit-mgmt-api/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Eclipse.IoT hawkBit - Management API - Model and Resources
|
||||
|
||||
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).
|
||||
|
||||
# Version 1
|
||||
|
||||
The model follows [semantic versioning](http://semver.org) with MAJOR version, i.e. breaking changes will result in a new MAJOR version.
|
||||
|
||||
# Compile
|
||||
|
||||
#### Build hawkbit-mgmt-api
|
||||
|
||||
```
|
||||
$ cd hawkbit/hawkbit-mgmt-api
|
||||
$ mvn clean install
|
||||
```
|
||||
|
||||
48
hawkbit-rest/hawkbit-mgmt-api/pom.xml
Normal file
48
hawkbit-rest/hawkbit-mgmt-api/pom.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<!--
|
||||
|
||||
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-rest-parent</artifactId>
|
||||
<version>0.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>hawkbit-mgmt-api</artifactId>
|
||||
<name>hawkBit :: REST :: Management 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>
|
||||
|
||||
<!-- Test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.yandex.qatools.allure</groupId>
|
||||
<artifactId>allure-junit-adaptor</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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.json.model;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for BaseEntity to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
public abstract class MgmtBaseEntity extends ResourceSupport {
|
||||
|
||||
@JsonProperty
|
||||
private String createdBy;
|
||||
|
||||
@JsonProperty
|
||||
private Long createdAt;
|
||||
|
||||
@JsonProperty
|
||||
private String lastModifiedBy;
|
||||
|
||||
@JsonProperty
|
||||
private Long lastModifiedAt;
|
||||
|
||||
/**
|
||||
* @return the createdBy
|
||||
*/
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param createdBy
|
||||
* the createdBy to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setCreatedBy(final String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the createdAt
|
||||
*/
|
||||
public Long getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param createdAt
|
||||
* the createdAt to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setCreatedAt(final Long createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastModifiedBy
|
||||
*/
|
||||
public String getLastModifiedBy() {
|
||||
return lastModifiedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastModifiedBy
|
||||
* the lastModifiedBy to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setLastModifiedBy(final String lastModifiedBy) {
|
||||
this.lastModifiedBy = lastModifiedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastModifiedAt
|
||||
*/
|
||||
public Long getLastModifiedAt() {
|
||||
return lastModifiedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastModifiedAt
|
||||
* the lastModifiedAt to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setLastModifiedAt(final Long lastModifiedAt) {
|
||||
this.lastModifiedAt = lastModifiedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.json.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* A generic abstract rest model which contains only a ID for use-case e.g.
|
||||
* which allows only posting or putting an ID into the request body, e.g. for
|
||||
* assignments.
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtId {
|
||||
|
||||
@JsonProperty
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* @return the id
|
||||
*/
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param id
|
||||
* the id to set
|
||||
*/
|
||||
public void setId(final Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) Siemens AG, 2018
|
||||
*
|
||||
* 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.json.model;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* JSON model for Management API to define the maintenance window.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtMaintenanceWindow extends MgmtMaintenanceWindowRequestBody {
|
||||
|
||||
/**
|
||||
* Time in {@link TimeUnit#MILLISECONDS} of the next maintenance window
|
||||
* start
|
||||
*/
|
||||
@JsonProperty
|
||||
private long nextStartAt;
|
||||
|
||||
public long getNextStartAt() {
|
||||
return nextStartAt;
|
||||
}
|
||||
|
||||
public void setNextStartAt(final long nextStartAt) {
|
||||
this.nextStartAt = nextStartAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2018 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.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;
|
||||
|
||||
/**
|
||||
* Request body for maintenance window PUT/POST commands, based on a schedule
|
||||
* defined as cron expression, duration in HH:mm:ss format and time zone as
|
||||
* offset from UTC.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtMaintenanceWindowRequestBody {
|
||||
@JsonProperty
|
||||
private String schedule;
|
||||
|
||||
@JsonProperty
|
||||
private String duration;
|
||||
|
||||
@JsonProperty
|
||||
private String timezone;
|
||||
|
||||
public String getSchedule() {
|
||||
return schedule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param schedule
|
||||
* is the cron expression to be used for scheduling maintenance
|
||||
* window(s). Expression has 6 mandatory fields and a last
|
||||
* optional field: "second minute hour dayofmonth month weekday
|
||||
* year".
|
||||
*/
|
||||
public void setSchedule(final String schedule) {
|
||||
this.schedule = schedule;
|
||||
}
|
||||
|
||||
public String getDuration() {
|
||||
return duration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param duration
|
||||
* in HH:mm:ss format specifying the duration of a maintenance
|
||||
* window, for example 00:30:00 for 30 minutes.
|
||||
*/
|
||||
public void setDuration(final String duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public String getTimezone() {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timezone
|
||||
* is the time zone specified as +/-hh:mm offset from UTC. For
|
||||
* example +02:00 for CET summer time and +00:00 for UTC. The
|
||||
* start time of a maintenance window calculated based on the
|
||||
* cron expression is relative to this time zone.
|
||||
*/
|
||||
public void setTimezone(final String timezone) {
|
||||
this.timezone = timezone;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* The representation of an meta data in the REST API for POST/Create.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtMetadata {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String key;
|
||||
@JsonProperty
|
||||
private String value;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(final String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* The representation of an meta data in the REST API for PUT/Update.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtMetadataBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String value;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.json.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for NamedEntity to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
public abstract class MgmtNamedEntity extends MgmtBaseEntity {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*/
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description to set
|
||||
*/
|
||||
public void setDescription(final String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for PollStatus to RESTful API representation.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtPollStatus {
|
||||
|
||||
@JsonProperty
|
||||
private Long lastRequestAt;
|
||||
|
||||
@JsonProperty
|
||||
private Long nextExpectedRequestAt;
|
||||
|
||||
@JsonProperty
|
||||
private boolean overdue;
|
||||
|
||||
/**
|
||||
* @return the lastRequestAt
|
||||
*/
|
||||
public Long getLastRequestAt() {
|
||||
return lastRequestAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastRequestAt
|
||||
* the lastRequestAt to set
|
||||
*/
|
||||
public void setLastRequestAt(final Long lastRequestAt) {
|
||||
this.lastRequestAt = lastRequestAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the nextExpectedRequestAt
|
||||
*/
|
||||
public Long getNextExpectedRequestAt() {
|
||||
return nextExpectedRequestAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nextExpectedRequestAt
|
||||
* the nextExpectedRequestAt to set
|
||||
*/
|
||||
public void setNextExpectedRequestAt(final Long nextExpectedRequestAt) {
|
||||
this.nextExpectedRequestAt = nextExpectedRequestAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the overdue
|
||||
*/
|
||||
public boolean isOverdue() {
|
||||
return overdue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param overdue
|
||||
* the overdue to set
|
||||
*/
|
||||
public void setOverdue(final boolean overdue) {
|
||||
this.overdue = overdue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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.json.model;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A list representation with meta data for pagination, e.g. containing the
|
||||
* total elements and size of content. The content of the actual list is stored
|
||||
* in the {@link #content} field.
|
||||
*
|
||||
* @param <T>
|
||||
* the type of elements in this list
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
public class PagedList<T> extends ResourceSupport {
|
||||
|
||||
@JsonProperty
|
||||
private final List<T> content;
|
||||
@JsonProperty
|
||||
private final long total;
|
||||
private final int size;
|
||||
|
||||
/**
|
||||
* creates a new paged list with the given {@code content} and {@code total}
|
||||
* .
|
||||
*
|
||||
* @param content
|
||||
* the actual content of the list
|
||||
* @param total
|
||||
* the total amount of elements
|
||||
* @throws NullPointerException
|
||||
* in case {@code content} is {@code null}.
|
||||
*/
|
||||
@JsonCreator
|
||||
public PagedList(@JsonProperty("content") @NotNull final List<T> content, @JsonProperty("total") final long total) {
|
||||
this.size = content.size();
|
||||
this.total = total;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size of the content list
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the total amount of elements
|
||||
*/
|
||||
public long getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
public List<T> getContent() {
|
||||
return Collections.unmodifiableList(content);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/**
|
||||
* 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.json.model.action;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtBaseEntity;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindow;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for Action to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtAction extends MgmtBaseEntity {
|
||||
|
||||
/**
|
||||
* API definition for action in update mode.
|
||||
*/
|
||||
public static final String ACTION_UPDATE = "update";
|
||||
|
||||
/**
|
||||
* API definition for action in canceling.
|
||||
*/
|
||||
public static final String ACTION_CANCEL = "cancel";
|
||||
|
||||
/**
|
||||
* API definition for action completed.
|
||||
*/
|
||||
public static final String ACTION_FINISHED = "finished";
|
||||
|
||||
/**
|
||||
* API definition for action still active.
|
||||
*/
|
||||
public static final String ACTION_PENDING = "pending";
|
||||
|
||||
@JsonProperty("id")
|
||||
private Long actionId;
|
||||
|
||||
@JsonProperty
|
||||
private String type;
|
||||
|
||||
@JsonProperty
|
||||
private String status;
|
||||
|
||||
@JsonProperty
|
||||
private Long forceTime;
|
||||
|
||||
@JsonProperty
|
||||
private MgmtActionType forceType;
|
||||
|
||||
@JsonProperty
|
||||
private MgmtMaintenanceWindow maintenanceWindow;
|
||||
|
||||
public MgmtMaintenanceWindow getMaintenanceWindow() {
|
||||
return maintenanceWindow;
|
||||
}
|
||||
|
||||
public void setMaintenanceWindow(final MgmtMaintenanceWindow maintenanceWindow) {
|
||||
this.maintenanceWindow = maintenanceWindow;
|
||||
}
|
||||
|
||||
public Long getForceTime() {
|
||||
return forceTime;
|
||||
}
|
||||
|
||||
public void setForceTime(final Long forceTime) {
|
||||
this.forceTime = forceTime;
|
||||
}
|
||||
|
||||
public MgmtActionType getForceType() {
|
||||
return forceType;
|
||||
}
|
||||
|
||||
public void setForceType(final MgmtActionType forceType) {
|
||||
this.forceType = forceType;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Long getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public void setActionId(final Long actionId) {
|
||||
this.actionId = actionId;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.action;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* A json annotated model for Action updates in RESTful API representation.
|
||||
*
|
||||
*/
|
||||
public class MgmtActionRequestBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private MgmtActionType forceType;
|
||||
|
||||
public MgmtActionType getForceType() {
|
||||
return forceType;
|
||||
}
|
||||
|
||||
public void setForceType(final MgmtActionType forceType) {
|
||||
this.forceType = forceType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* 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.json.model.action;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for ActionStatus to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtActionStatus {
|
||||
|
||||
@JsonProperty("id")
|
||||
private Long statusId;
|
||||
|
||||
@JsonProperty
|
||||
private String type;
|
||||
|
||||
@JsonProperty
|
||||
private List<String> messages;
|
||||
|
||||
@JsonProperty
|
||||
private Long reportedAt;
|
||||
|
||||
/**
|
||||
* @return the statusId
|
||||
*/
|
||||
public Long getStatusId() {
|
||||
return statusId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param statusId
|
||||
* the statusId to set
|
||||
*/
|
||||
public void setStatusId(final Long statusId) {
|
||||
this.statusId = statusId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the type to set
|
||||
*/
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the messages
|
||||
*/
|
||||
public List<String> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messages
|
||||
* the messages to set
|
||||
*/
|
||||
public void setMessages(final List<String> messages) {
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the reportedAt
|
||||
*/
|
||||
public Long getReportedAt() {
|
||||
return reportedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reportedAt
|
||||
* the reportedAt to set
|
||||
*/
|
||||
public void setReportedAt(final Long reportedAt) {
|
||||
this.reportedAt = reportedAt;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.json.model.artifact;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtBaseEntity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for Artifact to RESTful API representation.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtArtifact extends MgmtBaseEntity {
|
||||
|
||||
@JsonProperty("id")
|
||||
private Long artifactId;
|
||||
|
||||
@JsonProperty
|
||||
private MgmtArtifactHash hashes;
|
||||
|
||||
@JsonProperty
|
||||
private String providedFilename;
|
||||
|
||||
@JsonProperty
|
||||
private Long size;
|
||||
|
||||
public MgmtArtifact() {
|
||||
// need for json encoder
|
||||
}
|
||||
|
||||
/**
|
||||
* @param hashes
|
||||
* the hashes to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setHashes(final MgmtArtifactHash hashes) {
|
||||
this.hashes = hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param artifactId
|
||||
* the artifactId to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setArtifactId(final Long artifactId) {
|
||||
this.artifactId = artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the artifactId
|
||||
*/
|
||||
public Long getArtifactId() {
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the hashes
|
||||
*/
|
||||
public MgmtArtifactHash getHashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the providedFilename
|
||||
*/
|
||||
public String getProvidedFilename() {
|
||||
return providedFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param providedFilename
|
||||
* the providedFilename to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setProvidedFilename(final String providedFilename) {
|
||||
this.providedFilename = providedFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the size
|
||||
*/
|
||||
public Long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param size
|
||||
* the size to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setSize(final Long size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.json.model.artifact;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Hashes for given Artifact.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class MgmtArtifactHash {
|
||||
|
||||
@JsonProperty
|
||||
private String sha1;
|
||||
|
||||
@JsonProperty
|
||||
private String md5;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public MgmtArtifactHash() {
|
||||
// used for jackson to instantiate
|
||||
}
|
||||
|
||||
/**
|
||||
* Public constructor.
|
||||
*/
|
||||
public MgmtArtifactHash(final String sha1, final String md5) {
|
||||
this.sha1 = sha1;
|
||||
this.md5 = md5;
|
||||
}
|
||||
|
||||
public String getSha1() {
|
||||
return sha1;
|
||||
}
|
||||
|
||||
public String getMd5() {
|
||||
return md5;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.json.model.distributionset;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Definition of the Action type for the REST management API.
|
||||
*
|
||||
*/
|
||||
public enum MgmtActionType {
|
||||
/**
|
||||
* The soft action type.
|
||||
*/
|
||||
SOFT("soft"),
|
||||
|
||||
/**
|
||||
* The forced action type.
|
||||
*/
|
||||
FORCED("forced"),
|
||||
|
||||
/**
|
||||
* The time forced action type.
|
||||
*/
|
||||
TIMEFORCED("timeforced");
|
||||
|
||||
private final String name;
|
||||
|
||||
private MgmtActionType(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@JsonValue
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* 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.json.model.distributionset;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for DistributionSet to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtDistributionSet extends MgmtNamedEntity {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long dsId;
|
||||
|
||||
@JsonProperty
|
||||
private String version;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtSoftwareModule> modules = new ArrayList<>();
|
||||
|
||||
@JsonProperty
|
||||
private boolean requiredMigrationStep;
|
||||
|
||||
@JsonProperty
|
||||
private String type;
|
||||
|
||||
@JsonProperty
|
||||
private Boolean complete;
|
||||
|
||||
@JsonProperty
|
||||
private boolean deleted;
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(final boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public Long getDsId() {
|
||||
return dsId;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void setDsId(final Long id) {
|
||||
dsId = id;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(final String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public boolean isRequiredMigrationStep() {
|
||||
return requiredMigrationStep;
|
||||
}
|
||||
|
||||
public void setRequiredMigrationStep(final boolean requiredMigrationStep) {
|
||||
this.requiredMigrationStep = requiredMigrationStep;
|
||||
}
|
||||
|
||||
public List<MgmtSoftwareModule> getModules() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
public void setModules(final List<MgmtSoftwareModule> modules) {
|
||||
this.modules = modules;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Boolean getComplete() {
|
||||
return complete;
|
||||
}
|
||||
|
||||
public void setComplete(final Boolean complete) {
|
||||
this.complete = complete;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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.json.model.distributionset;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssigment;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for DistributionSet for POST.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtDistributionSetRequestBodyPost extends MgmtDistributionSetRequestBodyPut {
|
||||
|
||||
// deprecated format from the time where os, application and runtime where
|
||||
// statically defined
|
||||
@JsonProperty
|
||||
private MgmtSoftwareModuleAssigment os;
|
||||
|
||||
@JsonProperty
|
||||
private MgmtSoftwareModuleAssigment runtime;
|
||||
|
||||
@JsonProperty
|
||||
private MgmtSoftwareModuleAssigment application;
|
||||
// deprecated format - END
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtSoftwareModuleAssigment> modules;
|
||||
|
||||
@JsonProperty
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* @return the os
|
||||
*/
|
||||
public MgmtSoftwareModuleAssigment getOs() {
|
||||
return os;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param os
|
||||
* the os to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPost setOs(final MgmtSoftwareModuleAssigment os) {
|
||||
this.os = os;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the runtime
|
||||
*/
|
||||
public MgmtSoftwareModuleAssigment getRuntime() {
|
||||
return runtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param runtime
|
||||
* the runtime to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPost setRuntime(final MgmtSoftwareModuleAssigment runtime) {
|
||||
this.runtime = runtime;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the application
|
||||
*/
|
||||
public MgmtSoftwareModuleAssigment getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param application
|
||||
* the application to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPost setApplication(final MgmtSoftwareModuleAssigment application) {
|
||||
this.application = application;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the modules
|
||||
*/
|
||||
public List<MgmtSoftwareModuleAssigment> getModules() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param modules
|
||||
* the modules to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPost setModules(final List<MgmtSoftwareModuleAssigment> modules) {
|
||||
this.modules = modules;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the type to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPost setType(final String type) {
|
||||
this.type = type;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* 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.json.model.distributionset;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for DistributionSet for PUT/POST.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtDistributionSetRequestBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
@JsonProperty
|
||||
private String version;
|
||||
|
||||
@JsonProperty
|
||||
private Boolean requiredMigrationStep;
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPut setName(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requiredMigrationStep
|
||||
*/
|
||||
public Boolean isRequiredMigrationStep() {
|
||||
return requiredMigrationStep;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requiredMigrationStep
|
||||
* the requiredMigrationStep to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPut setRequiredMigrationStep(final Boolean requiredMigrationStep) {
|
||||
this.requiredMigrationStep = requiredMigrationStep;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPut setDescription(final String description) {
|
||||
this.description = description;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version
|
||||
* the version to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetRequestBodyPut setVersion(final String version) {
|
||||
this.version = version;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.distributionset;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindowRequestBody;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body of Target for assignment operations (ID only).
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTargetAssignmentRequestBody {
|
||||
|
||||
@JsonProperty
|
||||
private String id;
|
||||
|
||||
private long forcetime;
|
||||
|
||||
private MgmtActionType type;
|
||||
|
||||
/**
|
||||
* {@link MgmtMaintenanceWindowRequestBody} object containing schedule,
|
||||
* duration and timezone.
|
||||
*/
|
||||
private MgmtMaintenanceWindowRequestBody maintenanceWindow;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(final String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public MgmtActionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final MgmtActionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public long getForcetime() {
|
||||
return forcetime;
|
||||
}
|
||||
|
||||
public void setForcetime(final long forcetime) {
|
||||
this.forcetime = forcetime;
|
||||
}
|
||||
|
||||
public MgmtMaintenanceWindowRequestBody getMaintenanceWindow() {
|
||||
return maintenanceWindow;
|
||||
}
|
||||
|
||||
public void setMaintenanceWindow(final MgmtMaintenanceWindowRequestBody maintenanceWindow) {
|
||||
this.maintenanceWindow = maintenanceWindow;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.json.model.distributionset;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
* Response Body of Target for assignment operations.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTargetAssignmentResponseBody {
|
||||
|
||||
private int assigned;
|
||||
private int alreadyAssigned;
|
||||
private int total;
|
||||
|
||||
/**
|
||||
* @return the assigned
|
||||
*/
|
||||
public int getAssigned() {
|
||||
return assigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param assigned
|
||||
* the assigned to set
|
||||
*/
|
||||
public void setAssigned(final int assigned) {
|
||||
this.assigned = assigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the alreadyAssigned
|
||||
*/
|
||||
public int getAlreadyAssigned() {
|
||||
return alreadyAssigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param alreadyAssigned
|
||||
* the alreadyAssigned to set
|
||||
*/
|
||||
public void setAlreadyAssigned(final int alreadyAssigned) {
|
||||
this.alreadyAssigned = alreadyAssigned;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the total
|
||||
*/
|
||||
public int getTotal() {
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param total
|
||||
* the total to set
|
||||
*/
|
||||
public void setTotal(final int total) {
|
||||
this.total = total;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* 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.json.model.distributionsettype;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for SoftwareModuleType to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtDistributionSetType extends MgmtNamedEntity {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long moduleId;
|
||||
|
||||
@JsonProperty
|
||||
private String key;
|
||||
|
||||
@JsonProperty
|
||||
private boolean deleted;
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(final boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the moduleId
|
||||
*/
|
||||
public Long getModuleId() {
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param moduleId
|
||||
* the moduleId to set
|
||||
*/
|
||||
public void setModuleId(final Long moduleId) {
|
||||
this.moduleId = moduleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* the key to set
|
||||
*/
|
||||
public void setKey(final String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 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.json.model.distributionsettype;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeAssigment;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body for DistributionSetType POST.
|
||||
*
|
||||
*/
|
||||
public class MgmtDistributionSetTypeRequestBodyPost extends MgmtDistributionSetTypeRequestBodyPut {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String key;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtSoftwareModuleTypeAssigment> mandatorymodules;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtSoftwareModuleTypeAssigment> optionalmodules;
|
||||
|
||||
@Override
|
||||
public MgmtDistributionSetTypeRequestBodyPost setDescription(final String description) {
|
||||
super.setDescription(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MgmtDistributionSetTypeRequestBodyPost setColour(final String colour) {
|
||||
super.setColour(colour);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetTypeRequestBodyPost setName(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* the key to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetTypeRequestBodyPost setKey(final String key) {
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mandatory modules
|
||||
*/
|
||||
public List<MgmtSoftwareModuleTypeAssigment> getMandatorymodules() {
|
||||
return mandatorymodules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mandatorymodules
|
||||
* the mandatory modules to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetTypeRequestBodyPost setMandatorymodules(
|
||||
final List<MgmtSoftwareModuleTypeAssigment> mandatorymodules) {
|
||||
this.mandatorymodules = mandatorymodules;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the optional modules
|
||||
*/
|
||||
public List<MgmtSoftwareModuleTypeAssigment> getOptionalmodules() {
|
||||
return optionalmodules;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param optionalmodules
|
||||
* the optional modules to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtDistributionSetTypeRequestBodyPost setOptionalmodules(
|
||||
final List<MgmtSoftwareModuleTypeAssigment> optionalmodules) {
|
||||
this.optionalmodules = optionalmodules;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.json.model.distributionsettype;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body for DistributionSetType PUT, i.e. update.
|
||||
*
|
||||
*/
|
||||
public class MgmtDistributionSetTypeRequestBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
@JsonProperty
|
||||
private String colour;
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public MgmtDistributionSetTypeRequestBodyPut setDescription(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getColour() {
|
||||
return colour;
|
||||
}
|
||||
|
||||
public MgmtDistributionSetTypeRequestBodyPut setColour(final String colour) {
|
||||
this.colour = colour;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* 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.json.model.rollout;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
/**
|
||||
* Model for defining Conditions and Actions
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public abstract class AbstractMgmtRolloutConditionsEntity extends MgmtNamedEntity {
|
||||
|
||||
private MgmtRolloutCondition successCondition;
|
||||
private MgmtRolloutSuccessAction successAction;
|
||||
private MgmtRolloutCondition errorCondition;
|
||||
private MgmtRolloutErrorAction errorAction;
|
||||
|
||||
public MgmtRolloutCondition getSuccessCondition() {
|
||||
return successCondition;
|
||||
}
|
||||
|
||||
public void setSuccessCondition(final MgmtRolloutCondition successCondition) {
|
||||
this.successCondition = successCondition;
|
||||
}
|
||||
|
||||
public MgmtRolloutSuccessAction getSuccessAction() {
|
||||
return successAction;
|
||||
}
|
||||
|
||||
public void setSuccessAction(final MgmtRolloutSuccessAction successAction) {
|
||||
this.successAction = successAction;
|
||||
}
|
||||
|
||||
public MgmtRolloutCondition getErrorCondition() {
|
||||
return errorCondition;
|
||||
}
|
||||
|
||||
public void setErrorCondition(final MgmtRolloutCondition errorCondition) {
|
||||
this.errorCondition = errorCondition;
|
||||
}
|
||||
|
||||
public MgmtRolloutErrorAction getErrorAction() {
|
||||
return errorAction;
|
||||
}
|
||||
|
||||
public void setErrorAction(final MgmtRolloutErrorAction errorAction) {
|
||||
this.errorAction = errorAction;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.json.model.rollout;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutCondition {
|
||||
|
||||
private Condition condition = Condition.THRESHOLD;
|
||||
private String expression = "100";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public MgmtRolloutCondition() {
|
||||
// needed for jackson json creator.
|
||||
}
|
||||
|
||||
public MgmtRolloutCondition(final Condition condition, final String expression) {
|
||||
this.condition = condition;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the condition
|
||||
*/
|
||||
public Condition getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param condition
|
||||
* the condition to set
|
||||
*/
|
||||
public void setCondition(final Condition condition) {
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expession
|
||||
*/
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expession
|
||||
* the expession to set
|
||||
*/
|
||||
public void setExpression(final String expession) {
|
||||
this.expression = expession;
|
||||
}
|
||||
|
||||
public enum Condition {
|
||||
THRESHOLD;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.json.model.rollout;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
* An action that runs when the error condition is met
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutErrorAction {
|
||||
|
||||
private ErrorAction action = ErrorAction.PAUSE;
|
||||
private String expression;
|
||||
|
||||
/**
|
||||
* Creates a rollout error action
|
||||
*
|
||||
* @param action
|
||||
* the action to run when th error condition is met
|
||||
* @param expression
|
||||
* the expression for the action
|
||||
*/
|
||||
public MgmtRolloutErrorAction(ErrorAction action, String expression) {
|
||||
this.action = action;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public MgmtRolloutErrorAction() {
|
||||
// Instantiate default error action
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the action
|
||||
*/
|
||||
public ErrorAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param action
|
||||
* the action to set
|
||||
*/
|
||||
public void setAction(final ErrorAction action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expression
|
||||
*/
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expression
|
||||
* the expression to set
|
||||
*/
|
||||
public void setExpression(final String expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible actions
|
||||
*/
|
||||
public enum ErrorAction {
|
||||
PAUSE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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.json.model.rollout;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutResponseBody extends MgmtNamedEntity {
|
||||
|
||||
private String targetFilterQuery;
|
||||
private Long distributionSetId;
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long rolloutId;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String status;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private Long totalTargets;
|
||||
|
||||
@JsonProperty
|
||||
private Map<String, Long> totalTargetsPerStatus;
|
||||
|
||||
@JsonProperty
|
||||
private boolean deleted;
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(final boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Long getRolloutId() {
|
||||
return rolloutId;
|
||||
}
|
||||
|
||||
public void setRolloutId(final Long rolloutId) {
|
||||
this.rolloutId = rolloutId;
|
||||
}
|
||||
|
||||
public String getTargetFilterQuery() {
|
||||
return targetFilterQuery;
|
||||
}
|
||||
|
||||
public void setTargetFilterQuery(final String targetFilterQuery) {
|
||||
this.targetFilterQuery = targetFilterQuery;
|
||||
}
|
||||
|
||||
public Long getDistributionSetId() {
|
||||
return distributionSetId;
|
||||
}
|
||||
|
||||
public void setDistributionSetId(final Long distributionSetId) {
|
||||
this.distributionSetId = distributionSetId;
|
||||
}
|
||||
|
||||
public void setTotalTargets(final Long totalTargets) {
|
||||
this.totalTargets = totalTargets;
|
||||
}
|
||||
|
||||
public Long getTotalTargets() {
|
||||
return totalTargets;
|
||||
}
|
||||
|
||||
public Map<String, Long> getTotalTargetsPerStatus() {
|
||||
return totalTargetsPerStatus;
|
||||
}
|
||||
|
||||
public void addTotalTargetsPerStatus(final String status, final Long totalTargetCountByStatus) {
|
||||
if (totalTargetsPerStatus == null) {
|
||||
totalTargetsPerStatus = new HashMap<>();
|
||||
}
|
||||
|
||||
totalTargetsPerStatus.put(status, totalTargetCountByStatus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* 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.json.model.rollout;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
* Model for request containing a rollout body e.g. in a POST request of
|
||||
* creating a rollout via REST API.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutRestRequestBody extends AbstractMgmtRolloutConditionsEntity {
|
||||
|
||||
private String targetFilterQuery;
|
||||
private long distributionSetId;
|
||||
|
||||
private Integer amountGroups;
|
||||
|
||||
private Long forcetime;
|
||||
|
||||
private Long startAt;
|
||||
|
||||
private MgmtActionType type;
|
||||
|
||||
private List<MgmtRolloutGroup> groups;
|
||||
|
||||
/**
|
||||
* @return the targetFilterQuery
|
||||
*/
|
||||
public String getTargetFilterQuery() {
|
||||
return targetFilterQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetFilterQuery
|
||||
* the targetFilterQuery to set
|
||||
*/
|
||||
public void setTargetFilterQuery(final String targetFilterQuery) {
|
||||
this.targetFilterQuery = targetFilterQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the distributionSetId
|
||||
*/
|
||||
public long getDistributionSetId() {
|
||||
return distributionSetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param distributionSetId
|
||||
* the distributionSetId to set
|
||||
*/
|
||||
public void setDistributionSetId(final long distributionSetId) {
|
||||
this.distributionSetId = distributionSetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the groupSize
|
||||
*/
|
||||
public Integer getAmountGroups() {
|
||||
return amountGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groupSize
|
||||
* the groupSize to set
|
||||
*/
|
||||
public void setAmountGroups(final Integer groupSize) {
|
||||
this.amountGroups = groupSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the forcetime
|
||||
*/
|
||||
public Long getForcetime() {
|
||||
return forcetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param forcetime
|
||||
* the forcetime to set
|
||||
*/
|
||||
public void setForcetime(final Long forcetime) {
|
||||
this.forcetime = forcetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public MgmtActionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the type to set
|
||||
*/
|
||||
public void setType(final MgmtActionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the List of defined Groups
|
||||
*/
|
||||
public List<MgmtRolloutGroup> getGroups() {
|
||||
return groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param groups List of {@link MgmtRolloutGroup}
|
||||
*/
|
||||
public void setGroups(List<MgmtRolloutGroup> groups) {
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the start at timestamp in millis or null
|
||||
*/
|
||||
public Long getStartAt() {
|
||||
return startAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startAt
|
||||
* the start at timestamp in millis or null
|
||||
*/
|
||||
public void setStartAt(Long startAt) {
|
||||
this.startAt = startAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* 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.json.model.rollout;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutSuccessAction {
|
||||
|
||||
private SuccessAction action = SuccessAction.NEXTGROUP;
|
||||
private String expression = null;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public MgmtRolloutSuccessAction() {
|
||||
// needed for json creator
|
||||
}
|
||||
|
||||
public MgmtRolloutSuccessAction(final SuccessAction action, final String expression) {
|
||||
this.action = action;
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the action
|
||||
*/
|
||||
public SuccessAction getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param action
|
||||
* the action to set
|
||||
*/
|
||||
public void setAction(final SuccessAction action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the expession
|
||||
*/
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param expession
|
||||
* the expession to set
|
||||
*/
|
||||
public void setExpression(final String expession) {
|
||||
this.expression = expession;
|
||||
}
|
||||
|
||||
public enum SuccessAction {
|
||||
NEXTGROUP;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 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.json.model.rolloutgroup;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.rollout.AbstractMgmtRolloutConditionsEntity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
/**
|
||||
* Model for defining the Attributes of a Rollout Group
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutGroup extends AbstractMgmtRolloutConditionsEntity {
|
||||
|
||||
private String targetFilterQuery;
|
||||
private Float targetPercentage;
|
||||
|
||||
public String getTargetFilterQuery() {
|
||||
return targetFilterQuery;
|
||||
}
|
||||
|
||||
public void setTargetFilterQuery(final String targetFilterQuery) {
|
||||
this.targetFilterQuery = targetFilterQuery;
|
||||
}
|
||||
|
||||
public Float getTargetPercentage() {
|
||||
return targetPercentage;
|
||||
}
|
||||
|
||||
public void setTargetPercentage(Float targetPercentage) {
|
||||
this.targetPercentage = targetPercentage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.json.model.rolloutgroup;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Model for the rollout group annotated with json-annotations for easier
|
||||
* serialization and de-serialization.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtRolloutGroupResponseBody extends MgmtRolloutGroup {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long rolloutGroupId;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String status;
|
||||
|
||||
private int totalTargets;
|
||||
|
||||
private Map<String, Long> totalTargetsPerStatus;
|
||||
|
||||
public Long getRolloutGroupId() {
|
||||
return rolloutGroupId;
|
||||
}
|
||||
|
||||
public void setRolloutGroupId(final Long rolloutGroupId) {
|
||||
this.rolloutGroupId = rolloutGroupId;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(final String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getTotalTargets() {
|
||||
return totalTargets;
|
||||
}
|
||||
|
||||
public void setTotalTargets(final int totalTargets) {
|
||||
this.totalTargets = totalTargets;
|
||||
}
|
||||
|
||||
public Map<String, Long> getTotalTargetsPerStatus() {
|
||||
return totalTargetsPerStatus;
|
||||
}
|
||||
|
||||
public void addTotalTargetsPerStatus(final String status, final Long totalTargetCountByStatus) {
|
||||
if (totalTargetsPerStatus == null) {
|
||||
totalTargetsPerStatus = new HashMap<>();
|
||||
}
|
||||
|
||||
totalTargetsPerStatus.put(status, totalTargetCountByStatus);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* 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.json.model.softwaremodule;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for SoftwareModule to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSoftwareModule extends MgmtNamedEntity {
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long moduleId;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String version;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String type;
|
||||
|
||||
@JsonProperty
|
||||
private String vendor;
|
||||
|
||||
@JsonProperty
|
||||
private boolean deleted;
|
||||
|
||||
public void setDeleted(final boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public Long getModuleId() {
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void setModuleId(final Long moduleId) {
|
||||
this.moduleId = moduleId;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(final String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getVendor() {
|
||||
return vendor;
|
||||
}
|
||||
|
||||
public void setVendor(final String vendor) {
|
||||
this.vendor = vendor;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.json.model.softwaremodule;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtId;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Request Body of SoftwareModule for assignment operations (ID only).
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSoftwareModuleAssigment extends MgmtId {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* 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.json.model.softwaremodule;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* The representation of SoftwareModuleMetadata in the REST API for POST/Create.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSoftwareModuleMetadata {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String key;
|
||||
@JsonProperty
|
||||
private String value;
|
||||
@JsonProperty
|
||||
private boolean targetVisible;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(final String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isTargetVisible() {
|
||||
return targetVisible;
|
||||
}
|
||||
|
||||
public void setTargetVisible(final boolean targetVisible) {
|
||||
this.targetVisible = targetVisible;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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.json.model.softwaremodule;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* The representation of an meta data in the REST API for PUT/Update.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSoftwareModuleMetadataBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String value;
|
||||
@JsonProperty
|
||||
private Boolean targetVisible;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(final String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public Boolean isTargetVisible() {
|
||||
return targetVisible;
|
||||
}
|
||||
|
||||
public void setTargetVisible(final Boolean targetVisible) {
|
||||
this.targetVisible = targetVisible;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.softwaremodule;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body for SoftwareModule POST.
|
||||
*
|
||||
*/
|
||||
public class MgmtSoftwareModuleRequestBodyPost {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String version;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String type;
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
@JsonProperty
|
||||
private String vendor;
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPost setName(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version
|
||||
* the version to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPost setVersion(final String version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param type
|
||||
* the type to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPost setType(final String type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPost setDescription(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vendor
|
||||
*/
|
||||
public String getVendor() {
|
||||
return vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vendor
|
||||
* the vendor to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPost setVendor(final String vendor) {
|
||||
this.vendor = vendor;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* 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.json.model.softwaremodule;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body for SoftwareModule PUT.
|
||||
*
|
||||
*/
|
||||
public class MgmtSoftwareModuleRequestBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
@JsonProperty
|
||||
private String vendor;
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPut setDescription(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the vendor
|
||||
*/
|
||||
public String getVendor() {
|
||||
return vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param vendor
|
||||
* the vendor to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleRequestBodyPut setVendor(final String vendor) {
|
||||
this.vendor = vendor;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.json.model.softwaremoduletype;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for SoftwareModuleType to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSoftwareModuleType extends MgmtNamedEntity {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long moduleId;
|
||||
|
||||
@JsonProperty
|
||||
private String key;
|
||||
|
||||
@JsonProperty
|
||||
private int maxAssignments;
|
||||
|
||||
@JsonProperty
|
||||
private boolean deleted;
|
||||
|
||||
public boolean isDeleted() {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public void setDeleted(final boolean deleted) {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public Long getModuleId() {
|
||||
return moduleId;
|
||||
}
|
||||
|
||||
public void setModuleId(final Long moduleId) {
|
||||
this.moduleId = moduleId;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public void setKey(final String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public int getMaxAssignments() {
|
||||
return maxAssignments;
|
||||
}
|
||||
|
||||
public void setMaxAssignments(final int maxAssignments) {
|
||||
this.maxAssignments = maxAssignments;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.json.model.softwaremoduletype;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtId;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* Request Body of SoftwareModuleType for assignment operations (ID only).
|
||||
*
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSoftwareModuleTypeAssigment extends MgmtId {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* 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.json.model.softwaremoduletype;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body for SoftwareModuleType POST.
|
||||
*
|
||||
*/
|
||||
public class MgmtSoftwareModuleTypeRequestBodyPost extends MgmtSoftwareModuleTypeRequestBodyPut {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String key;
|
||||
|
||||
@JsonProperty
|
||||
private int maxAssignments;
|
||||
|
||||
@Override
|
||||
public MgmtSoftwareModuleTypeRequestBodyPost setDescription(final String description) {
|
||||
super.setDescription(description);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MgmtSoftwareModuleTypeRequestBodyPost setColour(final String colour) {
|
||||
super.setColour(colour);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleTypeRequestBodyPost setName(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* the key to set
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleTypeRequestBodyPost setKey(final String key) {
|
||||
this.key = key;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maxAssignments
|
||||
*/
|
||||
public int getMaxAssignments() {
|
||||
return maxAssignments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param maxAssignments
|
||||
* the maxAssignments to set
|
||||
*
|
||||
* @return updated body
|
||||
*/
|
||||
public MgmtSoftwareModuleTypeRequestBodyPost setMaxAssignments(final int maxAssignments) {
|
||||
this.maxAssignments = maxAssignments;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* 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.json.model.softwaremoduletype;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request Body for SoftwareModuleType PUT.
|
||||
*
|
||||
*/
|
||||
public class MgmtSoftwareModuleTypeRequestBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
@JsonProperty
|
||||
private String colour;
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public MgmtSoftwareModuleTypeRequestBodyPut setDescription(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getColour() {
|
||||
return colour;
|
||||
}
|
||||
|
||||
public MgmtSoftwareModuleTypeRequestBodyPut setColour(final String colour) {
|
||||
this.colour = colour;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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.json.model.system;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for a tenant configuration value to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemTenantConfigurationValue extends ResourceSupport {
|
||||
|
||||
@JsonInclude(Include.ALWAYS)
|
||||
private Object value;
|
||||
|
||||
@JsonInclude(Include.ALWAYS)
|
||||
private boolean isGlobal = true;
|
||||
|
||||
private Long lastModifiedAt;
|
||||
private String lastModifiedBy;
|
||||
private Long createdAt;
|
||||
private String createdBy;
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(final Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public boolean isGlobal() {
|
||||
return isGlobal;
|
||||
}
|
||||
|
||||
public void setGlobal(final boolean isGlobal) {
|
||||
this.isGlobal = isGlobal;
|
||||
}
|
||||
|
||||
public Long getLastModifiedAt() {
|
||||
return lastModifiedAt;
|
||||
}
|
||||
|
||||
public void setLastModifiedAt(final Long lastModifiedAt) {
|
||||
this.lastModifiedAt = lastModifiedAt;
|
||||
}
|
||||
|
||||
public String getLastModifiedBy() {
|
||||
return lastModifiedBy;
|
||||
}
|
||||
|
||||
public void setLastModifiedBy(final String lastModifiedBy) {
|
||||
this.lastModifiedBy = lastModifiedBy;
|
||||
}
|
||||
|
||||
public Long getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(final Long createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(final String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* 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.json.model.system;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for System Configuration for PUT.
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemTenantConfigurationValueRequest {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private Serializable value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the value of the MgmtSystemTenantConfigurationValueRequest
|
||||
*/
|
||||
public Serializable getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the MgmtSystemTenantConfigurationValueRequest
|
||||
*
|
||||
* @param value
|
||||
*/
|
||||
public void setValue(final Object value) {
|
||||
if (!(value instanceof Serializable)) {
|
||||
throw new IllegalArgumentException("The value muste be a instance of " + Serializable.class.getName());
|
||||
}
|
||||
this.value = (Serializable) value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.json.model.systemmanagement;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
|
||||
/**
|
||||
* Model representation of an Cache entry as json.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemCache {
|
||||
|
||||
private final String name;
|
||||
private final Collection<String> keys;
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name of the cache
|
||||
* @param cacheKeys
|
||||
* the keys which contains in the cache
|
||||
*/
|
||||
public MgmtSystemCache(final String name, final Collection<String> cacheKeys) {
|
||||
this.name = name;
|
||||
this.keys = cacheKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the keys
|
||||
*/
|
||||
public Collection<String> getKeys() {
|
||||
return keys;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MgmtSystemCache [name=" + name + ", keys=" + keys + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* 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.json.model.systemmanagement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Body for system statistics.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemStatisticsRest {
|
||||
|
||||
@JsonProperty
|
||||
private long overallTargets;
|
||||
|
||||
@JsonProperty
|
||||
private long overallArtifacts;
|
||||
|
||||
@JsonProperty
|
||||
private long overallArtifactVolumeInBytes;
|
||||
|
||||
@JsonProperty
|
||||
private long overallActions;
|
||||
|
||||
@JsonProperty
|
||||
private long overallTenants;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtSystemTenantServiceUsage> tenantStats;
|
||||
|
||||
public long getOverallTargets() {
|
||||
return overallTargets;
|
||||
}
|
||||
|
||||
public MgmtSystemStatisticsRest setOverallTargets(final long overallTargets) {
|
||||
this.overallTargets = overallTargets;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getOverallArtifacts() {
|
||||
return overallArtifacts;
|
||||
}
|
||||
|
||||
public MgmtSystemStatisticsRest setOverallArtifacts(final long overallArtifacts) {
|
||||
this.overallArtifacts = overallArtifacts;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getOverallArtifactVolumeInBytes() {
|
||||
return overallArtifactVolumeInBytes;
|
||||
}
|
||||
|
||||
public MgmtSystemStatisticsRest setOverallArtifactVolumeInBytes(final long overallArtifactVolumeInBytes) {
|
||||
this.overallArtifactVolumeInBytes = overallArtifactVolumeInBytes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getOverallActions() {
|
||||
return overallActions;
|
||||
}
|
||||
|
||||
public MgmtSystemStatisticsRest setOverallActions(final long overallActions) {
|
||||
this.overallActions = overallActions;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getOverallTenants() {
|
||||
return overallTenants;
|
||||
}
|
||||
|
||||
public MgmtSystemStatisticsRest setOverallTenants(final long overallTenants) {
|
||||
this.overallTenants = overallTenants;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void setTenantStats(final List<MgmtSystemTenantServiceUsage> tenantStats) {
|
||||
this.tenantStats = tenantStats;
|
||||
}
|
||||
|
||||
public List<MgmtSystemTenantServiceUsage> getTenantStats() {
|
||||
return tenantStats;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* 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.json.model.systemmanagement;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Response body for system usage report.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtSystemTenantServiceUsage {
|
||||
|
||||
@JsonProperty
|
||||
private String tenantName;
|
||||
|
||||
@JsonProperty
|
||||
private long targets;
|
||||
|
||||
@JsonProperty
|
||||
private long artifacts;
|
||||
|
||||
@JsonProperty
|
||||
private long actions;
|
||||
|
||||
@JsonProperty
|
||||
private long overallArtifactVolumeInBytes;
|
||||
|
||||
@JsonProperty
|
||||
private Map<String, String> usageData;
|
||||
|
||||
public void setTenantName(final String tenantName) {
|
||||
this.tenantName = tenantName;
|
||||
}
|
||||
|
||||
public long getTargets() {
|
||||
return targets;
|
||||
}
|
||||
|
||||
public void setTargets(final long targets) {
|
||||
this.targets = targets;
|
||||
}
|
||||
|
||||
public long getArtifacts() {
|
||||
return artifacts;
|
||||
}
|
||||
|
||||
public void setArtifacts(final long artifacts) {
|
||||
this.artifacts = artifacts;
|
||||
}
|
||||
|
||||
public long getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void setActions(final long actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public long getOverallArtifactVolumeInBytes() {
|
||||
return overallArtifactVolumeInBytes;
|
||||
}
|
||||
|
||||
public void setOverallArtifactVolumeInBytes(final long overallArtifactVolumeInBytes) {
|
||||
this.overallArtifactVolumeInBytes = overallArtifactVolumeInBytes;
|
||||
}
|
||||
|
||||
public String getTenantName() {
|
||||
return tenantName;
|
||||
}
|
||||
|
||||
public Map<String, String> getUsageData() {
|
||||
return usageData;
|
||||
}
|
||||
|
||||
public void setUsageData(final Map<String, String> usageData) {
|
||||
this.usageData = usageData;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.json.model.tag;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Request Body for PUT.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtAssignedDistributionSetRequestBody {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long distributionSetId;
|
||||
|
||||
public Long getDistributionSetId() {
|
||||
return distributionSetId;
|
||||
}
|
||||
|
||||
public MgmtAssignedDistributionSetRequestBody setDistributionSetId(final Long distributionSetId) {
|
||||
this.distributionSetId = distributionSetId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.json.model.tag;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Request Body for PUT.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtAssignedTargetRequestBody {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String controllerId;
|
||||
|
||||
public String getControllerId() {
|
||||
return controllerId;
|
||||
}
|
||||
|
||||
public MgmtAssignedTargetRequestBody setControllerId(final String controllerId) {
|
||||
this.controllerId = controllerId;
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.json.model.tag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* * A json annotated rest model for DSAssigmentResult to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtDistributionSetTagAssigmentResult {
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtDistributionSet> assignedDistributionSets;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtDistributionSet> unassignedDistributionSets;
|
||||
|
||||
public List<MgmtDistributionSet> getAssignedDistributionSets() {
|
||||
return assignedDistributionSets;
|
||||
}
|
||||
|
||||
public List<MgmtDistributionSet> getUnassignedDistributionSets() {
|
||||
return unassignedDistributionSets;
|
||||
}
|
||||
|
||||
public void setAssignedDistributionSets(final List<MgmtDistributionSet> assignedDistributionSets) {
|
||||
this.assignedDistributionSets = assignedDistributionSets;
|
||||
}
|
||||
|
||||
public void setUnassignedDistributionSets(final List<MgmtDistributionSet> unassignedDistributionSets) {
|
||||
this.unassignedDistributionSets = unassignedDistributionSets;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 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.json.model.tag;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for Tag to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTag extends MgmtNamedEntity {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long tagId;
|
||||
|
||||
@JsonProperty
|
||||
private String colour;
|
||||
|
||||
@JsonIgnore
|
||||
public void setTagId(final Long tagId) {
|
||||
this.tagId = tagId;
|
||||
}
|
||||
|
||||
public Long getTagId() {
|
||||
return tagId;
|
||||
}
|
||||
|
||||
public void setColour(final String colour) {
|
||||
this.colour = colour;
|
||||
}
|
||||
|
||||
public String getColour() {
|
||||
return colour;
|
||||
}
|
||||
}
|
||||
@@ -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.mgmt.json.model.tag;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Request Body for PUT/POST.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTagRequestBodyPut {
|
||||
|
||||
@JsonProperty
|
||||
private String colour;
|
||||
|
||||
@JsonProperty
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String description;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public MgmtTagRequestBodyPut setName(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public MgmtTagRequestBodyPut setDescription(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MgmtTagRequestBodyPut setColour(final String colour) {
|
||||
this.colour = colour;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getColour() {
|
||||
return colour;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.json.model.tag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* * A json annotated rest model for TargetTagAssigmentResult to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTargetTagAssigmentResult {
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtTarget> assignedTargets;
|
||||
|
||||
@JsonProperty
|
||||
private List<MgmtTarget> unassignedTargets;
|
||||
|
||||
public void setAssignedTargets(final List<MgmtTarget> assignedTargets) {
|
||||
this.assignedTargets = assignedTargets;
|
||||
}
|
||||
|
||||
public List<MgmtTarget> getAssignedTargets() {
|
||||
return assignedTargets;
|
||||
}
|
||||
|
||||
public void setUnassignedTargets(final List<MgmtTarget> unassignedTargets) {
|
||||
this.unassignedTargets = unassignedTargets;
|
||||
}
|
||||
|
||||
public List<MgmtTarget> getUnassignedTargets() {
|
||||
return unassignedTargets;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.target;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtId;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtMaintenanceWindowRequestBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
|
||||
|
||||
/**
|
||||
* Request Body of DistributionSet for assignment operations (ID only).
|
||||
*
|
||||
*/
|
||||
public class MgmtDistributionSetAssignment extends MgmtId {
|
||||
private long forcetime;
|
||||
private MgmtActionType type;
|
||||
|
||||
/**
|
||||
* {@link MgmtMaintenanceWindowRequestBody} object defining a schedule,
|
||||
* duration and timezone.
|
||||
*/
|
||||
private MgmtMaintenanceWindowRequestBody maintenanceWindow;
|
||||
|
||||
public MgmtActionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(final MgmtActionType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public long getForcetime() {
|
||||
return forcetime;
|
||||
}
|
||||
|
||||
public void setForcetime(final long forcetime) {
|
||||
this.forcetime = forcetime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link MgmtMaintenanceWindowRequestBody} for distribution set
|
||||
* assignment.
|
||||
*
|
||||
* @return {@link MgmtMaintenanceWindowRequestBody}.
|
||||
*/
|
||||
public MgmtMaintenanceWindowRequestBody getMaintenanceWindow() {
|
||||
return maintenanceWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets {@link MgmtMaintenanceWindowRequestBody} for distribution set
|
||||
* assignment.
|
||||
*
|
||||
* @param maintenanceWindow
|
||||
* as {@link MgmtMaintenanceWindowRequestBody}.
|
||||
*/
|
||||
public void setMaintenanceWindow(final MgmtMaintenanceWindowRequestBody maintenanceWindow) {
|
||||
this.maintenanceWindow = maintenanceWindow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.target;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtNamedEntity;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtPollStatus;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for Target to RESTful API representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTarget extends MgmtNamedEntity {
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String controllerId;
|
||||
|
||||
@JsonProperty
|
||||
private String updateStatus;
|
||||
|
||||
@JsonProperty
|
||||
private Long lastControllerRequestAt;
|
||||
|
||||
@JsonProperty
|
||||
private Long installedAt;
|
||||
|
||||
@JsonProperty
|
||||
private String ipAddress;
|
||||
|
||||
@JsonProperty
|
||||
private String address;
|
||||
|
||||
@JsonProperty
|
||||
private MgmtPollStatus pollStatus;
|
||||
|
||||
@JsonProperty
|
||||
private String securityToken;
|
||||
|
||||
/**
|
||||
* @return the controllerId
|
||||
*/
|
||||
public String getControllerId() {
|
||||
return controllerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param controllerId
|
||||
* the controllerId to set
|
||||
*/
|
||||
public void setControllerId(final String controllerId) {
|
||||
this.controllerId = controllerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the updateStatus
|
||||
*/
|
||||
public String getUpdateStatus() {
|
||||
return updateStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param updateStatus
|
||||
* the updateStatus to set
|
||||
*/
|
||||
public void setUpdateStatus(final String updateStatus) {
|
||||
this.updateStatus = updateStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastControllerRequestAt
|
||||
*/
|
||||
public Long getLastControllerRequestAt() {
|
||||
return lastControllerRequestAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lastControllerRequestAt
|
||||
* the lastControllerRequestAt to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setLastControllerRequestAt(final Long lastControllerRequestAt) {
|
||||
this.lastControllerRequestAt = lastControllerRequestAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the installedAt
|
||||
*/
|
||||
public Long getInstalledAt() {
|
||||
return installedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param installedAt
|
||||
* the installedAt to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setInstalledAt(final Long installedAt) {
|
||||
this.installedAt = installedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pollStatus
|
||||
*/
|
||||
public MgmtPollStatus getPollStatus() {
|
||||
return pollStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pollStatus
|
||||
* the pollStatus to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setPollStatus(final MgmtPollStatus pollStatus) {
|
||||
this.pollStatus = pollStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ipAddress
|
||||
*/
|
||||
public String getIpAddress() {
|
||||
return ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ipAddress
|
||||
* the ipAddress to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setIpAddress(final String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the securityToken
|
||||
*/
|
||||
public String getSecurityToken() {
|
||||
return securityToken;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void setAddress(final String address) {
|
||||
if (address != null) {
|
||||
URI.create(address);
|
||||
}
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param securityToken
|
||||
* the securityToken to set
|
||||
*/
|
||||
@JsonIgnore
|
||||
public void setSecurityToken(final String securityToken) {
|
||||
this.securityToken = securityToken;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.target;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link Map} with attributes of SP Target.
|
||||
*/
|
||||
public class MgmtTargetAttributes extends HashMap<String, String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2015 Bosch Software Innovations GmbH, Germany. All rights reserved.
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.json.model.target;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request body for target PUT/POST commands.
|
||||
*
|
||||
*/
|
||||
public class MgmtTargetRequestBody {
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String controllerId;
|
||||
|
||||
@JsonProperty
|
||||
private String address;
|
||||
|
||||
@JsonProperty
|
||||
private String securityToken;
|
||||
|
||||
public String getSecurityToken() {
|
||||
return securityToken;
|
||||
}
|
||||
|
||||
public void setSecurityToken(final String securityToken) {
|
||||
this.securityToken = securityToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the controllerId
|
||||
*/
|
||||
public String getControllerId() {
|
||||
return controllerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* the name to set
|
||||
*/
|
||||
public MgmtTargetRequestBody setName(final String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param description
|
||||
* the description to set
|
||||
*/
|
||||
public MgmtTargetRequestBody setDescription(final String description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param controllerId
|
||||
* the controllerId to set
|
||||
*/
|
||||
public MgmtTargetRequestBody setControllerId(final String controllerId) {
|
||||
this.controllerId = controllerId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(final String address) {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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.json.model.targetfilter;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtBaseEntity;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* A json annotated rest model for Target Filter Queries to RESTful API
|
||||
* representation.
|
||||
*
|
||||
*/
|
||||
@JsonInclude(Include.ALWAYS)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class MgmtTargetFilterQuery extends MgmtBaseEntity {
|
||||
|
||||
@JsonProperty(value = "id", required = true)
|
||||
private Long filterId;
|
||||
|
||||
@JsonProperty
|
||||
private String name;
|
||||
|
||||
@JsonProperty
|
||||
private String query;
|
||||
|
||||
@JsonProperty
|
||||
private Long autoAssignDistributionSet;
|
||||
|
||||
public Long getFilterId() {
|
||||
return filterId;
|
||||
}
|
||||
|
||||
public void setFilterId(final Long filterId) {
|
||||
this.filterId = filterId;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(final String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public Long getAutoAssignDistributionSet() {
|
||||
return autoAssignDistributionSet;
|
||||
}
|
||||
|
||||
public void setAutoAssignDistributionSet(final Long autoAssignDistributionSet) {
|
||||
this.autoAssignDistributionSet = autoAssignDistributionSet;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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.mgmt.json.model.targetfilter;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
/**
|
||||
* Request body for target PUT/POST commands.
|
||||
*
|
||||
*/
|
||||
public class MgmtTargetFilterQueryRequestBody {
|
||||
@JsonProperty(required = true)
|
||||
private String name;
|
||||
|
||||
@JsonProperty(required = true)
|
||||
private String query;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getQuery() {
|
||||
return query;
|
||||
}
|
||||
|
||||
public void setQuery(String query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
* 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.rest.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadataBodyPut;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPut;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtTargetAssignmentRequestBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtTargetAssignmentResponseBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModuleAssigment;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.targetfilter.MgmtTargetFilterQuery;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
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;
|
||||
|
||||
/**
|
||||
* REST Resource handling for DistributionSet CRUD operations.
|
||||
*/
|
||||
@RequestMapping(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDistributionSetRestApi {
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all DistributionSets .
|
||||
*
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of sets for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=name==abc}
|
||||
* @return a list of all set for a defined or default page request with
|
||||
* status OK. The response is always paged. In any failure the
|
||||
* JsonResponseExceptionHandler is handling the response.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtDistributionSet>> getDistributionSets(
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving a single DistributionSet .
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the set to retrieve
|
||||
*
|
||||
* @return a single DistributionSet with status OK.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}", produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtDistributionSet> getDistributionSet(@PathVariable("distributionSetId") Long distributionSetId);
|
||||
|
||||
/**
|
||||
* Handles the POST request of creating new distribution sets . The request
|
||||
* body must always be a list of sets.
|
||||
*
|
||||
* @param sets
|
||||
* the DistributionSets to be created.
|
||||
* @return In case all sets could successful created the ResponseEntity with
|
||||
* status code 201 - Created but without ResponseBody. In any
|
||||
* failure the JsonResponseExceptionHandler is handling the
|
||||
* response.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSet>> createDistributionSets(List<MgmtDistributionSetRequestBodyPost> sets);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request for a single DistributionSet .
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the DistributionSet to delete
|
||||
* @return status OK if delete as successful.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}")
|
||||
ResponseEntity<Void> deleteDistributionSet(@PathVariable("distributionSetId") Long distributionSetId);
|
||||
|
||||
/**
|
||||
* Handles the UPDATE request for a single DistributionSet .
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the DistributionSet to delete
|
||||
* @param toUpdate
|
||||
* with the data that needs updating
|
||||
*
|
||||
* @return status OK if update as successful with updated content.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}", consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaType.APPLICATION_JSON_VALUE,
|
||||
MediaTypes.HAL_JSON_VALUE })
|
||||
ResponseEntity<MgmtDistributionSet> updateDistributionSet(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
MgmtDistributionSetRequestBodyPut toUpdate);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving assigned targets to a specific
|
||||
* distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to retrieve the assigned
|
||||
* targets
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of targets for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=name==abc}
|
||||
* @return status OK if get request is successful with the paged list of
|
||||
* targets
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/assignedTargets", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtTarget>> getAssignedTargets(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving installed targets to a specific
|
||||
* distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to retrieve the assigned
|
||||
* targets
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of targets for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=name==abc}
|
||||
* @return status OK if get request is successful with the paged list of
|
||||
* targets
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/installedTargets", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtTarget>> getInstalledTargets(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request to retrieve target filter queries that have the
|
||||
* given distribution set as auto assign DS.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to retrieve the assigned
|
||||
* targets
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of targets for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search name parameter in the request URL, syntax
|
||||
* {@code q=myFilter}
|
||||
* @return status OK if get request is successful with the paged list of
|
||||
* targets
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/autoAssignTargetFilters", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtTargetFilterQuery>> getAutoAssignTargetFilterQueries(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the POST request of assigning multiple targets to a single
|
||||
* distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set within the URL path parameter
|
||||
* @param targetIds
|
||||
* the IDs of the target which should get assigned to the
|
||||
* distribution set given in the response body
|
||||
* @param offline
|
||||
* to <code>true</code> if update was executed offline, i.e. not
|
||||
* managed by hawkBit.
|
||||
* @return status OK if the assignment of the targets was successful and a
|
||||
* complex return body which contains information about the assigned
|
||||
* targets and the already assigned targets counters
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/assignedTargets", consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtTargetAssignmentResponseBody> createAssignedTarget(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
final List<MgmtTargetAssignmentRequestBody> targetIds,
|
||||
@RequestParam(value = "offline", required = false) boolean offline);
|
||||
|
||||
/**
|
||||
* Gets a paged list of meta data for a distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set for the meta data
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of targets for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=key==abc}
|
||||
* @return status OK if get request is successful with the paged list of
|
||||
* meta data
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtMetadata>> getMetadata(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Gets a single meta data value for a specific key of a distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to get the meta data from
|
||||
* @param metadataKey
|
||||
* the key of the meta data entry to retrieve the value from
|
||||
* @return status OK if get request is successful with the value of the meta
|
||||
* data
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtMetadata> getMetadataValue(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@PathVariable("metadataKey") String metadataKey);
|
||||
|
||||
/**
|
||||
* Updates a single meta data value of a distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to update the meta data entry
|
||||
* @param metadataKey
|
||||
* the key of the meta data to update the value
|
||||
* @param metadata
|
||||
* update body
|
||||
* @return status OK if the update request is successful and the updated
|
||||
* meta data result
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetId}/metadata/{metadataKey}", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtMetadata> updateMetadata(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@PathVariable("metadataKey") String metadataKey, MgmtMetadataBodyPut metadata);
|
||||
|
||||
/**
|
||||
* Deletes a single meta data entry from the distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to delete the meta data entry
|
||||
* @param metadataKey
|
||||
* the key of the meta data to delete
|
||||
* @return status OK if the delete request is successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}/metadata/{metadataKey}")
|
||||
ResponseEntity<Void> deleteMetadata(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@PathVariable("metadataKey") String metadataKey);
|
||||
|
||||
/**
|
||||
* Creates a list of meta data for a specific distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to create meta data for
|
||||
* @param metadataRest
|
||||
* the list of meta data entries to create
|
||||
* @return status created if post request is successful with the value of
|
||||
* the created meta data
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/metadata", consumes = {
|
||||
MediaType.APPLICATION_JSON_VALUE,
|
||||
MediaTypes.HAL_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtMetadata>> createMetadata(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
List<MgmtMetadata> metadataRest);
|
||||
|
||||
/**
|
||||
* Assigns a list of software modules to a distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to assign software modules for
|
||||
* @param softwareModuleIDs
|
||||
* the list of software modules ids to assign
|
||||
* @return http status
|
||||
*
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{distributionSetId}/assignedSM", consumes = {
|
||||
MediaType.APPLICATION_JSON_VALUE,
|
||||
MediaTypes.HAL_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<Void> assignSoftwareModules(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
List<MgmtSoftwareModuleAssigment> softwareModuleIDs);
|
||||
|
||||
/**
|
||||
* Deletes the assignment of the software module form the distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution set to reject the software module
|
||||
* for
|
||||
* @param softwareModuleId
|
||||
* the software module id to get rejected form the distribution
|
||||
* set
|
||||
* @return status OK if rejection was successful.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetId}/assignedSM/{softwareModuleId}")
|
||||
ResponseEntity<Void> deleteAssignSoftwareModules(@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@PathVariable("softwareModuleId") Long softwareModuleId);
|
||||
|
||||
/**
|
||||
* Handles the GET request for retrieving the assigned software modules of a
|
||||
* specific distribution set.
|
||||
*
|
||||
* @param distributionSetId
|
||||
* the ID of the distribution to retrieve
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of sets for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @return a list of the assigned software modules of a distribution set
|
||||
* with status OK, if none is assigned than {@code null}
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetId}/assignedSM", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtSoftwareModule>> getAssignedSoftwareModules(
|
||||
@PathVariable("distributionSetId") Long distributionSetId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam);
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* 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.rest.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedDistributionSetRequestBody;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtDistributionSetTagAssigmentResult;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTag;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
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;
|
||||
|
||||
/**
|
||||
* REST Resource handling for DistributionSetTag CRUD operations.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(MgmtRestConstants.DISTRIBUTIONSET_TAG_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDistributionSetTagRestApi {
|
||||
/**
|
||||
* Handles the GET request of retrieving all DistributionSet tags.
|
||||
*
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of DistributionSet tags for pagination,
|
||||
* might not be present in the rest request then default value
|
||||
* will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=name==abc}
|
||||
* @return a list of all target tags for a defined or default page request
|
||||
* with status OK. The response is always paged. In any failure the
|
||||
* JsonResponseExceptionHandler is handling the response.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtTag>> getDistributionSetTags(
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving a single distribution set tag.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
*
|
||||
* @return a single distribution set tag with status OK.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionsetTagId}", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtTag> getDistributionSetTag(@PathVariable("distributionsetTagId") Long distributionsetTagId);
|
||||
|
||||
/**
|
||||
* Handles the POST request of creating new distribution set tag. The
|
||||
* request body must always be a list of tags.
|
||||
*
|
||||
* @param tags
|
||||
* the distribution set tags to be created.
|
||||
* @return In case all modules could successful created the ResponseEntity
|
||||
* with status code 201 - Created. The Response Body are the created
|
||||
* distribution set tags but without ResponseBody.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtTag>> createDistributionSetTags(List<MgmtTagRequestBodyPut> tags);
|
||||
|
||||
/**
|
||||
*
|
||||
* Handles the PUT request of updating a single distribution set tag.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @param restDSTagRest
|
||||
* the the request body to be updated
|
||||
* @return status OK if update is successful and the updated distribution
|
||||
* set tag.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT, value = "/{distributionsetTagId}", consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtTag> updateDistributionSetTag(@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
MgmtTagRequestBodyPut restDSTagRest);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request for a single distribution set tag.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @return status OK if delete as successfully.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionsetTagId}")
|
||||
ResponseEntity<Void> deleteDistributionSetTag(@PathVariable("distributionsetTagId") Long distributionsetTagId);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all assigned distribution sets by
|
||||
* the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of target tags for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=name==abc}
|
||||
*
|
||||
* @return the list of assigned distribution sets.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtDistributionSet>> getAssignedDistributionSets(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all assigned distribution sets by
|
||||
* the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
*
|
||||
* @return the list of assigned distribution sets.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link #getAssignedDistributionSets(Long, int, int, String, String)}
|
||||
* instead as this variant does not include paging and as result
|
||||
* returns only a limited list of distributionsets
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestMapping(method = RequestMethod.GET, value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSet>> getAssignedDistributionSets(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId);
|
||||
|
||||
/**
|
||||
* Handles the POST request to toggle the assignment of distribution sets by
|
||||
* the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
* @param assignedDSRequestBodies
|
||||
* list of distribution set ids to be toggled
|
||||
*
|
||||
* @return the list of assigned distribution sets and unassigned
|
||||
* distribution sets.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING
|
||||
+ "/toggleTagAssignment")
|
||||
ResponseEntity<MgmtDistributionSetTagAssigmentResult> toggleTagAssignment(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to toggle the assignment of distribution sets by
|
||||
* the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
* @param assignedDSRequestBodies
|
||||
* list of distribution set ids to be toggled
|
||||
*
|
||||
* @return the list of assigned distribution sets and unassigned
|
||||
* distribution sets.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link MgmtDistributionSetTagRestApi#toggleTagAssignment}
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING
|
||||
+ "/toggleTagAssignment")
|
||||
ResponseEntity<MgmtDistributionSetTagAssigmentResult> toggleTagAssignmentUnpaged(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to assign distribution sets to the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
* @param assignedDSRequestBodies
|
||||
* list of distribution sets ids to be assigned
|
||||
*
|
||||
* @return the list of assigned distribution set.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSet>> assignDistributionSets(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the POST request to assign distribution sets to the given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag to retrieve
|
||||
* @param assignedDSRequestBodies
|
||||
* list of distribution sets ids to be assigned
|
||||
*
|
||||
* @return the list of assigned distribution set.
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link MgmtDistributionSetTagRestApi#assignDistributionSets}
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestMapping(method = RequestMethod.POST, value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING, consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSet>> assignDistributionSetsUnpaged(
|
||||
@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
List<MgmtAssignedDistributionSetRequestBody> assignedDSRequestBodies);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request to unassign one distribution set from the
|
||||
* given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @param distributionsetId
|
||||
* the ID of the distribution set to unassign
|
||||
* @return http status code
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = MgmtRestConstants.DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING
|
||||
+ "/{distributionsetId}")
|
||||
ResponseEntity<Void> unassignDistributionSet(@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
@PathVariable("distributionsetId") Long distributionsetId);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request to unassign one distribution set from the
|
||||
* given tag id.
|
||||
*
|
||||
* @param distributionsetTagId
|
||||
* the ID of the distribution set tag
|
||||
* @param distributionsetId
|
||||
* the ID of the distribution set to unassign
|
||||
* @return http status code
|
||||
*
|
||||
* @deprecated please use
|
||||
* {@link MgmtDistributionSetTagRestApi#unassignDistributionSet}
|
||||
*/
|
||||
@Deprecated
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = MgmtRestConstants.DEPRECATED_DISTRIBUTIONSET_TAG_DISTRIBUTIONSETS_REQUEST_MAPPING
|
||||
+ "/{distributionsetId}")
|
||||
ResponseEntity<Void> unassignDistributionSetUnpaged(@PathVariable("distributionsetTagId") Long distributionsetTagId,
|
||||
@PathVariable("distributionsetId") Long distributionsetId);
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* 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.rest.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.mgmt.json.model.MgmtId;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetType;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPut;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
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;
|
||||
|
||||
/**
|
||||
* REST Resource handling for SoftwareModule and related Artifact CRUD
|
||||
* operations.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_REQUEST_MAPPING)
|
||||
public interface MgmtDistributionSetTypeRestApi {
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving all DistributionSetTypes.
|
||||
*
|
||||
* @param pagingOffsetParam
|
||||
* the offset of list of modules for pagination, might not be
|
||||
* present in the rest request then default value will be applied
|
||||
* @param pagingLimitParam
|
||||
* the limit of the paged request, might not be present in the
|
||||
* rest request then default value will be applied
|
||||
* @param sortParam
|
||||
* the sorting parameter in the request URL, syntax
|
||||
* {@code field:direction, field:direction}
|
||||
* @param rsqlParam
|
||||
* the search parameter in the request URL, syntax
|
||||
* {@code q=name==abc}
|
||||
*
|
||||
* @return a list of all DistributionSetType for a defined or default page
|
||||
* request with status OK. The response is always paged. In any
|
||||
* failure the JsonResponseExceptionHandler is handling the
|
||||
* response.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<PagedList<MgmtDistributionSetType>> getDistributionSetTypes(
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_OFFSET, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET) int pagingOffsetParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_PAGING_LIMIT, defaultValue = MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT) int pagingLimitParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SORTING, required = false) String sortParam,
|
||||
@RequestParam(value = MgmtRestConstants.REQUEST_PARAMETER_SEARCH, required = false) String rsqlParam);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving a single DistributionSetType
|
||||
* within.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* the ID of the module type to retrieve
|
||||
*
|
||||
* @return a single softwareModule with status OK.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}", produces = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtDistributionSetType> getDistributionSetType(
|
||||
@PathVariable("distributionSetTypeId") Long distributionSetTypeId);
|
||||
|
||||
/**
|
||||
* Handles the DELETE request for a single Distribution Set Type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* the ID of the module to retrieve
|
||||
* @return status OK if delete as sucessfull.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}")
|
||||
ResponseEntity<Void> deleteDistributionSetType(@PathVariable("distributionSetTypeId") Long distributionSetTypeId);
|
||||
|
||||
/**
|
||||
* Handles the PUT request of updating a Distribution Set Type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* the ID of the software module in the URL
|
||||
* @param restDistributionSetType
|
||||
* the module type to be updated.
|
||||
* @return status OK if update is successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT, value = "/{distributionSetTypeId}", consumes = {
|
||||
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtDistributionSetType> updateDistributionSetType(
|
||||
@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
MgmtDistributionSetTypeRequestBodyPut restDistributionSetType);
|
||||
|
||||
/**
|
||||
* Handles the POST request of creating new DistributionSetTypes. The
|
||||
* request body must always be a list of types.
|
||||
*
|
||||
* @param distributionSetTypes
|
||||
* the modules to be created.
|
||||
* @return In case all modules could successful created the ResponseEntity
|
||||
* with status code 201 - Created but without ResponseBody. In any
|
||||
* failure the JsonResponseExceptionHandler is handling the
|
||||
* response.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE }, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtDistributionSetType>> createDistributionSetTypes(
|
||||
List<MgmtDistributionSetTypeRequestBodyPost> distributionSetTypes);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving the list of mandatory software
|
||||
* module types in that distribution set type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @return Unpaged list of module types and OK in case of success.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtSoftwareModuleType>> getMandatoryModules(
|
||||
@PathVariable("distributionSetTypeId") Long distributionSetTypeId);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving the single mandatory software
|
||||
* module type in that distribution set type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @param softwareModuleTypeId
|
||||
* of SoftwareModuleType.
|
||||
* @return Unpaged list of module types and OK in case of success.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES
|
||||
+ "/{softwareModuleTypeId}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtSoftwareModuleType> getMandatoryModule(
|
||||
@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
@PathVariable("softwareModuleTypeId") Long softwareModuleTypeId);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving the single optional software module
|
||||
* type in that distribution set type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @param softwareModuleTypeId
|
||||
* of SoftwareModuleType.
|
||||
* @return Unpaged list of module types and OK in case of success.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES
|
||||
+ "/{softwareModuleTypeId}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtSoftwareModuleType> getOptionalModule(
|
||||
@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
@PathVariable("softwareModuleTypeId") Long softwareModuleTypeId);
|
||||
|
||||
/**
|
||||
* Handles the GET request of retrieving the list of optional software
|
||||
* module types in that distribution set type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @return Unpaged list of module types and OK in case of success.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES, produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<List<MgmtSoftwareModuleType>> getOptionalModules(
|
||||
@PathVariable("distributionSetTypeId") Long distributionSetTypeId);
|
||||
|
||||
/**
|
||||
* Handles DELETE request for removing a mandatory module from the
|
||||
* DistributionSetType.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @param softwareModuleTypeId
|
||||
* of the SoftwareModuleType to remove
|
||||
*
|
||||
* @return OK if the request was successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES + "/{softwareModuleTypeId}")
|
||||
ResponseEntity<Void> removeMandatoryModule(@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
@PathVariable("softwareModuleTypeId") Long softwareModuleTypeId);
|
||||
|
||||
/**
|
||||
* Handles DELETE request for removing an optional module from the
|
||||
* DistributionSetType.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @param softwareModuleTypeId
|
||||
* of the SoftwareModuleType to remove
|
||||
*
|
||||
* @return OK if the request was successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES + "/{softwareModuleTypeId}")
|
||||
ResponseEntity<Void> removeOptionalModule(@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
@PathVariable("softwareModuleTypeId") Long softwareModuleTypeId);
|
||||
|
||||
/**
|
||||
* Handles the POST request for adding a mandatory software module type to a
|
||||
* distribution set type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @param smtId
|
||||
* of the SoftwareModuleType to add
|
||||
*
|
||||
* @return OK if the request was successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_MANDATORY_MODULE_TYPES, consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<Void> addMandatoryModule(@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
MgmtId smtId);
|
||||
|
||||
/**
|
||||
* Handles the POST request for adding an optional software module type to a
|
||||
* distribution set type.
|
||||
*
|
||||
* @param distributionSetTypeId
|
||||
* of the DistributionSetType.
|
||||
* @param smtId
|
||||
* of the SoftwareModuleType to add
|
||||
*
|
||||
* @return OK if the request was successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{distributionSetTypeId}/"
|
||||
+ MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULE_TYPES, consumes = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<Void> addOptionalModule(@PathVariable("distributionSetTypeId") Long distributionSetTypeId,
|
||||
MgmtId smtId);
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.rest.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
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.ResponseBody;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@RequestMapping(MgmtRestConstants.SOFTWAREMODULE_V1_REQUEST_MAPPING)
|
||||
@FunctionalInterface
|
||||
public interface MgmtDownloadArtifactRestApi {
|
||||
|
||||
/**
|
||||
* Handles the GET request for downloading an artifact.
|
||||
*
|
||||
* @param softwareModuleId
|
||||
* of the parent SoftwareModule
|
||||
* @param artifactId
|
||||
* of the related LocalArtifact
|
||||
* @param servletResponse
|
||||
* of the servlet
|
||||
* @param request
|
||||
* of the client
|
||||
*
|
||||
* @return responseEntity with status ok if successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{softwareModuleId}/artifacts/{artifactId}/download")
|
||||
@ResponseBody
|
||||
ResponseEntity<InputStream> downloadArtifact(@PathVariable("softwareModuleId") Long softwareModuleId,
|
||||
@PathVariable("artifactId") Long artifactId);
|
||||
|
||||
}
|
||||
@@ -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
|
||||
*/
|
||||
package org.eclipse.hawkbit.mgmt.rest.api;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
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.ResponseBody;
|
||||
|
||||
/**
|
||||
* A resource for download artifacts.
|
||||
*
|
||||
*/
|
||||
@RequestMapping(MgmtRestConstants.DOWNLOAD_ID_V1_REQUEST_MAPPING_BASE)
|
||||
@FunctionalInterface
|
||||
public interface MgmtDownloadRestApi {
|
||||
|
||||
/**
|
||||
* Handles the GET request for downloading an artifact.
|
||||
*
|
||||
* @param tenant
|
||||
* the download belongs to
|
||||
* @param downloadId
|
||||
* the generated download id
|
||||
* @param response
|
||||
* of the servlet
|
||||
* @return {@link ResponseEntity} with status {@link HttpStatus#OK} if
|
||||
* successful
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET, value = MgmtRestConstants.DOWNLOAD_ID_V1_REQUEST_MAPPING)
|
||||
@ResponseBody
|
||||
ResponseEntity<InputStream> downloadArtifactByDownloadId(@PathVariable("tenant") String tenant,
|
||||
@PathVariable("downloadId") String downloadId);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user