Code format hawkbit-ddi-resource (#1941)
Signed-off-by: Marinov Avgustin <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
# Eclipse.IoT hawkBit - DDI Resource
|
# 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.
|
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
|
# Compile
|
||||||
|
|
||||||
|
|||||||
@@ -10,104 +10,105 @@
|
|||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<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"
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
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>
|
xmlns="http://maven.apache.org/POM/4.0.0">
|
||||||
<parent>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<parent>
|
||||||
<artifactId>hawkbit-rest-parent</artifactId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<version>${revision}</version>
|
<artifactId>hawkbit-rest-parent</artifactId>
|
||||||
</parent>
|
<version>${revision}</version>
|
||||||
<artifactId>hawkbit-ddi-resource</artifactId>
|
</parent>
|
||||||
<name>hawkBit :: REST :: DDI Resources</name>
|
<artifactId>hawkbit-ddi-resource</artifactId>
|
||||||
|
<name>hawkBit :: REST :: DDI Resources</name>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-ddi-api</artifactId>
|
<artifactId>hawkbit-ddi-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-rest-core</artifactId>
|
<artifactId>hawkbit-rest-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-repository-api</artifactId>
|
<artifactId>hawkbit-repository-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.plugin</groupId>
|
<groupId>org.springframework.plugin</groupId>
|
||||||
<artifactId>spring-plugin-core</artifactId>
|
<artifactId>spring-plugin-core</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.servlet</groupId>
|
<groupId>jakarta.servlet</groupId>
|
||||||
<artifactId>jakarta.servlet-api</artifactId>
|
<artifactId>jakarta.servlet-api</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!-- Test -->
|
<!-- Test -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-repository-test</artifactId>
|
<artifactId>hawkbit-repository-test</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-repository-jpa</artifactId>
|
<artifactId>hawkbit-repository-jpa</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-rest-core</artifactId>
|
<artifactId>hawkbit-rest-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<classifier>tests</classifier>
|
<classifier>tests</classifier>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.el</groupId>
|
<groupId>javax.el</groupId>
|
||||||
<artifactId>javax.el-api</artifactId>
|
<artifactId>javax.el-api</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-config</artifactId>
|
<artifactId>spring-security-config</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.hawkbit</groupId>
|
<groupId>org.eclipse.hawkbit</groupId>
|
||||||
<artifactId>hawkbit-http-security</artifactId>
|
<artifactId>hawkbit-http-security</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-json</artifactId>
|
<artifactId>spring-boot-starter-json</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.security</groupId>
|
<groupId>org.springframework.security</groupId>
|
||||||
<artifactId>spring-security-aspects</artifactId>
|
<artifactId>spring-security-aspects</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.qameta.allure</groupId>
|
<groupId>io.qameta.allure</groupId>
|
||||||
<artifactId>allure-junit5</artifactId>
|
<artifactId>allure-junit5</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
<artifactId>spring-context-support</artifactId>
|
<artifactId>spring-context-support</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -45,72 +45,12 @@ import org.springframework.util.CollectionUtils;
|
|||||||
* Utility class for the DDI API.
|
* Utility class for the DDI API.
|
||||||
*/
|
*/
|
||||||
public final class DataConversionHelper {
|
public final class DataConversionHelper {
|
||||||
|
|
||||||
// utility class, private constructor.
|
// utility class, private constructor.
|
||||||
private DataConversionHelper() {
|
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 new ResponseList<>(uAction.getDistributionSet().getModules().stream()
|
|
||||||
.map(module -> new DdiChunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
|
|
||||||
module.getName(), module.isEncrypted() ? Boolean.TRUE : null,
|
|
||||||
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(), artifact.getSha256Hash()));
|
|
||||||
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(Link.of(entry.getRef()).withRel(entry.getRel()).expand()));
|
|
||||||
|
|
||||||
return file;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DdiConfirmationBase createConfirmationBase(final Target target, final Action activeAction,
|
public static DdiConfirmationBase createConfirmationBase(final Target target, final Action activeAction,
|
||||||
final DdiAutoConfirmationState autoConfirmationState, final TenantAware tenantAware) {
|
final DdiAutoConfirmationState autoConfirmationState, final TenantAware tenantAware) {
|
||||||
final String controllerId = target.getControllerId();
|
final String controllerId = target.getControllerId();
|
||||||
@@ -145,9 +85,9 @@ public final class DataConversionHelper {
|
|||||||
if (activeAction != null) {
|
if (activeAction != null) {
|
||||||
if (activeAction.isWaitingConfirmation()) {
|
if (activeAction.isWaitingConfirmation()) {
|
||||||
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
|
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
|
||||||
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||||
.getConfirmationBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(),
|
.getConfirmationBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||||
activeAction.getId(), calculateEtag(activeAction), null))
|
activeAction.getId(), calculateEtag(activeAction), null))
|
||||||
.withRel(DdiRestConstants.CONFIRMATION_BASE).expand());
|
.withRel(DdiRestConstants.CONFIRMATION_BASE).expand());
|
||||||
|
|
||||||
} else if (activeAction.isCancelingOrCanceled()) {
|
} else if (activeAction.isCancelingOrCanceled()) {
|
||||||
@@ -163,9 +103,9 @@ public final class DataConversionHelper {
|
|||||||
// change the payload of the
|
// change the payload of the
|
||||||
// response because of eTags.
|
// response because of eTags.
|
||||||
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
|
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
|
||||||
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||||
.getControllerDeploymentBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(),
|
.getControllerDeploymentBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||||
activeAction.getId(), calculateEtag(activeAction), null))
|
activeAction.getId(), calculateEtag(activeAction), null))
|
||||||
.withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand());
|
.withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,13 +129,73 @@ public final class DataConversionHelper {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 new ResponseList<>(uAction.getDistributionSet().getModules().stream()
|
||||||
|
.map(module -> new DdiChunk(mapChunkLegacyKeys(module.getType().getKey()), module.getVersion(),
|
||||||
|
module.getName(), module.isEncrypted() ? Boolean.TRUE : null,
|
||||||
|
createArtifacts(target, module, artifactUrlHandler, systemManagement, request),
|
||||||
|
mapMetadata(metadata.get(module.getId()))))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(), artifact.getSha256Hash()));
|
||||||
|
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(Link.of(entry.getRef()).withRel(entry.getRel()).expand()));
|
||||||
|
|
||||||
|
return file;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates an etag for the given {@link Action} based on the entities
|
* Calculates an etag for the given {@link Action} based on the entities
|
||||||
* hashcode and the {@link Action#isHitAutoForceTime(long)} to reflect a
|
* hashcode and the {@link Action#isHitAutoForceTime(long)} to reflect a
|
||||||
* force switch.
|
* force switch.
|
||||||
*
|
*
|
||||||
* @param action
|
* @param action to calculate the etag for
|
||||||
* to calculate the etag for
|
|
||||||
* @return the etag
|
* @return the etag
|
||||||
*/
|
*/
|
||||||
private static int calculateEtag(final Action action) {
|
private static int calculateEtag(final Action action) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import org.springframework.stereotype.Controller;
|
|||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
@ComponentScan
|
@ComponentScan
|
||||||
@Import({RestConfiguration.class, OpenApiConfiguration.class})
|
@Import({ RestConfiguration.class, OpenApiConfiguration.class })
|
||||||
public class DdiApiConfiguration {
|
public class DdiApiConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import java.util.Optional;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import jakarta.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
import jakarta.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
import org.eclipse.hawkbit.api.ArtifactUrlHandler;
|
||||||
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
import org.eclipse.hawkbit.artifact.repository.model.DbArtifact;
|
||||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
|
|||||||
import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory;
|
import org.eclipse.hawkbit.ddi.json.model.DdiActionHistory;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation;
|
import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
|
import org.eclipse.hawkbit.ddi.json.model.DdiArtifact;
|
||||||
|
import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiAutoConfirmationState;
|
import org.eclipse.hawkbit.ddi.json.model.DdiAutoConfirmationState;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiCancel;
|
import org.eclipse.hawkbit.ddi.json.model.DdiCancel;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiCancelActionToStop;
|
import org.eclipse.hawkbit.ddi.json.model.DdiCancelActionToStop;
|
||||||
@@ -41,7 +42,6 @@ import org.eclipse.hawkbit.ddi.json.model.DdiDeployment;
|
|||||||
import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.DdiMaintenanceWindowStatus;
|
import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.DdiMaintenanceWindowStatus;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.HandlingType;
|
import org.eclipse.hawkbit.ddi.json.model.DdiDeployment.HandlingType;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase;
|
import org.eclipse.hawkbit.ddi.json.model.DdiDeploymentBase;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion;
|
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult.FinalResult;
|
import org.eclipse.hawkbit.ddi.json.model.DdiResult.FinalResult;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiUpdateMode;
|
import org.eclipse.hawkbit.ddi.json.model.DdiUpdateMode;
|
||||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||||
@@ -99,7 +99,7 @@ import org.springframework.web.context.WebApplicationContext;
|
|||||||
@RestController
|
@RestController
|
||||||
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
|
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
|
||||||
public class DdiRootController implements DdiRootControllerRestApi {
|
public class DdiRootController implements DdiRootControllerRestApi {
|
||||||
|
|
||||||
private static final String GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET = "given action ({}) is not assigned to given target ({}).";
|
private static final String GIVEN_ACTION_IS_NOT_ASSIGNED_TO_GIVEN_TARGET = "given action ({}) is not assigned to given target ({}).";
|
||||||
private static final String FALLBACK_REMARK = "Initiated using the Device Direct Integration API without providing a remark.";
|
private static final String FALLBACK_REMARK = "Initiated using the Device Direct Integration API without providing a remark.";
|
||||||
|
|
||||||
@@ -208,36 +208,14 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
RequestResponseContextHolder.getHttpServletRequest(),
|
RequestResponseContextHolder.getHttpServletRequest(),
|
||||||
(length, shippedSinceLastEvent,
|
(length, shippedSinceLastEvent,
|
||||||
total) -> eventPublisher.publishEvent(new DownloadProgressEvent(
|
total) -> eventPublisher.publishEvent(new DownloadProgressEvent(
|
||||||
tenantAware.getCurrentTenant(), statusId, shippedSinceLastEvent,
|
tenantAware.getCurrentTenant(), statusId, shippedSinceLastEvent,
|
||||||
serviceMatcher != null ? serviceMatcher.getBusId() : bus.getId())));
|
serviceMatcher != null ? serviceMatcher.getBusId() : bus.getId())));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
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");
|
|
||||||
|
|
||||||
final 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 module == null || module.getArtifactByFilename(fileName).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
// Exception squid:S3655 - Optional access is checked in checkModule
|
// Exception squid:S3655 - Optional access is checked in checkModule
|
||||||
// subroutine
|
// subroutine
|
||||||
@@ -301,30 +279,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
return ResponseEntity.notFound().build();
|
return ResponseEntity.notFound().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HandlingType calculateDownloadType(final Action action) {
|
|
||||||
if (action.isDownloadOnly() || action.isForcedOrTimeForced()) {
|
|
||||||
return HandlingType.FORCED;
|
|
||||||
}
|
|
||||||
return HandlingType.ATTEMPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
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.isDownloadOnly()) {
|
|
||||||
return HandlingType.SKIP;
|
|
||||||
} else if (action.hasMaintenanceSchedule()) {
|
|
||||||
return action.isMaintenanceWindowAvailable() ? downloadType : HandlingType.SKIP;
|
|
||||||
}
|
|
||||||
return downloadType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<Void> postDeploymentBaseActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
|
public ResponseEntity<Void> postDeploymentBaseActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
|
||||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
||||||
@@ -349,91 +303,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
return ResponseEntity.ok().build();
|
return ResponseEntity.ok().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId,
|
|
||||||
final Long actionId) {
|
|
||||||
|
|
||||||
final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
|
|
||||||
|
|
||||||
final List<String> messages = new ArrayList<>();
|
|
||||||
|
|
||||||
if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) {
|
|
||||||
messages.addAll(feedback.getStatus().getDetails());
|
|
||||||
}
|
|
||||||
|
|
||||||
final Integer code = feedback.getStatus().getCode();
|
|
||||||
if (code != null) {
|
|
||||||
actionStatusCreate.code(code);
|
|
||||||
messages.add("Device reported status code: " + code);
|
|
||||||
}
|
|
||||||
|
|
||||||
final 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 cancellation.", 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 actionStatusCreate.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) {
|
|
||||||
final 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) {
|
|
||||||
final 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
|
@Override
|
||||||
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
|
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
|
||||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) {
|
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) {
|
||||||
@@ -501,6 +370,149 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<DdiConfirmationBase> getConfirmationBase(final String tenant, final String controllerId) {
|
||||||
|
log.debug("getConfirmationBase is called [controllerId={}].", controllerId);
|
||||||
|
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(controllerId, IpUtil
|
||||||
|
.getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties));
|
||||||
|
final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null);
|
||||||
|
|
||||||
|
final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId);
|
||||||
|
|
||||||
|
final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase(target, activeAction,
|
||||||
|
autoConfirmationState, tenantAware);
|
||||||
|
return new ResponseEntity<>(confirmationBase, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<DdiConfirmationBaseAction> getConfirmationBaseAction(
|
||||||
|
@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("getConfirmationBaseAction({},{})", controllerId, resource);
|
||||||
|
|
||||||
|
final Target target = findTarget(controllerId);
|
||||||
|
final Action action = findActionForTarget(actionId, target);
|
||||||
|
|
||||||
|
checkAndCancelExpiredAction(action);
|
||||||
|
|
||||||
|
if (!action.isCancelingOrCanceled() && action.isWaitingConfirmation()) {
|
||||||
|
|
||||||
|
final DdiConfirmationBaseAction base = generateDdiConfirmationBase(target, action,
|
||||||
|
actionHistoryMessageCount);
|
||||||
|
|
||||||
|
log.debug("Found an active UpdateAction for target {}. Returning confirmation: {}", controllerId, base);
|
||||||
|
|
||||||
|
return new ResponseEntity<>(base, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> postConfirmationActionFeedback(
|
||||||
|
@Valid @RequestBody final DdiConfirmationFeedback feedback, @PathVariable("tenant") final String tenant,
|
||||||
|
@PathVariable("controllerId") final String controllerId,
|
||||||
|
@PathVariable("actionId") @NotNull final Long actionId) {
|
||||||
|
log.debug("provideConfirmationActionFeedback with feedback [controllerId={}, actionId={}]: {}", controllerId,
|
||||||
|
actionId, feedback);
|
||||||
|
|
||||||
|
final Target target = findTarget(controllerId);
|
||||||
|
final Action action = findActionForTarget(actionId, target);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
switch (feedback.getConfirmation()) {
|
||||||
|
case CONFIRMED:
|
||||||
|
log.info("Controller confirmed the action (actionId: {}, controllerId: {}) as we got {} report.",
|
||||||
|
actionId, controllerId, feedback.getConfirmation());
|
||||||
|
confirmationManagement.confirmAction(actionId, feedback.getCode(), feedback.getDetails());
|
||||||
|
break;
|
||||||
|
case DENIED:
|
||||||
|
default:
|
||||||
|
log.debug("Controller denied the action (actionId: {}, controllerId: {}) as we got {} report.",
|
||||||
|
actionId, controllerId, feedback.getConfirmation());
|
||||||
|
confirmationManagement.denyAction(actionId, feedback.getCode(), feedback.getDetails());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (final InvalidConfirmationFeedbackException e) {
|
||||||
|
if (e.getReason() == InvalidConfirmationFeedbackException.Reason.ACTION_CLOSED) {
|
||||||
|
log.warn("Updating action {} with confirmation {} not possible since action not active anymore.",
|
||||||
|
action.getId(), feedback.getConfirmation());
|
||||||
|
return new ResponseEntity<>(HttpStatus.GONE);
|
||||||
|
} else if (e.getReason() == InvalidConfirmationFeedbackException.Reason.NOT_AWAITING_CONFIRMATION) {
|
||||||
|
log.debug("Action is not waiting for confirmation, deny request.");
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> activateAutoConfirmation(final String tenant, final String controllerId,
|
||||||
|
final DdiActivateAutoConfirmation body) {
|
||||||
|
final String initiator = body == null ? null : body.getInitiator();
|
||||||
|
final String remark = body == null ? FALLBACK_REMARK : body.getRemark();
|
||||||
|
log.debug("Activate auto-confirmation request for device '{}' with payload: [initiator='{}' | remark='{}'",
|
||||||
|
controllerId, initiator, remark);
|
||||||
|
confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark);
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> deactivateAutoConfirmation(final String tenant, final String controllerId) {
|
||||||
|
log.debug("Deactivate auto-confirmation request for device ‘{}‘", controllerId);
|
||||||
|
confirmationManagement.deactivateAutoConfirmation(controllerId);
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<Void> setAsssignedOfflineVersion(@Valid @RequestBody DdiAssignedVersion ddiAssignedVersion,
|
||||||
|
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) {
|
||||||
|
boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId,
|
||||||
|
ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion());
|
||||||
|
if (updated) {
|
||||||
|
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||||
|
}
|
||||||
|
return new ResponseEntity<>(HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean checkModule(final String fileName, final SoftwareModule module) {
|
||||||
|
return module == null || module.getArtifactByFilename(fileName).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HandlingType calculateDownloadType(final Action action) {
|
||||||
|
if (action.isDownloadOnly() || action.isForcedOrTimeForced()) {
|
||||||
|
return HandlingType.FORCED;
|
||||||
|
}
|
||||||
|
return HandlingType.ATTEMPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
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.isDownloadOnly()) {
|
||||||
|
return HandlingType.SKIP;
|
||||||
|
} else if (action.hasMaintenanceSchedule()) {
|
||||||
|
return action.isMaintenanceWindowAvailable() ? downloadType : HandlingType.SKIP;
|
||||||
|
}
|
||||||
|
return downloadType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addMessageIfEmpty(final String text, final List<String> messages) {
|
||||||
|
if (messages != null && messages.isEmpty()) {
|
||||||
|
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + text + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static ActionStatusCreate generateActionCancelStatus(final DdiActionFeedback feedback, final Target target,
|
private static ActionStatusCreate generateActionCancelStatus(final DdiActionFeedback feedback, final Target target,
|
||||||
final Long actionId, final EntityFactory entityFactory) {
|
final Long actionId, final EntityFactory entityFactory) {
|
||||||
|
|
||||||
@@ -509,21 +521,21 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
final List<String> messages = new ArrayList<>();
|
final List<String> messages = new ArrayList<>();
|
||||||
final Status status;
|
final Status status;
|
||||||
switch (feedback.getStatus().getExecution()) {
|
switch (feedback.getStatus().getExecution()) {
|
||||||
case CANCELED:
|
case CANCELED:
|
||||||
status = handleCaseCancelCanceled(feedback, target, actionId, messages);
|
status = handleCaseCancelCanceled(feedback, target, actionId, messages);
|
||||||
break;
|
break;
|
||||||
case REJECTED:
|
case REJECTED:
|
||||||
log.info("Target rejected the cancellation request (actionId: {}, controllerId: {}).", actionId,
|
log.info("Target rejected the cancellation request (actionId: {}, controllerId: {}).", actionId,
|
||||||
target.getControllerId());
|
target.getControllerId());
|
||||||
status = Status.CANCEL_REJECTED;
|
status = Status.CANCEL_REJECTED;
|
||||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancellation request.");
|
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancellation request.");
|
||||||
break;
|
break;
|
||||||
case CLOSED:
|
case CLOSED:
|
||||||
status = handleCancelClosedCase(feedback, messages);
|
status = handleCancelClosedCase(feedback, messages);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
status = Status.RUNNING;
|
status = Status.RUNNING;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (feedback.getStatus().getDetails() != null) {
|
if (feedback.getStatus().getDetails() != null) {
|
||||||
@@ -564,6 +576,114 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
final 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 ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId,
|
||||||
|
final Long actionId) {
|
||||||
|
|
||||||
|
final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
|
||||||
|
|
||||||
|
final List<String> messages = new ArrayList<>();
|
||||||
|
|
||||||
|
if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) {
|
||||||
|
messages.addAll(feedback.getStatus().getDetails());
|
||||||
|
}
|
||||||
|
|
||||||
|
final Integer code = feedback.getStatus().getCode();
|
||||||
|
if (code != null) {
|
||||||
|
actionStatusCreate.code(code);
|
||||||
|
messages.add("Device reported status code: " + code);
|
||||||
|
}
|
||||||
|
|
||||||
|
final 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 cancellation.", 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 actionStatusCreate.status(status).messages(messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Status handleDefaultCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId,
|
||||||
|
final List<String> messages) {
|
||||||
|
final 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) {
|
||||||
|
final 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;
|
||||||
|
}
|
||||||
|
|
||||||
private Target findTarget(final String controllerId) {
|
private Target findTarget(final String controllerId) {
|
||||||
return controllerManagement.getByControllerId(controllerId)
|
return controllerManagement.getByControllerId(controllerId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
|
||||||
@@ -588,8 +708,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
* If the action has a maintenance schedule defined but is no longer valid,
|
* If the action has a maintenance schedule defined but is no longer valid,
|
||||||
* cancel the action.
|
* cancel the action.
|
||||||
*
|
*
|
||||||
* @param action
|
* @param action is the {@link Action} to check.
|
||||||
* is the {@link Action} to check.
|
|
||||||
*/
|
*/
|
||||||
private void checkAndCancelExpiredAction(final Action action) {
|
private void checkAndCancelExpiredAction(final Action action) {
|
||||||
if (action != null && action.hasMaintenanceSchedule() && action.isMaintenanceScheduleLapsed()) {
|
if (action != null && action.hasMaintenanceSchedule() && action.isMaintenanceScheduleLapsed()) {
|
||||||
@@ -601,44 +720,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<DdiConfirmationBaseAction> getConfirmationBaseAction(
|
|
||||||
@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("getConfirmationBaseAction({},{})", controllerId, resource);
|
|
||||||
|
|
||||||
final Target target = findTarget(controllerId);
|
|
||||||
final Action action = findActionForTarget(actionId, target);
|
|
||||||
|
|
||||||
checkAndCancelExpiredAction(action);
|
|
||||||
|
|
||||||
if (!action.isCancelingOrCanceled() && action.isWaitingConfirmation()) {
|
|
||||||
|
|
||||||
final DdiConfirmationBaseAction base = generateDdiConfirmationBase(target, action,
|
|
||||||
actionHistoryMessageCount);
|
|
||||||
|
|
||||||
log.debug("Found an active UpdateAction for target {}. Returning confirmation: {}", controllerId, base);
|
|
||||||
|
|
||||||
return new ResponseEntity<>(base, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResponseEntity.notFound().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private DdiDeploymentBase generateDdiDeploymentBase(final Target target, final Action action,
|
private DdiDeploymentBase generateDdiDeploymentBase(final Target target, final Action action,
|
||||||
final Integer actionHistoryMessageCount) {
|
final Integer actionHistoryMessageCount) {
|
||||||
final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null);
|
final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null);
|
||||||
@@ -672,60 +753,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
: Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs));
|
: Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<Void> postConfirmationActionFeedback(
|
|
||||||
@Valid @RequestBody final DdiConfirmationFeedback feedback, @PathVariable("tenant") final String tenant,
|
|
||||||
@PathVariable("controllerId") final String controllerId,
|
|
||||||
@PathVariable("actionId") @NotNull final Long actionId) {
|
|
||||||
log.debug("provideConfirmationActionFeedback with feedback [controllerId={}, actionId={}]: {}", controllerId,
|
|
||||||
actionId, feedback);
|
|
||||||
|
|
||||||
final Target target = findTarget(controllerId);
|
|
||||||
final Action action = findActionForTarget(actionId, target);
|
|
||||||
|
|
||||||
try {
|
|
||||||
|
|
||||||
switch (feedback.getConfirmation()) {
|
|
||||||
case CONFIRMED:
|
|
||||||
log.info("Controller confirmed the action (actionId: {}, controllerId: {}) as we got {} report.",
|
|
||||||
actionId, controllerId, feedback.getConfirmation());
|
|
||||||
confirmationManagement.confirmAction(actionId, feedback.getCode(), feedback.getDetails());
|
|
||||||
break;
|
|
||||||
case DENIED:
|
|
||||||
default:
|
|
||||||
log.debug("Controller denied the action (actionId: {}, controllerId: {}) as we got {} report.",
|
|
||||||
actionId, controllerId, feedback.getConfirmation());
|
|
||||||
confirmationManagement.denyAction(actionId, feedback.getCode(), feedback.getDetails());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (final InvalidConfirmationFeedbackException e) {
|
|
||||||
if (e.getReason() == InvalidConfirmationFeedbackException.Reason.ACTION_CLOSED) {
|
|
||||||
log.warn("Updating action {} with confirmation {} not possible since action not active anymore.",
|
|
||||||
action.getId(), feedback.getConfirmation());
|
|
||||||
return new ResponseEntity<>(HttpStatus.GONE);
|
|
||||||
} else if (e.getReason() == InvalidConfirmationFeedbackException.Reason.NOT_AWAITING_CONFIRMATION) {
|
|
||||||
log.debug("Action is not waiting for confirmation, deny request.");
|
|
||||||
return ResponseEntity.notFound().build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ResponseEntity.ok().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<DdiConfirmationBase> getConfirmationBase(final String tenant, final String controllerId) {
|
|
||||||
log.debug("getConfirmationBase is called [controllerId={}].", controllerId);
|
|
||||||
final Target target = controllerManagement.findOrRegisterTargetIfItDoesNotExist(controllerId, IpUtil
|
|
||||||
.getClientIpFromRequest(RequestResponseContextHolder.getHttpServletRequest(), securityProperties));
|
|
||||||
final Action activeAction = controllerManagement.findActiveActionWithHighestWeight(controllerId).orElse(null);
|
|
||||||
|
|
||||||
final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId);
|
|
||||||
|
|
||||||
final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase(target, activeAction,
|
|
||||||
autoConfirmationState, tenantAware);
|
|
||||||
return new ResponseEntity<>(confirmationBase, HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
private DdiAutoConfirmationState getAutoConfirmationState(final String controllerId) {
|
private DdiAutoConfirmationState getAutoConfirmationState(final String controllerId) {
|
||||||
return confirmationManagement.getStatus(controllerId).map(status -> {
|
return confirmationManagement.getStatus(controllerId).map(status -> {
|
||||||
final DdiAutoConfirmationState state = DdiAutoConfirmationState.active(status.getActivatedAt());
|
final DdiAutoConfirmationState state = DdiAutoConfirmationState.active(status.getActivatedAt());
|
||||||
@@ -739,33 +766,4 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
|||||||
return DdiAutoConfirmationState.disabled();
|
return DdiAutoConfirmationState.disabled();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<Void> activateAutoConfirmation(final String tenant, final String controllerId,
|
|
||||||
final DdiActivateAutoConfirmation body) {
|
|
||||||
final String initiator = body == null ? null : body.getInitiator();
|
|
||||||
final String remark = body == null ? FALLBACK_REMARK : body.getRemark();
|
|
||||||
log.debug("Activate auto-confirmation request for device '{}' with payload: [initiator='{}' | remark='{}'",
|
|
||||||
controllerId, initiator, remark);
|
|
||||||
confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark);
|
|
||||||
return new ResponseEntity<>(HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<Void> deactivateAutoConfirmation(final String tenant, final String controllerId) {
|
|
||||||
log.debug("Deactivate auto-confirmation request for device ‘{}‘", controllerId);
|
|
||||||
confirmationManagement.deactivateAutoConfirmation(controllerId);
|
|
||||||
return new ResponseEntity<>(HttpStatus.OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResponseEntity<Void> setAsssignedOfflineVersion(@Valid @RequestBody DdiAssignedVersion ddiAssignedVersion,
|
|
||||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId){
|
|
||||||
boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId,
|
|
||||||
ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion());
|
|
||||||
if (updated) {
|
|
||||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
|
||||||
}
|
|
||||||
return new ResponseEntity<>(HttpStatus.OK);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,10 +24,18 @@ import java.time.Instant;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonFactory;
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
|
||||||
|
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
|
||||||
|
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
|
import org.eclipse.hawkbit.ddi.json.model.DdiActionFeedback;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
|
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion;
|
import org.eclipse.hawkbit.ddi.json.model.DdiAssignedVersion;
|
||||||
|
import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiProgress;
|
import org.eclipse.hawkbit.ddi.json.model.DdiProgress;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||||
@@ -49,15 +57,6 @@ import org.springframework.test.web.servlet.ResultActions;
|
|||||||
import org.springframework.test.web.servlet.ResultMatcher;
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonFactory;
|
|
||||||
import com.fasterxml.jackson.core.JsonGenerator;
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
|
|
||||||
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
|
|
||||||
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
|
|
||||||
|
|
||||||
@ContextConfiguration(classes = { DdiApiConfiguration.class, RestConfiguration.class,
|
@ContextConfiguration(classes = { DdiApiConfiguration.class, RestConfiguration.class,
|
||||||
RepositoryApplicationConfiguration.class, TestConfiguration.class })
|
RepositoryApplicationConfiguration.class, TestConfiguration.class })
|
||||||
@Import(TestChannelBinderConfiguration.class)
|
@Import(TestChannelBinderConfiguration.class)
|
||||||
@@ -65,19 +64,17 @@ import com.fasterxml.jackson.dataformat.cbor.CBORParser;
|
|||||||
public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrationTest {
|
public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrationTest {
|
||||||
|
|
||||||
public static final int HTTP_PORT = 8080;
|
public static final int HTTP_PORT = 8080;
|
||||||
protected static final String HTTP_LOCALHOST = String.format("http://localhost:%s/",HTTP_PORT);
|
protected static final String HTTP_LOCALHOST = String.format("http://localhost:%s/", HTTP_PORT);
|
||||||
protected static final String CONTROLLER_BASE = "/{tenant}/controller/v1/{controllerId}";
|
protected static final String CONTROLLER_BASE = "/{tenant}/controller/v1/{controllerId}";
|
||||||
|
|
||||||
protected static final String SOFTWARE_MODULE_ARTIFACTS = CONTROLLER_BASE
|
protected static final String SOFTWARE_MODULE_ARTIFACTS = CONTROLLER_BASE
|
||||||
+ "/softwaremodules/{softwareModuleId}/artifacts";
|
+ "/softwaremodules/{softwareModuleId}/artifacts";
|
||||||
protected static final String DEPLOYMENT_BASE = CONTROLLER_BASE + "/deploymentBase/{actionId}";
|
protected static final String DEPLOYMENT_BASE = CONTROLLER_BASE + "/deploymentBase/{actionId}";
|
||||||
|
protected static final String DEPLOYMENT_FEEDBACK = DEPLOYMENT_BASE + "/feedback";
|
||||||
protected static final String CANCEL_ACTION = CONTROLLER_BASE + "/cancelAction/{actionId}";
|
protected static final String CANCEL_ACTION = CONTROLLER_BASE + "/cancelAction/{actionId}";
|
||||||
|
protected static final String CANCEL_FEEDBACK = CANCEL_ACTION + "/feedback";
|
||||||
protected static final String INSTALLED_BASE = CONTROLLER_BASE + "/installedBase/{actionId}";
|
protected static final String INSTALLED_BASE = CONTROLLER_BASE + "/installedBase/{actionId}";
|
||||||
protected static final String INSTALLED_BASE_ROOT = CONTROLLER_BASE + "/installedBase";
|
protected static final String INSTALLED_BASE_ROOT = CONTROLLER_BASE + "/installedBase";
|
||||||
|
|
||||||
protected static final String DEPLOYMENT_FEEDBACK = DEPLOYMENT_BASE + "/feedback";
|
|
||||||
protected static final String CANCEL_FEEDBACK = CANCEL_ACTION + "/feedback";
|
|
||||||
|
|
||||||
protected static final String CONFIRMATION_BASE = CONTROLLER_BASE + "/confirmationBase";
|
protected static final String CONFIRMATION_BASE = CONTROLLER_BASE + "/confirmationBase";
|
||||||
protected static final String ACTIVATE_AUTO_CONFIRM = CONFIRMATION_BASE + "/activateAutoConfirm";
|
protected static final String ACTIVATE_AUTO_CONFIRM = CONFIRMATION_BASE + "/activateAutoConfirm";
|
||||||
protected static final String DEACTIVATE_AUTO_CONFIRM = CONFIRMATION_BASE + "/deactivateAutoConfirm";
|
protected static final String DEACTIVATE_AUTO_CONFIRM = CONFIRMATION_BASE + "/deactivateAutoConfirm";
|
||||||
@@ -91,11 +88,9 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
/**
|
/**
|
||||||
* Convert JSON to a CBOR equivalent.
|
* Convert JSON to a CBOR equivalent.
|
||||||
*
|
*
|
||||||
* @param json
|
* @param json JSON object to convert
|
||||||
* JSON object to convert
|
|
||||||
* @return Equivalent CBOR data
|
* @return Equivalent CBOR data
|
||||||
* @throws IOException
|
* @throws IOException Invalid JSON input
|
||||||
* Invalid JSON input
|
|
||||||
*/
|
*/
|
||||||
protected static byte[] jsonToCbor(final String json) throws IOException {
|
protected static byte[] jsonToCbor(final String json) throws IOException {
|
||||||
final JsonFactory jsonFactory = new JsonFactory();
|
final JsonFactory jsonFactory = new JsonFactory();
|
||||||
@@ -113,11 +108,9 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
/**
|
/**
|
||||||
* Convert CBOR to JSON equivalent.
|
* Convert CBOR to JSON equivalent.
|
||||||
*
|
*
|
||||||
* @param input
|
* @param input CBOR data to convert
|
||||||
* CBOR data to convert
|
|
||||||
* @return Equivalent JSON string
|
* @return Equivalent JSON string
|
||||||
* @throws IOException
|
* @throws IOException Invalid CBOR input
|
||||||
* Invalid CBOR input
|
|
||||||
*/
|
*/
|
||||||
protected static String cborToJson(final byte[] input) throws IOException {
|
protected static String cborToJson(final byte[] input) throws IOException {
|
||||||
final CBORFactory cborFactory = new CBORFactory();
|
final CBORFactory cborFactory = new CBORFactory();
|
||||||
@@ -132,6 +125,10 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
return stringWriter.toString();
|
return stringWriter.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static ObjectMapper getMapper() {
|
||||||
|
return objectMapper;
|
||||||
|
}
|
||||||
|
|
||||||
protected ResultActions postDeploymentFeedback(final String controllerId, final Long actionId, final String content,
|
protected ResultActions postDeploymentFeedback(final String controllerId, final Long actionId, final String content,
|
||||||
final ResultMatcher statusMatcher) throws Exception {
|
final ResultMatcher statusMatcher) throws Exception {
|
||||||
return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(),
|
return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(),
|
||||||
@@ -139,7 +136,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected ResultActions putInstalledBase(final String controllerId, final String content,
|
protected ResultActions putInstalledBase(final String controllerId, final String content,
|
||||||
final ResultMatcher statusMatcher) throws Exception {
|
final ResultMatcher statusMatcher) throws Exception {
|
||||||
return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId)
|
return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId)
|
||||||
.content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8))
|
.content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
|
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
|
||||||
@@ -170,7 +167,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher,
|
protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher,
|
||||||
final String... values) throws Exception {
|
final String... values) throws Exception {
|
||||||
return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType)
|
return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType)
|
||||||
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher)
|
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher)
|
||||||
.andExpect(content().contentTypeCompatibleWith(mediaType));
|
.andExpect(content().contentTypeCompatibleWith(mediaType));
|
||||||
}
|
}
|
||||||
@@ -200,61 +197,6 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
getDownloadAndUploadType(actionType), getDownloadAndUploadType(actionType));
|
getDownloadAndUploadType(actionType), getDownloadAndUploadType(actionType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultActions verifyBasePayload(final String prefix, final ResultActions resultActions, final String controllerId,
|
|
||||||
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
|
||||||
final Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
|
||||||
return resultActions.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
|
||||||
.andExpect(jsonPath(prefix + ".download", equalTo(downloadType)))
|
|
||||||
.andExpect(jsonPath(prefix + ".update", equalTo(updateType)))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].name",
|
|
||||||
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].version",
|
|
||||||
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].name",
|
|
||||||
contains(ds.findFirstModuleByType(osType).get().getName())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].version",
|
|
||||||
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].size", contains(ARTIFACT_SIZE)))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].filename",
|
|
||||||
contains(artifact.getFilename())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.md5",
|
|
||||||
contains(artifact.getMd5Hash())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha1",
|
|
||||||
contains(artifact.getSha1Hash())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha256",
|
|
||||||
contains(artifact.getSha256Hash())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
|
|
||||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
|
||||||
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename()
|
|
||||||
+ "/download")))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href",
|
|
||||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
|
||||||
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename()
|
|
||||||
+ "/download.MD5SUM")))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE)))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename",
|
|
||||||
contains(artifactSignature.getFilename())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.md5",
|
|
||||||
contains(artifactSignature.getMd5Hash())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha1",
|
|
||||||
contains(artifactSignature.getSha1Hash())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha256",
|
|
||||||
contains(artifactSignature.getSha256Hash())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
|
|
||||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
|
||||||
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename()
|
|
||||||
+ "/download")))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href",
|
|
||||||
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
|
||||||
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename()
|
|
||||||
+ "/download.MD5SUM")))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version",
|
|
||||||
contains(ds.findFirstModuleByType(appType).get().getVersion())))
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist())
|
|
||||||
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].name")
|
|
||||||
.value(ds.findFirstModuleByType(appType).get().getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String installedBaseLink(final String controllerId, final String actionId) {
|
protected String installedBaseLink(final String controllerId, final String actionId) {
|
||||||
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
+ "/installedBase/" + actionId;
|
+ "/installedBase/" + actionId;
|
||||||
@@ -265,13 +207,6 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
+ "/deploymentBase/" + actionId;
|
+ "/deploymentBase/" + actionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getDownloadAndUploadType(final Action.ActionType actionType) {
|
|
||||||
if (Action.ActionType.FORCED.equals(actionType)) {
|
|
||||||
return "forced";
|
|
||||||
}
|
|
||||||
return "attempt";
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getJsonRejectedCancelActionFeedback() throws JsonProcessingException {
|
protected String getJsonRejectedCancelActionFeedback() throws JsonProcessingException {
|
||||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS,
|
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS,
|
||||||
Collections.singletonList("rejected"));
|
Collections.singletonList("rejected"));
|
||||||
@@ -367,7 +302,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String getJsonConfirmationFeedback(final DdiConfirmationFeedback.Confirmation confirmation,
|
protected String getJsonConfirmationFeedback(final DdiConfirmationFeedback.Confirmation confirmation,
|
||||||
final Integer code, final List<String> messages) throws JsonProcessingException {
|
final Integer code, final List<String> messages) throws JsonProcessingException {
|
||||||
return objectMapper.writeValueAsString(new DdiConfirmationFeedback(confirmation, code, messages));
|
return objectMapper.writeValueAsString(new DdiConfirmationFeedback(confirmation, code, messages));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,10 +310,6 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
return objectMapper.writeValueAsString(new DdiAssignedVersion(name, version));
|
return objectMapper.writeValueAsString(new DdiAssignedVersion(name, version));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static ObjectMapper getMapper(){
|
|
||||||
return objectMapper;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ResultActions getAndVerifyConfirmationBasePayload(final String controllerId, final MediaType mediaType,
|
protected ResultActions getAndVerifyConfirmationBasePayload(final String controllerId, final MediaType mediaType,
|
||||||
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
||||||
final Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
final Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
||||||
@@ -391,4 +322,66 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
|||||||
static void implicitLock(final DistributionSet set) {
|
static void implicitLock(final DistributionSet set) {
|
||||||
((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1);
|
((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String getDownloadAndUploadType(final Action.ActionType actionType) {
|
||||||
|
if (Action.ActionType.FORCED.equals(actionType)) {
|
||||||
|
return "forced";
|
||||||
|
}
|
||||||
|
return "attempt";
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultActions verifyBasePayload(final String prefix, final ResultActions resultActions, final String controllerId,
|
||||||
|
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
||||||
|
final Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
||||||
|
return resultActions.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
||||||
|
.andExpect(jsonPath(prefix + ".download", equalTo(downloadType)))
|
||||||
|
.andExpect(jsonPath(prefix + ".update", equalTo(updateType)))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].name",
|
||||||
|
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].version",
|
||||||
|
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].name",
|
||||||
|
contains(ds.findFirstModuleByType(osType).get().getName())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].version",
|
||||||
|
contains(ds.findFirstModuleByType(osType).get().getVersion())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].size", contains(ARTIFACT_SIZE)))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].filename",
|
||||||
|
contains(artifact.getFilename())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.md5",
|
||||||
|
contains(artifact.getMd5Hash())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha1",
|
||||||
|
contains(artifact.getSha1Hash())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha256",
|
||||||
|
contains(artifact.getSha256Hash())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
|
||||||
|
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
|
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename()
|
||||||
|
+ "/download")))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href",
|
||||||
|
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
|
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename()
|
||||||
|
+ "/download.MD5SUM")))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE)))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename",
|
||||||
|
contains(artifactSignature.getFilename())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.md5",
|
||||||
|
contains(artifactSignature.getMd5Hash())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha1",
|
||||||
|
contains(artifactSignature.getSha1Hash())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha256",
|
||||||
|
contains(artifactSignature.getSha256Hash())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
|
||||||
|
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
|
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename()
|
||||||
|
+ "/download")))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href",
|
||||||
|
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||||
|
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename()
|
||||||
|
+ "/download.MD5SUM")))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version",
|
||||||
|
contains(ds.findFirstModuleByType(appType).get().getVersion())))
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist())
|
||||||
|
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].name")
|
||||||
|
.value(ds.findFirstModuleByType(appType).get().getName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,9 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
|
import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
||||||
@@ -48,10 +51,6 @@ import org.springframework.http.HttpHeaders;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test artifact downloads from the controller.
|
* Test artifact downloads from the controller.
|
||||||
*/
|
*/
|
||||||
@@ -102,55 +101,55 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// test now consistent data to test allowed methods
|
// test now consistent data to test allowed methods
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||||
.header(HttpHeaders.IF_MATCH, artifact.getSha1Hash()))
|
.header(HttpHeaders.IF_MATCH, artifact.getSha1Hash()))
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
// test failed If-match
|
// test failed If-match
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||||
.header(HttpHeaders.IF_MATCH, "fsjkhgjfdhg"))
|
.header(HttpHeaders.IF_MATCH, "fsjkhgjfdhg"))
|
||||||
.andExpect(status().isPreconditionFailed());
|
.andExpect(status().isPreconditionFailed());
|
||||||
|
|
||||||
// test invalid range
|
// test invalid range
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||||
.header("Range", "bytes=1-10,hdsfjksdh"))
|
.header("Range", "bytes=1-10,hdsfjksdh"))
|
||||||
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
|
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
|
||||||
.andExpect(status().isRequestedRangeNotSatisfiable());
|
.andExpect(status().isRequestedRangeNotSatisfiable());
|
||||||
|
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())
|
||||||
.header("Range", "bytes=100-10"))
|
.header("Range", "bytes=100-10"))
|
||||||
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
|
.andExpect(header().string("Content-Range", "bytes */" + 5 * 1024))
|
||||||
.andExpect(status().isRequestedRangeNotSatisfiable());
|
.andExpect(status().isRequestedRangeNotSatisfiable());
|
||||||
|
|
||||||
// not allowed methods
|
// not allowed methods
|
||||||
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
mvc.perform(put("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
mvc.perform(delete("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
mvc.perform(post("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}.MD5SUM",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,8 +181,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// now assign and download successful
|
// now assign and download successful
|
||||||
assignDistributionSet(ds, targets);
|
assignDistributionSet(ds, targets);
|
||||||
final MvcResult result = mvc.perform(get(
|
final MvcResult result = mvc.perform(get(
|
||||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||||
@@ -191,7 +190,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andReturn();
|
.andReturn();
|
||||||
|
|
||||||
assertTrue(
|
assertTrue(
|
||||||
Arrays.equals(result.getResponse().getContentAsByteArray(), random), "The same file that was uploaded is expected when downloaded");
|
Arrays.equals(result.getResponse().getContentAsByteArray(), random),
|
||||||
|
"The same file that was uploaded is expected when downloaded");
|
||||||
|
|
||||||
// download complete
|
// download complete
|
||||||
assertThat(downLoadProgress).isEqualTo(10);
|
assertThat(downLoadProgress).isEqualTo(10);
|
||||||
@@ -217,8 +217,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// download
|
// download
|
||||||
final MvcResult result = mvc.perform(get(
|
final MvcResult result = mvc.perform(get(
|
||||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM",
|
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||||
.andExpect(status().isOk()).andExpect(header().string("Content-Disposition",
|
.andExpect(status().isOk()).andExpect(header().string("Content-Disposition",
|
||||||
"attachment;filename=" + artifact.getFilename() + ".MD5SUM"))
|
"attachment;filename=" + artifact.getFilename() + ".MD5SUM"))
|
||||||
.andReturn();
|
.andReturn();
|
||||||
@@ -258,8 +258,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final String rangeString = "" + i * range + "-" + ((i + 1) * range - 1);
|
final String rangeString = "" + i * range + "-" + ((i + 1) * range - 1);
|
||||||
|
|
||||||
final MvcResult result = mvc.perform(get(
|
final MvcResult result = mvc.perform(get(
|
||||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range",
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range",
|
||||||
"bytes=" + rangeString))
|
"bytes=" + rangeString))
|
||||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
@@ -276,8 +276,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// return last 1000 Bytes
|
// return last 1000 Bytes
|
||||||
MvcResult result = mvc.perform(
|
MvcResult result = mvc.perform(
|
||||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||||
.header("Range", "bytes=-1000"))
|
.header("Range", "bytes=-1000"))
|
||||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
@@ -293,8 +293,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// skip first 1000 Bytes and return the rest
|
// skip first 1000 Bytes and return the rest
|
||||||
result = mvc.perform(
|
result = mvc.perform(
|
||||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||||
.header("Range", "bytes=1000-"))
|
.header("Range", "bytes=1000-"))
|
||||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
@@ -310,8 +310,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// Start download from file end fails
|
// Start download from file end fails
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||||
.header("Range", "bytes=" + random.length + "-"))
|
.header("Range", "bytes=" + random.length + "-"))
|
||||||
.andExpect(status().isRequestedRangeNotSatisfiable())
|
.andExpect(status().isRequestedRangeNotSatisfiable())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||||
@@ -322,8 +322,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// multipart download - first 20 bytes in 2 parts
|
// multipart download - first 20 bytes in 2 parts
|
||||||
result = mvc.perform(
|
result = mvc.perform(
|
||||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||||
.header("Range", "bytes=0-9,10-19"))
|
.header("Range", "bytes=0-9,10-19"))
|
||||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||||
.andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART"))
|
.andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART"))
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||||
@@ -41,10 +44,6 @@ import org.springframework.hateoas.MediaTypes;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.integration.json.JsonPathUtils;
|
import org.springframework.integration.json.JsonPathUtils;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test cancel action from the controller.
|
* Test cancel action from the controller.
|
||||||
*/
|
*/
|
||||||
@@ -52,6 +51,9 @@ import io.qameta.allure.Story;
|
|||||||
@Story("Cancel Action Resource")
|
@Story("Cancel Action Resource")
|
||||||
class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ActionStatusRepository actionStatusRepository;
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests that the cancel action resource can be used with CBOR.")
|
@Description("Tests that the cancel action resource can be used with CBOR.")
|
||||||
void cancelActionCbor() throws Exception {
|
void cancelActionCbor() throws Exception {
|
||||||
@@ -65,7 +67,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final byte[] result = mvc
|
final byte[] result = mvc
|
||||||
.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId(), tenantAware.getCurrentTenant())
|
+ cancelAction.getId(), tenantAware.getCurrentTenant())
|
||||||
.accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
.accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andReturn().getResponse()
|
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andReturn().getResponse()
|
||||||
.getContentAsByteArray();
|
.getContentAsByteArray();
|
||||||
@@ -76,7 +78,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// and submit feedback as CBOR
|
// and submit feedback as CBOR
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(jsonToCbor(getJsonProceedingCancelActionFeedback()))
|
.content(jsonToCbor(getJsonProceedingCancelActionFeedback()))
|
||||||
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -97,7 +99,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// controller rejects cancellation
|
// controller rejects cancellation
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -106,8 +108,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// get update action anyway
|
// get update action anyway
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId,
|
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId,
|
||||||
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
||||||
@@ -122,9 +124,9 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// and finish it
|
// and finish it
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
||||||
+ actionId + "/feedback", tenantAware.getCurrentTenant()).content(
|
+ actionId + "/feedback", tenantAware.getCurrentTenant()).content(
|
||||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
|
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
|
||||||
Collections.singletonList("message")))
|
Collections.singletonList("message")))
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
@@ -135,7 +137,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.isEqualTo(ds);
|
.isEqualTo(ds);
|
||||||
assertThat(
|
assertThat(
|
||||||
targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getInstallationDate())
|
targetManagement.getByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).get().getInstallationDate())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.isGreaterThanOrEqualTo(current);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +152,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
final long timeBeforeFirstPoll = System.currentTimeMillis();
|
final long timeBeforeFirstPoll = System.currentTimeMillis();
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||||
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON)).andDo(MockMvcResultPrinter.print())
|
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||||
@@ -179,7 +181,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
final long timeBefore2ndPoll = System.currentTimeMillis();
|
final long timeBefore2ndPoll = System.currentTimeMillis();
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||||
@@ -190,7 +192,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.isBetween(timeBefore2ndPoll, timeAfter2ndPoll);
|
.isBetween(timeBefore2ndPoll, timeAfter2ndPoll);
|
||||||
|
|
||||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||||
@@ -200,7 +202,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// controller confirmed cancelled action, should not be active anymore
|
// controller confirmed cancelled action, should not be active anymore
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -220,41 +222,31 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// not allowed methods
|
// not allowed methods
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||||
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||||
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
|
||||||
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
// non existing target
|
// non existing target
|
||||||
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
|
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotFound());
|
.andExpect(status().isNotFound());
|
||||||
|
|
||||||
createCancelAction("34534543");
|
createCancelAction("34534543");
|
||||||
|
|
||||||
// wrong media type
|
// wrong media type
|
||||||
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
|
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
|
||||||
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotAcceptable());
|
.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 = getFirstAssignedActionId(assignDistributionSet(ds, toAssign));
|
|
||||||
|
|
||||||
return deploymentManagement.cancelAction(actionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Tests the feedback channel of the cancel operation.")
|
@Description("Tests the feedback channel of the cancel operation.")
|
||||||
void rootRsCancelActionFeedback() throws Exception {
|
void rootRsCancelActionFeedback() throws Exception {
|
||||||
@@ -272,7 +264,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -281,7 +273,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(countActionStatusAll()).isEqualTo(3);
|
assertThat(countActionStatusAll()).isEqualTo(3);
|
||||||
|
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -289,7 +281,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(countActionStatusAll()).isEqualTo(4);
|
assertThat(countActionStatusAll()).isEqualTo(4);
|
||||||
|
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -299,7 +291,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// cancellation canceled -> should remove the action from active
|
// cancellation canceled -> should remove the action from active
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -312,7 +304,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// error
|
// error
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -321,7 +313,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// update closed -> should remove the action from active
|
// update closed -> should remove the action from active
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -359,7 +351,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(3);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(3);
|
||||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||||
@@ -367,7 +359,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(countActionStatusAll()).isEqualTo(6);
|
assertThat(countActionStatusAll()).isEqualTo(6);
|
||||||
|
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(),
|
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(),
|
||||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||||
@@ -376,7 +368,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// now lets return feedback for the first cancelation
|
// now lets return feedback for the first cancelation
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -386,7 +378,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
+ cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
|
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
|
||||||
@@ -394,7 +386,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(countActionStatusAll()).isEqualTo(8);
|
assertThat(countActionStatusAll()).isEqualTo(8);
|
||||||
|
|
||||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||||
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||||
@@ -403,7 +395,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// now lets return feedback for the second cancelation
|
// now lets return feedback for the second cancelation
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -412,8 +404,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||||
.isEqualTo(ds3);
|
.isEqualTo(ds3);
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
|
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
|
||||||
tenantAware.getCurrentTenant()))
|
tenantAware.getCurrentTenant()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
assertThat(countActionStatusAll()).isEqualTo(10);
|
assertThat(countActionStatusAll()).isEqualTo(10);
|
||||||
|
|
||||||
@@ -429,7 +421,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.isEqualTo(ds3);
|
.isEqualTo(ds3);
|
||||||
|
|
||||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
+ cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
|
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
|
||||||
@@ -438,7 +430,7 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// now lets return feedback for the third cancelation
|
// now lets return feedback for the third cancelation
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
@@ -466,13 +458,13 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// only 97 action status left
|
// only 97 action status left
|
||||||
for (int i = 0; i < 98; i++) {
|
for (int i = 0; i < 98; i++) {
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback)
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback)
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback)
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(feedback)
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isForbidden());
|
.andExpect(status().isForbidden());
|
||||||
}
|
}
|
||||||
@@ -485,22 +477,22 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// not allowed methods
|
// not allowed methods
|
||||||
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
// bad content type
|
// bad content type
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||||
@@ -508,33 +500,41 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// bad body
|
// bad body
|
||||||
String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}";
|
String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}";
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
// non existing target
|
// non existing target
|
||||||
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
|
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
|
||||||
tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback())
|
tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||||
|
|
||||||
// invalid action
|
// invalid action
|
||||||
invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
|
invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||||
|
|
||||||
// finaly, get it right :)
|
// finaly, get it right :)
|
||||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
private Action createCancelAction(final String targetid) {
|
||||||
ActionStatusRepository actionStatusRepository;
|
final DistributionSet ds = testdataFactory.createDistributionSet(targetid);
|
||||||
|
final Target savedTarget = testdataFactory.createTarget(targetid);
|
||||||
|
final List<Target> toAssign = new ArrayList<>();
|
||||||
|
toAssign.add(savedTarget);
|
||||||
|
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, toAssign));
|
||||||
|
|
||||||
|
return deploymentManagement.cancelAction(actionId);
|
||||||
|
}
|
||||||
|
|
||||||
private long countActionStatusAll() {
|
private long countActionStatusAll() {
|
||||||
return actionStatusRepository.count();
|
return actionStatusRepository.count();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,10 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Step;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||||
import org.eclipse.hawkbit.exception.SpServerError;
|
import org.eclipse.hawkbit.exception.SpServerError;
|
||||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||||
@@ -40,10 +44,6 @@ import org.springframework.hateoas.MediaTypes;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.context.ActiveProfiles;
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Step;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
/**
|
/**
|
||||||
* Test config data from the controller.
|
* Test config data from the controller.
|
||||||
*/
|
*/
|
||||||
@@ -66,8 +66,8 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
||||||
|
|
||||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(jsonToCbor(JsonBuilder.configData(attributes).toString()))
|
.content(jsonToCbor(JsonBuilder.configData(attributes).toString()))
|
||||||
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andDo(MockMvcResultPrinter.print())
|
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||||
}
|
}
|
||||||
@@ -81,15 +81,15 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
final long current = System.currentTimeMillis();
|
final long current = System.currentTimeMillis();
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.configData.href", equalTo(
|
.andExpect(jsonPath("$._links.configData.href", equalTo(
|
||||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
|
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
|
||||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||||
// often too fast and
|
// often too fast and
|
||||||
// the following assert will fail
|
// the following assert will fail
|
||||||
assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new)
|
assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new)
|
||||||
.getLastTargetQuery())
|
.getLastTargetQuery())
|
||||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||||
@@ -107,7 +107,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse();
|
assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse();
|
||||||
|
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
@@ -125,14 +125,14 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
||||||
|
|
||||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||||
|
|
||||||
// update
|
// update
|
||||||
attributes.put("sdsds", "123412");
|
attributes.put("sdsds", "123412");
|
||||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||||
}
|
}
|
||||||
@@ -149,13 +149,13 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
attributes.put("dsafsdf" + i, "sdsds" + i);
|
attributes.put("dsafsdf" + i, "sdsds" + i);
|
||||||
}
|
}
|
||||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
attributes = new HashMap<>();
|
attributes = new HashMap<>();
|
||||||
attributes.put("on too many", "sdsds");
|
attributes.put("on too many", "sdsds");
|
||||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isForbidden())
|
.andExpect(status().isForbidden())
|
||||||
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
|
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
|
||||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||||
@@ -183,17 +183,17 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final Map<String, String> attributes = new HashMap<>();
|
final Map<String, String> attributes = new HashMap<>();
|
||||||
attributes.put("dsafsdf", "sdsds");
|
attributes.put("dsafsdf", "sdsds");
|
||||||
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||||
|
|
||||||
// non existing target
|
// non existing target
|
||||||
mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant())
|
mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||||
|
|
||||||
// bad body
|
// bad body
|
||||||
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
||||||
.content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON))
|
.content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,26 +206,6 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
putAndVerifyConfigDataWithValueTooLong();
|
putAndVerifyConfigDataWithValueTooLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Step
|
|
||||||
private void putAndVerifyConfigDataWithKeyTooLong() throws Exception {
|
|
||||||
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_TOO_LONG, ATTRIBUTE_VALUE_VALID);
|
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
|
||||||
.andExpect(status().isBadRequest())
|
|
||||||
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
|
||||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_TARGET_ATTRIBUTES_INVALID.getKey())));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Step
|
|
||||||
private void putAndVerifyConfigDataWithValueTooLong() throws Exception {
|
|
||||||
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_TOO_LONG);
|
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
|
||||||
.andExpect(status().isBadRequest())
|
|
||||||
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
|
||||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_TARGET_ATTRIBUTES_INVALID.getKey())));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).")
|
@Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).")
|
||||||
void putConfigDataWithDifferentUpdateModes() throws Exception {
|
void putConfigDataWithDifferentUpdateModes() throws Exception {
|
||||||
@@ -249,6 +229,26 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
putConfigDataWithInvalidUpdateMode();
|
putConfigDataWithInvalidUpdateMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void putAndVerifyConfigDataWithKeyTooLong() throws Exception {
|
||||||
|
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_TOO_LONG, ATTRIBUTE_VALUE_VALID);
|
||||||
|
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isBadRequest())
|
||||||
|
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
||||||
|
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_TARGET_ATTRIBUTES_INVALID.getKey())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void putAndVerifyConfigDataWithValueTooLong() throws Exception {
|
||||||
|
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_TOO_LONG);
|
||||||
|
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
|
.andExpect(status().isBadRequest())
|
||||||
|
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
||||||
|
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_TARGET_ATTRIBUTES_INVALID.getKey())));
|
||||||
|
}
|
||||||
|
|
||||||
@Step
|
@Step
|
||||||
private void putConfigDataWithInvalidUpdateMode() throws Exception {
|
private void putConfigDataWithInvalidUpdateMode() throws Exception {
|
||||||
// create some attriutes
|
// create some attriutes
|
||||||
@@ -258,8 +258,8 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// use an invalid update mode
|
// use an invalid update mode
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString())
|
.content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString())
|
||||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isBadRequest());
|
.andExpect(status().isBadRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,8 +274,8 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
removeAttributes.put("k3", "bar");
|
removeAttributes.put("k3", "bar");
|
||||||
|
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(removeAttributes, "remove").toString())
|
.content(JsonBuilder.configData(removeAttributes, "remove").toString())
|
||||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
// verify attribute removal
|
// verify attribute removal
|
||||||
@@ -298,8 +298,8 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
mergeAttributes.put("k1", "v1_modified_again");
|
mergeAttributes.put("k1", "v1_modified_again");
|
||||||
mergeAttributes.put("k4", "v4");
|
mergeAttributes.put("k4", "v4");
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(mergeAttributes, "merge").toString())
|
.content(JsonBuilder.configData(mergeAttributes, "merge").toString())
|
||||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
// verify attribute merge
|
// verify attribute merge
|
||||||
@@ -325,8 +325,8 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
replacementAttributes.put("k2", "v2");
|
replacementAttributes.put("k2", "v2");
|
||||||
replacementAttributes.put("k3", "v3");
|
replacementAttributes.put("k3", "v3");
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(replacementAttributes, "replace").toString())
|
.content(JsonBuilder.configData(replacementAttributes, "replace").toString())
|
||||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|
||||||
// verify attribute replacement
|
// verify attribute replacement
|
||||||
@@ -349,7 +349,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// set the initial attributes
|
// set the initial attributes
|
||||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
// verify the initial parameters
|
// verify the initial parameters
|
||||||
|
|||||||
@@ -9,6 +9,21 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ddi.rest.resource;
|
package org.eclipse.hawkbit.ddi.rest.resource;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.eclipse.hawkbit.repository.jpa.management.JpaConfirmationManagement.CONFIRMATION_CODE_MSG_PREFIX;
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.hasItem;
|
||||||
|
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.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
import io.qameta.allure.Description;
|
||||||
import io.qameta.allure.Feature;
|
import io.qameta.allure.Feature;
|
||||||
import io.qameta.allure.Step;
|
import io.qameta.allure.Step;
|
||||||
@@ -49,21 +64,6 @@ import org.springframework.hateoas.MediaTypes;
|
|||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.test.web.servlet.ResultActions;
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
import static org.eclipse.hawkbit.repository.jpa.management.JpaConfirmationManagement.CONFIRMATION_CODE_MSG_PREFIX;
|
|
||||||
import static org.hamcrest.CoreMatchers.equalTo;
|
|
||||||
import static org.hamcrest.Matchers.containsString;
|
|
||||||
import static org.hamcrest.Matchers.hasItem;
|
|
||||||
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.jsonPath;
|
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test confirmation base from the controller.
|
* Test confirmation base from the controller.
|
||||||
*/
|
*/
|
||||||
@@ -91,7 +91,7 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||||
Action.ActionType.FORCED).getAssignedEntity().stream().map(Action::getTarget)
|
Action.ActionType.FORCED).getAssignedEntity().stream().map(Action::getTarget)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
implicitLock(ds);
|
implicitLock(ds);
|
||||||
|
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||||
@@ -116,10 +116,10 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
DEFAULT_CONTROLLER_ID)
|
DEFAULT_CONTROLLER_ID)
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href",
|
.andExpect(jsonPath("$._links.confirmationBase.href",
|
||||||
containsString(expectedConfirmationBaseLink)))
|
containsString(expectedConfirmationBaseLink)))
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
||||||
|
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.isGreaterThanOrEqualTo(current);
|
||||||
@@ -179,12 +179,12 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.get(0);
|
.get(0);
|
||||||
|
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
|
||||||
|
|
||||||
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
|
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotFound());
|
.andExpect(status().isNotFound());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.get(0);
|
.get(0);
|
||||||
|
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href").exists())
|
.andExpect(jsonPath("$._links.confirmationBase.href").exists())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
||||||
@@ -212,7 +212,7 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
|
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotFound());
|
.andExpect(status().isNotFound());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,14 +238,14 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// verify confirmation endpoint is still accessible
|
// verify confirmation endpoint is still accessible
|
||||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 20,
|
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 20,
|
||||||
"Action denied message.").andExpect(status().isOk());
|
"Action denied message.").andExpect(status().isOk());
|
||||||
|
|
||||||
// confirmation base should still be exposed
|
// confirmation base should still be exposed
|
||||||
verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId());
|
verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId());
|
||||||
|
|
||||||
// verify confirmation endpoint is still accessible
|
// verify confirmation endpoint is still accessible
|
||||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10,
|
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10,
|
||||||
"Action confirmed message.").andExpect(status().isOk());
|
"Action confirmed message.").andExpect(status().isOk());
|
||||||
|
|
||||||
// assert deployment link is exposed to the target
|
// assert deployment link is exposed to the target
|
||||||
verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
|
verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
|
||||||
@@ -282,38 +282,6 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
|
verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Step
|
|
||||||
private void verifyActionInDeploymentBaseState(final String controllerId, final long actionId) throws Exception {
|
|
||||||
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
|
|
||||||
tenantAware.getCurrentTenant(), controllerId, actionId);
|
|
||||||
|
|
||||||
mvc.perform(
|
|
||||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)))
|
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
|
|
||||||
|
|
||||||
// assert that deployment endpoint is working
|
|
||||||
mvc.perform(get(expectedDeploymentBaseLink).accept(MediaType.APPLICATION_JSON))
|
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Step
|
|
||||||
private void verifyActionInConfirmationBaseState(final String controllerId, final long actionId) throws Exception {
|
|
||||||
mvc.perform(
|
|
||||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href").exists())
|
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
|
||||||
|
|
||||||
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, actionId)
|
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, actionId)
|
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
|
||||||
.andExpect(status().isNotFound());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Confirmation base provides right values if auto-confirm not active.")
|
@Description("Confirmation base provides right values if auto-confirm not active.")
|
||||||
void getConfirmationBaseProvidesAutoConfirmStatusNotActive() throws Exception {
|
void getConfirmationBaseProvidesAutoConfirmStatusNotActive() throws Exception {
|
||||||
@@ -331,7 +299,7 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
tenantAware.getCurrentTenant(), controllerId);
|
tenantAware.getCurrentTenant(), controllerId);
|
||||||
|
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE)))
|
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE)))
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(confirmationBaseActionLink)))
|
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(confirmationBaseActionLink)))
|
||||||
@@ -353,7 +321,7 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
controllerId);
|
controllerId);
|
||||||
|
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE)))
|
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE)))
|
||||||
.andExpect(initiator == null ? jsonPath("autoConfirm.initiator").doesNotExist()
|
.andExpect(initiator == null ? jsonPath("autoConfirm.initiator").doesNotExist()
|
||||||
@@ -364,11 +332,6 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andExpect(jsonPath("$._links.activateAutoConfirm").doesNotExist());
|
.andExpect(jsonPath("$._links.activateAutoConfirm").doesNotExist());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Stream<Arguments> possibleActiveStates() {
|
|
||||||
return Stream.of(Arguments.of("someInitiator", "someRemark"), Arguments.of(null, "someRemark"),
|
|
||||||
Arguments.of("someInitiator", null), Arguments.of(null, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@MethodSource("possibleActiveStates")
|
@MethodSource("possibleActiveStates")
|
||||||
@Description("Verify auto-confirm activation is handled correctly.")
|
@Description("Verify auto-confirm activation is handled correctly.")
|
||||||
@@ -378,7 +341,7 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final DdiActivateAutoConfirmation body = new DdiActivateAutoConfirmation(initiator, remark);
|
final DdiActivateAutoConfirmation body = new DdiActivateAutoConfirmation(initiator, remark);
|
||||||
|
|
||||||
mvc.perform(post(ACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId)
|
mvc.perform(post(ACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId)
|
||||||
.content(getMapper().writeValueAsString(body)).contentType(MediaType.APPLICATION_JSON_UTF8))
|
.content(getMapper().writeValueAsString(body)).contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
assertThat(confirmationManagement.getStatus(controllerId)).hasValueSatisfying(status -> {
|
assertThat(confirmationManagement.getStatus(controllerId)).hasValueSatisfying(status -> {
|
||||||
@@ -433,29 +396,16 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
tenantAware.getCurrentTenant(), controllerId, savedAction.getId());
|
tenantAware.getCurrentTenant(), controllerId, savedAction.getId());
|
||||||
|
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||||
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)));
|
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)));
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
|
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotFound());
|
.andExpect(status().isNotFound());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultActions sendConfirmationFeedback(final Target target, final Action action,
|
|
||||||
final DdiConfirmationFeedback.Confirmation confirmation, Integer code, String message) throws Exception {
|
|
||||||
|
|
||||||
if (message == null) {
|
|
||||||
message = RandomStringUtils.randomAlphanumeric(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String feedback = getJsonConfirmationFeedback(confirmation, code, Collections.singletonList(message));
|
|
||||||
return mvc.perform(
|
|
||||||
post(CONFIRMATION_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId())
|
|
||||||
.content(feedback).contentType(MediaType.APPLICATION_JSON));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
|
@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),
|
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||||
@@ -485,18 +435,68 @@ public class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// confirmationBase not available in RUNNING state anymore
|
// confirmationBase not available in RUNNING state anymore
|
||||||
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
||||||
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||||
|
|
||||||
// assert confirmed message against deploymentBase endpoint
|
// assert confirmed message against deploymentBase endpoint
|
||||||
// this call will update the action due to retrieved action status update
|
// this call will update the action due to retrieved action status update
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
||||||
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString(CONFIRMED_MESSAGE))))
|
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString(CONFIRMED_MESSAGE))))
|
||||||
.andExpect(jsonPath("$.actionHistory.messages",
|
.andExpect(jsonPath("$.actionHistory.messages",
|
||||||
hasItem(containsString(String.format(CONFIRMATION_CODE_MSG_PREFIX, CONFIRMED_CODE)))));
|
hasItem(containsString(String.format(CONFIRMATION_CODE_MSG_PREFIX, CONFIRMED_CODE)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Stream<Arguments> possibleActiveStates() {
|
||||||
|
return Stream.of(Arguments.of("someInitiator", "someRemark"), Arguments.of(null, "someRemark"),
|
||||||
|
Arguments.of("someInitiator", null), Arguments.of(null, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void verifyActionInDeploymentBaseState(final String controllerId, final long actionId) throws Exception {
|
||||||
|
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
|
||||||
|
tenantAware.getCurrentTenant(), controllerId, actionId);
|
||||||
|
|
||||||
|
mvc.perform(
|
||||||
|
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)))
|
||||||
|
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
|
||||||
|
|
||||||
|
// assert that deployment endpoint is working
|
||||||
|
mvc.perform(get(expectedDeploymentBaseLink).accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void verifyActionInConfirmationBaseState(final String controllerId, final long actionId) throws Exception {
|
||||||
|
mvc.perform(
|
||||||
|
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._links.confirmationBase.href").exists())
|
||||||
|
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
||||||
|
|
||||||
|
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, actionId)
|
||||||
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
|
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, actionId)
|
||||||
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||||
|
.andExpect(status().isNotFound());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultActions sendConfirmationFeedback(final Target target, final Action action,
|
||||||
|
final DdiConfirmationFeedback.Confirmation confirmation, Integer code, String message) throws Exception {
|
||||||
|
|
||||||
|
if (message == null) {
|
||||||
|
message = RandomStringUtils.randomAlphanumeric(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String feedback = getJsonConfirmationFeedback(confirmation, code, Collections.singletonList(message));
|
||||||
|
return mvc.perform(
|
||||||
|
post(CONFIRMATION_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId())
|
||||||
|
.content(feedback).contentType(MediaType.APPLICATION_JSON));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ import java.util.Optional;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.jayway.jsonpath.JsonPath;
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.assertj.core.api.Condition;
|
import org.assertj.core.api.Condition;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||||
@@ -66,12 +70,6 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
import com.jayway.jsonpath.JsonPath;
|
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test deployment base from the controller.
|
* Test deployment base from the controller.
|
||||||
*/
|
*/
|
||||||
@@ -79,6 +77,10 @@ import io.qameta.allure.Story;
|
|||||||
@Story("Deployment Action Resource")
|
@Story("Deployment Action Resource")
|
||||||
public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ActionRepository actionRepository;
|
||||||
|
@Autowired
|
||||||
|
ActionStatusRepository actionStatusRepository;
|
||||||
private static final String DEFAULT_CONTROLLER_ID = "4712";
|
private static final String DEFAULT_CONTROLLER_ID = "4712";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -130,10 +132,10 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
|
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
|
||||||
.andExpect(jsonPath("$", hasSize(3)))
|
.andExpect(jsonPath("$", hasSize(3)))
|
||||||
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
|
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
|
||||||
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
|
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
|
||||||
.andExpect(jsonPath("$.[?(@.filename=='filename2')]", hasSize(1)));
|
.andExpect(jsonPath("$.[?(@.filename=='filename2')]", hasSize(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -171,8 +173,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final long current = System.currentTimeMillis();
|
final long current = System.currentTimeMillis();
|
||||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.isGreaterThanOrEqualTo(current);
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
@@ -214,7 +216,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
DEFAULT_CONTROLLER_ID).andReturn();
|
DEFAULT_CONTROLLER_ID).andReturn();
|
||||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||||
.toString()).isEqualTo(urlBeforeSwitch)
|
.toString()).isEqualTo(urlBeforeSwitch)
|
||||||
.startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, actionId.toString()));
|
.startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, actionId.toString()));
|
||||||
|
|
||||||
// After the time is over we should see a new etag
|
// After the time is over we should see a new etag
|
||||||
TimeUnit.MILLISECONDS.sleep(2_000);
|
TimeUnit.MILLISECONDS.sleep(2_000);
|
||||||
@@ -269,8 +271,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final long current = System.currentTimeMillis();
|
final long current = System.currentTimeMillis();
|
||||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.isGreaterThanOrEqualTo(current);
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
@@ -327,8 +329,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final long current = System.currentTimeMillis();
|
final long current = System.currentTimeMillis();
|
||||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.isGreaterThanOrEqualTo(current);
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
@@ -373,7 +375,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||||
ActionType.DOWNLOAD_ONLY).getAssignedEntity().stream().map(Action::getTarget)
|
ActionType.DOWNLOAD_ONLY).getAssignedEntity().stream().map(Action::getTarget)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
implicitLock(ds);
|
implicitLock(ds);
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||||
|
|
||||||
@@ -394,8 +396,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final long current = System.currentTimeMillis();
|
final long current = System.currentTimeMillis();
|
||||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
.isGreaterThanOrEqualTo(current);
|
.isGreaterThanOrEqualTo(current);
|
||||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||||
@@ -417,17 +419,6 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getAndVerifyDeploymentBasePayload(final String controllerId, final MediaType mediaType,
|
|
||||||
final DistributionSet ds, final String visibleMetadataOsKey, final String visibleMetadataOsValue,
|
|
||||||
final Artifact artifact, final Artifact artifactSignature, final Long actionId, final String downloadType,
|
|
||||||
final String updateType, final Long osModuleId) throws Exception {
|
|
||||||
getAndVerifyDeploymentBasePayload(controllerId, mediaType, ds, artifact, artifactSignature, actionId,
|
|
||||||
osModuleId, downloadType, updateType).andExpect(
|
|
||||||
jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].key").value(visibleMetadataOsKey))
|
|
||||||
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].value")
|
|
||||||
.value(visibleMetadataOsValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test various invalid access attempts to the deployment resource und the expected behaviour of the server.")
|
@Description("Test various invalid access attempts to the deployment resource und the expected behaviour of the server.")
|
||||||
public void badDeploymentAction() throws Exception {
|
public void badDeploymentAction() throws Exception {
|
||||||
@@ -449,7 +440,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// no deployment
|
// no deployment
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||||
|
|
||||||
// wrong media type
|
// wrong media type
|
||||||
@@ -460,8 +451,8 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID,
|
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID,
|
||||||
actionId)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
actionId)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
mvc.perform(MockMvcRequestBuilders
|
mvc.perform(MockMvcRequestBuilders
|
||||||
.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, actionId)
|
.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, actionId)
|
||||||
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotAcceptable());
|
.andExpect(status().isNotAcceptable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -552,8 +543,6 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertStatusMessagesCount(6);
|
assertStatusMessagesCount(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
|
||||||
ActionRepository actionRepository;
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Verifies that an update action is correctly set to error if the controller provides error feedback.")
|
@Description("Verifies that an update action is correctly set to error if the controller provides error feedback.")
|
||||||
public void rootRsSingleDeploymentActionWithErrorFeedback() throws Exception {
|
public void rootRsSingleDeploymentActionWithErrorFeedback() throws Exception {
|
||||||
@@ -669,7 +658,7 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// not allowed methods
|
// not allowed methods
|
||||||
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(),
|
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(),
|
||||||
DEFAULT_CONTROLLER_ID, "2")).andDo(MockMvcResultPrinter.print())
|
DEFAULT_CONTROLLER_ID, "2")).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isMethodNotAllowed());
|
.andExpect(status().isMethodNotAllowed());
|
||||||
|
|
||||||
mvc.perform(put(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2"))
|
mvc.perform(put(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2"))
|
||||||
@@ -750,6 +739,21 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andExpect(jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
|
.andExpect(jsonPath("$.exceptionClass", equalTo(MessageNotReadableException.class.getCanonicalName())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long countActionStatusAll() {
|
||||||
|
return actionStatusRepository.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAndVerifyDeploymentBasePayload(final String controllerId, final MediaType mediaType,
|
||||||
|
final DistributionSet ds, final String visibleMetadataOsKey, final String visibleMetadataOsValue,
|
||||||
|
final Artifact artifact, final Artifact artifactSignature, final Long actionId, final String downloadType,
|
||||||
|
final String updateType, final Long osModuleId) throws Exception {
|
||||||
|
getAndVerifyDeploymentBasePayload(controllerId, mediaType, ds, artifact, artifactSignature, actionId,
|
||||||
|
osModuleId, downloadType, updateType).andExpect(
|
||||||
|
jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].key").value(visibleMetadataOsKey))
|
||||||
|
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].value")
|
||||||
|
.value(visibleMetadataOsValue));
|
||||||
|
}
|
||||||
|
|
||||||
private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) {
|
private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) {
|
||||||
final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
|
final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
|
||||||
assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
assertThat(target.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
|
||||||
@@ -762,19 +766,6 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
new ActionStatusCondition(Status.RUNNING));
|
new ActionStatusCondition(Status.RUNNING));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ActionStatusCondition extends Condition<ActionStatus> {
|
|
||||||
private final Action.Status status;
|
|
||||||
|
|
||||||
public ActionStatusCondition(final Action.Status status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(final ActionStatus value) {
|
|
||||||
return value.getStatus() == status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Target createTargetAndAssertNoActiveActions() {
|
private Target createTargetAndAssertNoActiveActions() {
|
||||||
final Target savedTarget = testdataFactory.createTarget(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID);
|
final Target savedTarget = testdataFactory.createTarget(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID);
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||||
@@ -829,12 +820,21 @@ public class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.hasSize(activeActions);
|
.hasSize(activeActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
|
||||||
ActionStatusRepository actionStatusRepository;
|
|
||||||
private Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
|
private Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
|
||||||
return JpaManagementHelper.findAllWithCountBySpec(actionStatusRepository, pageable, null);
|
return JpaManagementHelper.findAllWithCountBySpec(actionStatusRepository, pageable, null);
|
||||||
}
|
}
|
||||||
public long countActionStatusAll() {
|
|
||||||
return actionStatusRepository.count();
|
private static class ActionStatusCondition extends Condition<ActionStatus> {
|
||||||
|
|
||||||
|
private final Action.Status status;
|
||||||
|
|
||||||
|
public ActionStatusCondition(final Action.Status status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(final ActionStatus value) {
|
||||||
|
return value.getStatus() == status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.apache.commons.lang3.RandomUtils;
|
import org.apache.commons.lang3.RandomUtils;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||||
@@ -62,10 +65,6 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.test.web.servlet.ResultActions;
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test installed base from the controller.
|
* Test installed base from the controller.
|
||||||
*/
|
*/
|
||||||
@@ -73,6 +72,8 @@ import io.qameta.allure.Story;
|
|||||||
@Story("Installed Base Resource")
|
@Story("Installed Base Resource")
|
||||||
public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ActionStatusRepository actionStatusRepository;
|
||||||
private static final int ARTIFACT_SIZE = 5 * 1024;
|
private static final int ARTIFACT_SIZE = 5 * 1024;
|
||||||
private static final String CONTROLLER_ID = "4715";
|
private static final String CONTROLLER_ID = "4715";
|
||||||
|
|
||||||
@@ -105,17 +106,17 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final Target target = createTargetAndAssertNoActiveActions();
|
final Target target = createTargetAndAssertNoActiveActions();
|
||||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||||
|
|
||||||
|
|
||||||
// update assigned version
|
// update assigned version
|
||||||
putInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status()
|
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status()
|
||||||
.isCreated());
|
.isCreated());
|
||||||
|
|
||||||
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId())
|
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId())
|
||||||
.isEqualTo(ds.getId());
|
.isEqualTo(ds.getId());
|
||||||
|
|
||||||
// update assigned version while version already assigned
|
// update assigned version while version already assigned
|
||||||
putInstalledBase(target.getControllerId(),getJsonInstalledBase(ds.getName(),ds.getVersion()),status().isOk());
|
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Ensure that installedVersion is version self assigned")
|
@Description("Ensure that installedVersion is version self assigned")
|
||||||
public void installedVersionNotExist() throws Exception {
|
public void installedVersionNotExist() throws Exception {
|
||||||
@@ -123,9 +124,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
final String dsName = "unknown";
|
final String dsName = "unknown";
|
||||||
final String dsVersion = "1.0.0";
|
final String dsVersion = "1.0.0";
|
||||||
|
|
||||||
|
|
||||||
// get installed base
|
// get installed base
|
||||||
putInstalledBase(target.getControllerId(),getJsonInstalledBase(dsName,dsVersion),status().isNotFound());
|
putInstalledBase(target.getControllerId(), getJsonInstalledBase(dsName, dsVersion), status().isNotFound());
|
||||||
|
|
||||||
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue();
|
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).isEmpty()).isTrue();
|
||||||
}
|
}
|
||||||
@@ -401,14 +401,10 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
||||||
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
|
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
|
||||||
.andExpect(jsonPath("$", hasSize(3)))
|
.andExpect(jsonPath("$", hasSize(3)))
|
||||||
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
|
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
|
||||||
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
|
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
|
||||||
.andExpect(jsonPath("$.[?(@.filename=='filename2')]", hasSize(1)));
|
.andExpect(jsonPath("$.[?(@.filename=='filename2')]", hasSize(1)));
|
||||||
}
|
|
||||||
|
|
||||||
private static Stream<Action.ActionType> actionTypeForDeployment() {
|
|
||||||
return Stream.of(Action.ActionType.SOFT, Action.ActionType.FORCED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -484,8 +480,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").exists())
|
.andExpect(jsonPath("$._links.deploymentBase.href").exists())
|
||||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
||||||
|
|
||||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(),
|
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(),
|
||||||
status().isOk());
|
status().isOk());
|
||||||
@@ -495,8 +491,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// Test
|
// Test
|
||||||
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@@ -511,8 +507,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").exists())
|
.andExpect(jsonPath("$._links.deploymentBase.href").exists())
|
||||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
||||||
|
|
||||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE),
|
getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE),
|
||||||
@@ -525,8 +521,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// Test
|
// Test
|
||||||
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||||
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -556,14 +552,14 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
// Test
|
// Test
|
||||||
// for zero input no action history is returned
|
// for zero input no action history is returned
|
||||||
mvc.perform(get(INSTALLED_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(INSTALLED_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
||||||
|
|
||||||
// depending on given query parameter value, only the latest messages are
|
// depending on given query parameter value, only the latest messages are
|
||||||
// returned
|
// returned
|
||||||
mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed"))))
|
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed"))))
|
||||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
|
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
|
||||||
@@ -572,7 +568,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
// for negative input the entire action history is returned
|
// for negative input the entire action history is returned
|
||||||
mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed"))))
|
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed"))))
|
||||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
|
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
|
||||||
@@ -611,12 +607,14 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
|||||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId))
|
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId)
|
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId)
|
||||||
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
||||||
.andExpect(status().isNotAcceptable());
|
.andExpect(status().isNotAcceptable());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Autowired
|
private static Stream<Action.ActionType> actionTypeForDeployment() {
|
||||||
ActionStatusRepository actionStatusRepository;
|
return Stream.of(Action.ActionType.SOFT, Action.ActionType.FORCED);
|
||||||
|
}
|
||||||
|
|
||||||
private Target createTargetAndAssertNoActiveActions() {
|
private Target createTargetAndAssertNoActiveActions() {
|
||||||
final Target savedTarget = testdataFactory.createTarget(CONTROLLER_ID);
|
final Target savedTarget = testdataFactory.createTarget(CONTROLLER_ID);
|
||||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ import java.util.Collections;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Step;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.apache.commons.lang3.RandomStringUtils;
|
import org.apache.commons.lang3.RandomStringUtils;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||||
@@ -72,11 +76,6 @@ import org.springframework.http.MediaType;
|
|||||||
import org.springframework.test.web.servlet.MvcResult;
|
import org.springframework.test.web.servlet.MvcResult;
|
||||||
import org.springframework.test.web.servlet.ResultActions;
|
import org.springframework.test.web.servlet.ResultActions;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Step;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test the root controller resources.
|
* Test the root controller resources.
|
||||||
*/
|
*/
|
||||||
@@ -270,7 +269,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThat(etagWithFirstUpdate).isNotNull();
|
assertThat(etagWithFirstUpdate).isNotNull();
|
||||||
|
|
||||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match",
|
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match",
|
||||||
etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
||||||
|
|
||||||
// now lets finish the update
|
// now lets finish the update
|
||||||
@@ -300,8 +299,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.getContent().get(0);
|
.getContent().get(0);
|
||||||
|
|
||||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
|
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
|
||||||
.header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON)
|
.header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON)
|
||||||
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||||
@@ -430,7 +429,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertThatAttributesUpdateIsRequested(savedTarget.getControllerId());
|
assertThatAttributesUpdateIsRequested(savedTarget.getControllerId());
|
||||||
|
|
||||||
mvc.perform(put(CONTROLLER_BASE + "/configData", tenantAware.getCurrentTenant(), savedTarget.getControllerId())
|
mvc.perform(put(CONTROLLER_BASE + "/configData", tenantAware.getCurrentTenant(), savedTarget.getControllerId())
|
||||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
assertThatAttributesUpdateIsNotRequested(savedTarget.getControllerId());
|
assertThatAttributesUpdateIsNotRequested(savedTarget.getControllerId());
|
||||||
|
|
||||||
@@ -439,59 +438,6 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
assertAttributesUpdateRequestedAfterSuccessfulDeployment(savedTarget, ds);
|
assertAttributesUpdateRequestedAfterSuccessfulDeployment(savedTarget, ds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Step
|
|
||||||
private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds)
|
|
||||||
throws Exception {
|
|
||||||
target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId()));
|
|
||||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
|
||||||
.getContent().get(0);
|
|
||||||
sendDeploymentActionFeedback(target, action, "closed", "failure").andExpect(status().isOk());
|
|
||||||
assertThatAttributesUpdateIsNotRequested(target.getControllerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Step
|
|
||||||
private void assertAttributesUpdateRequestedAfterSuccessfulDeployment(Target target, final DistributionSet ds)
|
|
||||||
throws Exception {
|
|
||||||
target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId()));
|
|
||||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
|
||||||
.getContent().get(0);
|
|
||||||
sendDeploymentActionFeedback(target, action, "closed", null).andExpect(status().isOk());
|
|
||||||
assertThatAttributesUpdateIsRequested(target.getControllerId());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertThatAttributesUpdateIsRequested(final String targetControllerId) throws Exception {
|
|
||||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId)
|
|
||||||
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
|
||||||
.andExpect(jsonPath("$._links.configData.href").isNotEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void assertThatAttributesUpdateIsNotRequested(final String targetControllerId) throws Exception {
|
|
||||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId)
|
|
||||||
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
|
||||||
.andExpect(jsonPath("$._links.configData").doesNotExist());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution,
|
|
||||||
String finished, String message) throws Exception {
|
|
||||||
if (finished == null) {
|
|
||||||
finished = "none";
|
|
||||||
}
|
|
||||||
if (message == null) {
|
|
||||||
message = RandomStringUtils.randomAlphanumeric(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.valueOf(execution.toUpperCase()),
|
|
||||||
DdiResult.FinalResult.valueOf(finished.toUpperCase()), Collections.singletonList(message));
|
|
||||||
return mvc.perform(
|
|
||||||
post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId())
|
|
||||||
.content(feedback).contentType(MediaType.APPLICATION_JSON));
|
|
||||||
}
|
|
||||||
|
|
||||||
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution,
|
|
||||||
final String finished) throws Exception {
|
|
||||||
return sendDeploymentActionFeedback(target, action, execution, finished, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
|
@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),
|
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||||
@@ -520,7 +466,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages",
|
.andExpect(jsonPath("$.actionHistory.messages",
|
||||||
hasItem(containsString(TARGET_COMPLETED_INSTALLATION_MSG))))
|
hasItem(containsString(TARGET_COMPLETED_INSTALLATION_MSG))))
|
||||||
@@ -558,12 +504,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
|
||||||
}
|
}
|
||||||
@@ -596,7 +542,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", tenantAware.getCurrentTenant(), 911, savedAction.getId())
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.actionHistory.messages",
|
.andExpect(jsonPath("$.actionHistory.messages",
|
||||||
hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG))))
|
hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG))))
|
||||||
@@ -668,7 +614,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.getContent().get(0);
|
.getContent().get(0);
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
|
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||||
.andExpect(jsonPath("$.deployment.update", equalTo("skip")))
|
.andExpect(jsonPath("$.deployment.update", equalTo("skip")))
|
||||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable")));
|
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable")));
|
||||||
@@ -688,7 +634,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.getContent().get(0);
|
.getContent().get(0);
|
||||||
|
|
||||||
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
|
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
|
||||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||||
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
|
||||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available")));
|
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available")));
|
||||||
@@ -719,12 +665,65 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
|||||||
.andExpect(status().isBadRequest());
|
.andExpect(status().isBadRequest());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds)
|
||||||
|
throws Exception {
|
||||||
|
target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId()));
|
||||||
|
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||||
|
.getContent().get(0);
|
||||||
|
sendDeploymentActionFeedback(target, action, "closed", "failure").andExpect(status().isOk());
|
||||||
|
assertThatAttributesUpdateIsNotRequested(target.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Step
|
||||||
|
private void assertAttributesUpdateRequestedAfterSuccessfulDeployment(Target target, final DistributionSet ds)
|
||||||
|
throws Exception {
|
||||||
|
target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId()));
|
||||||
|
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||||
|
.getContent().get(0);
|
||||||
|
sendDeploymentActionFeedback(target, action, "closed", null).andExpect(status().isOk());
|
||||||
|
assertThatAttributesUpdateIsRequested(target.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatAttributesUpdateIsRequested(final String targetControllerId) throws Exception {
|
||||||
|
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId)
|
||||||
|
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._links.configData.href").isNotEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertThatAttributesUpdateIsNotRequested(final String targetControllerId) throws Exception {
|
||||||
|
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId)
|
||||||
|
.accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$._links.configData").doesNotExist());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution,
|
||||||
|
String finished, String message) throws Exception {
|
||||||
|
if (finished == null) {
|
||||||
|
finished = "none";
|
||||||
|
}
|
||||||
|
if (message == null) {
|
||||||
|
message = RandomStringUtils.randomAlphanumeric(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.valueOf(execution.toUpperCase()),
|
||||||
|
DdiResult.FinalResult.valueOf(finished.toUpperCase()), Collections.singletonList(message));
|
||||||
|
return mvc.perform(
|
||||||
|
post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), target.getControllerId(), action.getId())
|
||||||
|
.content(feedback).contentType(MediaType.APPLICATION_JSON));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution,
|
||||||
|
final String finished) throws Exception {
|
||||||
|
return sendDeploymentActionFeedback(target, action, execution, finished, null);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId)
|
private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
|
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
|
||||||
tenantAware.getCurrentTenant(), controllerId, expectedActionId);
|
tenantAware.getCurrentTenant(), controllerId, expectedActionId);
|
||||||
mvc.perform(
|
mvc.perform(
|
||||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||||
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)));
|
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)));
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.qameta.allure.Description;
|
||||||
|
import io.qameta.allure.Feature;
|
||||||
|
import io.qameta.allure.Story;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
@@ -30,13 +33,8 @@ import org.springframework.test.web.servlet.MvcResult;
|
|||||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
||||||
import org.springframework.web.context.WebApplicationContext;
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
|
||||||
import io.qameta.allure.Description;
|
|
||||||
import io.qameta.allure.Feature;
|
|
||||||
import io.qameta.allure.Story;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test potential DOS attack scenarios and check if the filter prevents them.
|
* Test potential DOS attack scenarios and check if the filter prevents them.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
@ActiveProfiles({ "test" })
|
@ActiveProfiles({ "test" })
|
||||||
@Feature("Component Tests - REST Security")
|
@Feature("Component Tests - REST Security")
|
||||||
@@ -100,7 +98,8 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
|
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
|
||||||
@SuppressWarnings("squid:S2925") // No idea how to get rid of the Thread.sleep here
|
@SuppressWarnings("squid:S2925")
|
||||||
|
// No idea how to get rid of the Thread.sleep here
|
||||||
void acceptableGetLoad() throws Exception {
|
void acceptableGetLoad() throws Exception {
|
||||||
|
|
||||||
for (int x = 0; x < 3; x++) {
|
for (int x = 0; x < 3; x++) {
|
||||||
@@ -123,7 +122,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
|||||||
int requests = 0;
|
int requests = 0;
|
||||||
do {
|
do {
|
||||||
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||||
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback)
|
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback)
|
||||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||||
.andReturn();
|
.andReturn();
|
||||||
requests++;
|
requests++;
|
||||||
@@ -139,7 +138,8 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
|
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
|
||||||
@SuppressWarnings("squid:S2925") // No idea how to get rid of the Thread.sleep here
|
@SuppressWarnings("squid:S2925")
|
||||||
|
// No idea how to get rid of the Thread.sleep here
|
||||||
void acceptablePutPostLoad() throws Exception {
|
void acceptablePutPostLoad() throws Exception {
|
||||||
final Long actionId = prepareDeploymentBase();
|
final Long actionId = prepareDeploymentBase();
|
||||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||||
@@ -150,7 +150,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
|||||||
|
|
||||||
for (int i = 0; i < 9; i++) {
|
for (int i = 0; i < 9; i++) {
|
||||||
mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||||
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1")
|
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1")
|
||||||
.content(feedback).contentType(MediaType.APPLICATION_JSON)
|
.content(feedback).contentType(MediaType.APPLICATION_JSON)
|
||||||
.accept(MediaType.APPLICATION_JSON))
|
.accept(MediaType.APPLICATION_JSON))
|
||||||
.andExpect(status().isOk());
|
.andExpect(status().isOk());
|
||||||
|
|||||||
Reference in New Issue
Block a user