Code refactoring of hawkbit-ddi-resource (#2053)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -13,6 +13,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.artifact.repository.urlhandler.ApiType;
|
||||
import org.eclipse.hawkbit.artifact.repository.urlhandler.ArtifactUrlHandler;
|
||||
import org.eclipse.hawkbit.artifact.repository.urlhandler.URLPlaceholder;
|
||||
@@ -44,14 +46,11 @@ import org.springframework.util.CollectionUtils;
|
||||
/**
|
||||
* Utility class for the DDI API.
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public final class DataConversionHelper {
|
||||
|
||||
// utility class, private constructor.
|
||||
private DataConversionHelper() {
|
||||
|
||||
}
|
||||
|
||||
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 String controllerId = target.getControllerId();
|
||||
final DdiConfirmationBase confirmationBase = new DdiConfirmationBase(autoConfirmationState);
|
||||
@@ -77,7 +76,8 @@ public final class DataConversionHelper {
|
||||
return confirmationBase;
|
||||
}
|
||||
|
||||
public static DdiControllerBase fromTarget(final Target target, final Action installedAction,
|
||||
public static DdiControllerBase fromTarget(
|
||||
final Target target, final Action installedAction,
|
||||
final Action activeAction, final String defaultControllerPollTime, final TenantAware tenantAware) {
|
||||
final DdiControllerBase result = new DdiControllerBase(
|
||||
new DdiConfig(new DdiPolling(defaultControllerPollTime)));
|
||||
@@ -97,14 +97,13 @@ public final class DataConversionHelper {
|
||||
activeAction.getId()))
|
||||
.withRel(DdiRestConstants.CANCEL_ACTION).expand());
|
||||
} else {
|
||||
// we need to add the hashcode here of the actionWithStatus
|
||||
// because the action might
|
||||
// have changed from 'soft' to 'forced' type and we need to
|
||||
// change the payload of the
|
||||
// we need to add the hashcode here of the actionWithStatus because the action might
|
||||
// have changed from 'soft' to 'forced' type, and we need to change the payload of the
|
||||
// response because of eTags.
|
||||
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
|
||||
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||
.getControllerDeploymentBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
.getControllerDeploymentBaseAction(
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
activeAction.getId(), calculateEtag(activeAction), null))
|
||||
.withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand());
|
||||
}
|
||||
@@ -121,7 +120,8 @@ public final class DataConversionHelper {
|
||||
|
||||
if (target.isRequestControllerAttributes()) {
|
||||
result.add(WebMvcLinkBuilder
|
||||
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||
.linkTo(WebMvcLinkBuilder
|
||||
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
|
||||
.putConfigData(null, tenantAware.getCurrentTenant(), target.getControllerId()))
|
||||
.withRel(DdiRestConstants.CONFIG_DATA_ACTION).expand());
|
||||
}
|
||||
@@ -129,10 +129,10 @@ public final class DataConversionHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
static List<DdiChunk> createChunks(final Target target, final Action uAction,
|
||||
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()));
|
||||
@@ -156,7 +156,8 @@ public final class DataConversionHelper {
|
||||
}
|
||||
|
||||
private static List<DdiMetadata> mapMetadata(final List<SoftwareModuleMetadata> metadata) {
|
||||
return CollectionUtils.isEmpty(metadata) ? null
|
||||
return CollectionUtils.isEmpty(metadata)
|
||||
? null
|
||||
: metadata.stream().map(md -> new DdiMetadata(md.getKey(), md.getValue())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@@ -167,11 +168,11 @@ public final class DataConversionHelper {
|
||||
if ("runtime".equals(key)) {
|
||||
return "jvm";
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
private static DdiArtifact createArtifact(final Target target, final ArtifactUrlHandler artifactUrlHandler,
|
||||
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()));
|
||||
@@ -187,13 +188,11 @@ public final class DataConversionHelper {
|
||||
.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
|
||||
* hashcode and the {@link Action#isHitAutoForceTime(long)} to reflect a
|
||||
* force switch.
|
||||
* Calculates an etag for the given {@link Action} based on the entities hashcode and the {@link Action#isHitAutoForceTime(long)}
|
||||
* to reflect a force switch.
|
||||
*
|
||||
* @param action to calculate the etag for
|
||||
* @return the etag
|
||||
@@ -207,5 +206,4 @@ public final class DataConversionHelper {
|
||||
result = prime * result + offsetPrime;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,5 @@ import org.springframework.stereotype.Controller;
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan
|
||||
@Import({ RestConfiguration.class, OpenApiConfiguration.class })
|
||||
public class DdiApiConfiguration {
|
||||
|
||||
}
|
||||
@Import({ RestConfiguration.class, OpenApiConfiguration.class, DdiOpenApiConfiguration.class })
|
||||
public class DdiApiConfiguration {}
|
||||
|
||||
@@ -91,9 +91,9 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* The {@link DdiRootController} of the hawkBit server DDI API that is queried
|
||||
* by the hawkBit controller in order to pull {@link Action}s that have to be
|
||||
* fulfilled and report status updates concerning the {@link Action} processing.
|
||||
* The {@link DdiRootController} of the hawkBit server DDI API that is queried by the hawkBit
|
||||
* controller in order to pull {@link Action}s that have to be fulfilled and report status updates concerning
|
||||
* the {@link Action} processing.
|
||||
*
|
||||
* Transactional (read-write) as all queries at least update the last poll time.
|
||||
*/
|
||||
@@ -139,7 +139,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
private EntityFactory entityFactory;
|
||||
|
||||
@Override
|
||||
public ResponseEntity<List<DdiArtifact>> getSoftwareModulesArtifacts(@PathVariable("tenant") final String tenant,
|
||||
public ResponseEntity<List<DdiArtifact>> getSoftwareModulesArtifacts(
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId) {
|
||||
log.debug("getSoftwareModulesArtifacts({})", controllerId);
|
||||
@@ -156,7 +157,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("tenant") final String tenant,
|
||||
public ResponseEntity<DdiControllerBase> getControllerBase(
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId) {
|
||||
log.debug("getControllerBase({})", controllerId);
|
||||
|
||||
@@ -170,9 +172,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
// activeAction
|
||||
return new ResponseEntity<>(DataConversionHelper.fromTarget(target, installedAction, activeAction,
|
||||
activeAction == null ? controllerManagement.getPollingTime()
|
||||
: controllerManagement.getPollingTimeForAction(activeAction.getId()),
|
||||
tenantAware), HttpStatus.OK);
|
||||
activeAction == null
|
||||
? controllerManagement.getPollingTime()
|
||||
: controllerManagement.getPollingTimeForAction(activeAction.getId()), tenantAware),
|
||||
HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -200,11 +203,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
|
||||
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
|
||||
} else {
|
||||
final ActionStatus action = checkAndLogDownload(RequestResponseContextHolder.getHttpServletRequest(),
|
||||
target, module.getId());
|
||||
|
||||
final ActionStatus action = checkAndLogDownload(RequestResponseContextHolder.getHttpServletRequest(), target, module.getId());
|
||||
final Long statusId = action.getId();
|
||||
|
||||
result = FileStreamingUtil.writeFileResponse(file, artifact.getFilename(), artifact.getCreatedAt(),
|
||||
RequestResponseContextHolder.getHttpServletResponse(),
|
||||
RequestResponseContextHolder.getHttpServletRequest(),
|
||||
@@ -218,11 +218,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
// Exception squid:S3655 - Optional access is checked in checkModule
|
||||
// subroutine
|
||||
// Exception squid:S3655 - Optional access is checked in checkModule subroutine
|
||||
@SuppressWarnings("squid:S3655")
|
||||
public ResponseEntity<Void> downloadArtifactMd5(@PathVariable("tenant") final String tenant,
|
||||
@Override
|
||||
public ResponseEntity<Void> downloadArtifactMd5(
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("softwareModuleId") final Long softwareModuleId,
|
||||
@PathVariable("fileName") final String fileName) {
|
||||
@@ -249,12 +249,12 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
return ResponseEntity.ok().build();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<DdiDeploymentBase> getControllerDeploymentBaseAction(
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
||||
@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) {
|
||||
@@ -266,13 +266,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
checkAndCancelExpiredAction(action);
|
||||
|
||||
if (!action.isCancelingOrCanceled() && !action.isWaitingConfirmation()) {
|
||||
|
||||
final DdiDeploymentBase base = generateDdiDeploymentBase(target, action, actionHistoryMessageCount);
|
||||
|
||||
log.debug("Found an active UpdateAction for target {}. returning deployment: {}", controllerId, base);
|
||||
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved update action and should start now the download.");
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX +
|
||||
"Target retrieved update action and should start now the download.");
|
||||
|
||||
return new ResponseEntity<>(base, HttpStatus.OK);
|
||||
}
|
||||
@@ -281,8 +279,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> postDeploymentBaseActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
|
||||
public ResponseEntity<Void> postDeploymentBaseActionFeedback(
|
||||
@Valid @RequestBody final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId,
|
||||
@PathVariable("actionId") @NotNull final Long actionId) {
|
||||
log.debug("postDeploymentBaseActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback);
|
||||
|
||||
@@ -294,8 +294,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
if (!action.isActive()) {
|
||||
log.warn("Updating action {} with feedback {} not possible since action not active anymore.",
|
||||
action.getId(), feedback.getStatus());
|
||||
log.warn("Updating action {} with feedback {} not possible since action not active anymore.", action.getId(), feedback.getStatus());
|
||||
return new ResponseEntity<>(HttpStatus.GONE);
|
||||
}
|
||||
|
||||
@@ -305,9 +304,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) {
|
||||
|
||||
public ResponseEntity<Void> putConfigData(
|
||||
@Valid @RequestBody final DdiConfigData configData,
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId) {
|
||||
controllerManagement.updateControllerAttributes(controllerId, configData.getData(), getUpdateMode(configData));
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
@@ -322,13 +322,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
final Action action = findActionForTarget(actionId, target);
|
||||
|
||||
if (action.isCancelingOrCanceled()) {
|
||||
final DdiCancel cancel = new DdiCancel(String.valueOf(action.getId()),
|
||||
new DdiCancelActionToStop(String.valueOf(action.getId())));
|
||||
|
||||
final DdiCancel cancel = new DdiCancel(String.valueOf(action.getId()), new DdiCancelActionToStop(String.valueOf(action.getId())));
|
||||
log.debug("Found an active CancelAction for target {}. returning cancel: {}", controllerId, cancel);
|
||||
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target retrieved cancel action and should start now the cancellation.");
|
||||
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX +
|
||||
"Target retrieved cancel action and should start now the cancellation.");
|
||||
|
||||
return new ResponseEntity<>(cancel, HttpStatus.OK);
|
||||
}
|
||||
@@ -337,7 +335,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> postCancelActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback,
|
||||
public ResponseEntity<Void> postCancelActionFeedback(
|
||||
@Valid @RequestBody final DdiActionFeedback feedback,
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") @NotEmpty final String controllerId,
|
||||
@PathVariable("actionId") @NotNull final Long actionId) {
|
||||
@@ -352,7 +351,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<DdiDeploymentBase> getControllerInstalledAction(@PathVariable("tenant") final String tenant,
|
||||
public ResponseEntity<DdiDeploymentBase> getControllerInstalledAction(
|
||||
@PathVariable("tenant") final String tenant,
|
||||
@PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId,
|
||||
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
|
||||
log.debug("getControllerInstalledAction({})", controllerId);
|
||||
@@ -380,14 +380,15 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId);
|
||||
|
||||
final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase(target, activeAction,
|
||||
autoConfirmationState, tenantAware);
|
||||
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("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) {
|
||||
@@ -399,10 +400,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
checkAndCancelExpiredAction(action);
|
||||
|
||||
if (!action.isCancelingOrCanceled() && action.isWaitingConfirmation()) {
|
||||
|
||||
final DdiConfirmationBaseAction base = generateDdiConfirmationBase(target, action,
|
||||
actionHistoryMessageCount);
|
||||
|
||||
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);
|
||||
@@ -413,17 +411,15 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> postConfirmationActionFeedback(
|
||||
@Valid @RequestBody final DdiConfirmationFeedback feedback, @PathVariable("tenant") final String tenant,
|
||||
@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);
|
||||
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.",
|
||||
@@ -452,8 +448,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> activateAutoConfirmation(final String tenant, final String controllerId,
|
||||
final DdiActivateAutoConfirmation body) {
|
||||
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='{}'",
|
||||
@@ -470,8 +466,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> setAsssignedOfflineVersion(@Valid @RequestBody DdiAssignedVersion ddiAssignedVersion,
|
||||
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) {
|
||||
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) {
|
||||
@@ -514,29 +512,31 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
}
|
||||
|
||||
private static ActionStatusCreate generateActionCancelStatus(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionId, final EntityFactory entityFactory) {
|
||||
|
||||
private static ActionStatusCreate generateActionCancelStatus(
|
||||
final DdiActionFeedback feedback, final Target target, final Long actionId, final EntityFactory entityFactory) {
|
||||
final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
final Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
case CANCELED: {
|
||||
status = handleCaseCancelCanceled(feedback, target, actionId, messages);
|
||||
break;
|
||||
case REJECTED:
|
||||
}
|
||||
case REJECTED: {
|
||||
log.info("Target rejected the cancellation request (actionId: {}, controllerId: {}).", actionId,
|
||||
target.getControllerId());
|
||||
status = Status.CANCEL_REJECTED;
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancellation request.");
|
||||
break;
|
||||
case CLOSED:
|
||||
}
|
||||
case CLOSED: {
|
||||
status = handleCancelClosedCase(feedback, messages);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
status = Status.RUNNING;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (feedback.getStatus().getDetails() != null) {
|
||||
@@ -550,7 +550,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
return actionStatusCreate.status(status).messages(messages);
|
||||
|
||||
}
|
||||
|
||||
private static Status handleCancelClosedCase(final DdiActionFeedback feedback, final List<String> messages) {
|
||||
@@ -565,15 +564,15 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
return status;
|
||||
}
|
||||
|
||||
private static Status handleCaseCancelCanceled(final DdiActionFeedback feedback, final Target target,
|
||||
final Long actionId, final List<String> messages) {
|
||||
private static Status handleCaseCancelCanceled(
|
||||
final DdiActionFeedback feedback, final Target target, final Long actionId, final List<String> messages) {
|
||||
final Status status;
|
||||
log.error(
|
||||
"Target reported cancel for a cancel which is not supported by the server (actionId: {}, controllerId: {}) as we got {} report.",
|
||||
actionId, target.getControllerId(), feedback.getStatus().getExecution());
|
||||
status = Status.WARNING;
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX
|
||||
+ "Target reported cancel for a cancel which is not supported by the server.");
|
||||
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX +
|
||||
"Target reported cancel for a cancel which is not supported by the server.");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -596,8 +595,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
final String message;
|
||||
if (range != null) {
|
||||
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads range " + range + " of: "
|
||||
+ request.getRequestURI();
|
||||
message = RepositoryConstants.SERVER_MESSAGE_PREFIX +
|
||||
"Target downloads range " + range + " of: " + request.getRequestURI();
|
||||
} else {
|
||||
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI();
|
||||
}
|
||||
@@ -606,11 +605,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
entityFactory.actionStatus().create(action.getId()).status(Status.DOWNLOAD).message(message));
|
||||
}
|
||||
|
||||
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId,
|
||||
final Long actionId) {
|
||||
|
||||
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())) {
|
||||
@@ -625,43 +621,49 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
|
||||
final Status status;
|
||||
switch (feedback.getStatus().getExecution()) {
|
||||
case CANCELED:
|
||||
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:
|
||||
}
|
||||
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:
|
||||
}
|
||||
case CLOSED: {
|
||||
status = handleClosedCase(feedback, controllerId, actionId, messages);
|
||||
break;
|
||||
case DOWNLOAD:
|
||||
}
|
||||
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:
|
||||
}
|
||||
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:
|
||||
}
|
||||
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) {
|
||||
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());
|
||||
@@ -670,8 +672,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
return status;
|
||||
}
|
||||
|
||||
private Status handleClosedCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId,
|
||||
final List<String> messages) {
|
||||
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());
|
||||
@@ -706,8 +708,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* If the action has a maintenance schedule defined but is no longer valid,
|
||||
* cancel the action.
|
||||
* If the action has a maintenance schedule defined but is no longer valid, cancel the action.
|
||||
*
|
||||
* @param action is the {@link Action} to check.
|
||||
*/
|
||||
@@ -721,22 +722,21 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
}
|
||||
}
|
||||
|
||||
private DdiDeploymentBase generateDdiDeploymentBase(final Target target, final Action action,
|
||||
final Integer actionHistoryMessageCount) {
|
||||
private DdiDeploymentBase generateDdiDeploymentBase(final Target target, final Action action, final Integer actionHistoryMessageCount) {
|
||||
final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null);
|
||||
final DdiDeployment ddiDeployment = generateDdiDeployment(target, action);
|
||||
return new DdiDeploymentBase(Long.toString(action.getId()), ddiDeployment, actionHistory);
|
||||
}
|
||||
|
||||
private DdiConfirmationBaseAction generateDdiConfirmationBase(final Target target, final Action action,
|
||||
final Integer actionHistoryMessageCount) {
|
||||
private DdiConfirmationBaseAction generateDdiConfirmationBase(final Target target, final Action action, final Integer actionHistoryMessageCount) {
|
||||
final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null);
|
||||
final DdiDeployment ddiDeployment = generateDdiDeployment(target, action);
|
||||
return new DdiConfirmationBaseAction(Long.toString(action.getId()), ddiDeployment, actionHistory);
|
||||
}
|
||||
|
||||
private DdiDeployment generateDdiDeployment(final Target target, final Action action) {
|
||||
final List<DdiChunk> chunks = DataConversionHelper.createChunks(target, action, artifactUrlHandler,
|
||||
final List<DdiChunk> chunks = DataConversionHelper.createChunks(
|
||||
target, action, artifactUrlHandler,
|
||||
systemManagement, new ServletServerHttpRequest(RequestResponseContextHolder.getHttpServletRequest()),
|
||||
controllerManagement);
|
||||
final HandlingType downloadType = calculateDownloadType(action);
|
||||
@@ -745,12 +745,13 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
return new DdiDeployment(downloadType, updateType, chunks, maintenanceWindow);
|
||||
}
|
||||
|
||||
private Optional<DdiActionHistory> generateDdiActionHistory(final Action action,
|
||||
final Integer actionHistoryMessageCount) {
|
||||
private Optional<DdiActionHistory> generateDdiActionHistory(final Action action, final Integer actionHistoryMessageCount) {
|
||||
final List<String> actionHistoryMsgs = controllerManagement.getActionHistoryMessages(action.getId(),
|
||||
actionHistoryMessageCount == null ? Integer.parseInt(DdiRestConstants.NO_ACTION_HISTORY)
|
||||
actionHistoryMessageCount == null
|
||||
? Integer.parseInt(DdiRestConstants.NO_ACTION_HISTORY)
|
||||
: actionHistoryMessageCount);
|
||||
return actionHistoryMsgs.isEmpty() ? Optional.empty()
|
||||
return actionHistoryMsgs.isEmpty()
|
||||
? Optional.empty()
|
||||
: Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs));
|
||||
}
|
||||
|
||||
@@ -779,11 +780,9 @@ public class DdiRootController implements DdiRootControllerRestApi {
|
||||
* @param response the response
|
||||
* @param md5Hash of the artifact
|
||||
* @param filename as provided by the client
|
||||
* @return the response
|
||||
* @throws IOException cannot write output stream
|
||||
*/
|
||||
private static void writeMD5FileResponse(
|
||||
final HttpServletResponse response, final String md5Hash, final String filename) throws IOException {
|
||||
private static void writeMD5FileResponse(final HttpServletResponse response, final String md5Hash, final String filename) throws IOException {
|
||||
if (md5Hash == null) {
|
||||
throw new IllegalArgumentException("MD5 hash must not be null");
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.StringWriter;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
@@ -57,8 +58,8 @@ import org.springframework.test.web.servlet.ResultActions;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
@ContextConfiguration(classes = { DdiApiConfiguration.class, RestConfiguration.class,
|
||||
RepositoryApplicationConfiguration.class, TestConfiguration.class })
|
||||
@ContextConfiguration(
|
||||
classes = { DdiApiConfiguration.class, RestConfiguration.class, RepositoryApplicationConfiguration.class, TestConfiguration.class })
|
||||
@Import(TestChannelBinderConfiguration.class)
|
||||
@TestPropertySource(locations = "classpath:/ddi-test.properties")
|
||||
public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrationTest {
|
||||
@@ -67,8 +68,7 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
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 SOFTWARE_MODULE_ARTIFACTS = CONTROLLER_BASE
|
||||
+ "/softwaremodules/{softwareModuleId}/artifacts";
|
||||
protected static final String SOFTWARE_MODULE_ARTIFACTS = CONTROLLER_BASE + "/softwaremodules/{softwareModuleId}/artifacts";
|
||||
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}";
|
||||
@@ -83,7 +83,8 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
protected static final String CONFIRMATION_FEEDBACK = CONFIRMATION_BASE_ACTION + "/feedback";
|
||||
|
||||
protected static final int ARTIFACT_SIZE = 5 * 1024;
|
||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
private static final Random RND = new Random();
|
||||
|
||||
/**
|
||||
* Convert JSON to a CBOR equivalent.
|
||||
@@ -126,62 +127,69 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
}
|
||||
|
||||
protected static ObjectMapper getMapper() {
|
||||
return objectMapper;
|
||||
return OBJECT_MAPPER;
|
||||
}
|
||||
|
||||
protected ResultActions postDeploymentFeedback(final String controllerId, final Long actionId, final String content,
|
||||
final ResultMatcher statusMatcher) throws Exception {
|
||||
return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(),
|
||||
statusMatcher);
|
||||
return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(), statusMatcher);
|
||||
}
|
||||
|
||||
protected ResultActions putInstalledBase(final String controllerId, final String content,
|
||||
final ResultMatcher statusMatcher) throws Exception {
|
||||
protected ResultActions putInstalledBase(final String controllerId, final String content, final ResultMatcher statusMatcher)
|
||||
throws Exception {
|
||||
return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId)
|
||||
.content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(statusMatcher);
|
||||
}
|
||||
|
||||
protected ResultActions postDeploymentFeedback(final MediaType mediaType, final String controllerId,
|
||||
protected ResultActions postDeploymentFeedback(
|
||||
final MediaType mediaType, final String controllerId,
|
||||
final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception {
|
||||
return mvc
|
||||
.perform(post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId)
|
||||
.content(content).contentType(mediaType).accept(mediaType))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(statusMatcher);
|
||||
}
|
||||
|
||||
protected ResultActions postCancelFeedback(final String controllerId, final Long actionId, final String content,
|
||||
protected ResultActions postCancelFeedback(
|
||||
final String controllerId, final Long actionId, final String content,
|
||||
final ResultMatcher statusMatcher) throws Exception {
|
||||
return postCancelFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(),
|
||||
statusMatcher);
|
||||
return postCancelFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(), statusMatcher);
|
||||
}
|
||||
|
||||
protected ResultActions postCancelFeedback(final MediaType mediaType, final String controllerId,
|
||||
protected ResultActions postCancelFeedback(
|
||||
final MediaType mediaType, final String controllerId,
|
||||
final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception {
|
||||
return mvc
|
||||
.perform(post(CANCEL_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId).content(content)
|
||||
.contentType(mediaType).accept(mediaType))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher);
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(statusMatcher);
|
||||
}
|
||||
|
||||
protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher,
|
||||
final String... values) throws Exception {
|
||||
protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher, final String... values)
|
||||
throws Exception {
|
||||
return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType)
|
||||
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher)
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(statusMatcher)
|
||||
.andExpect(content().contentTypeCompatibleWith(mediaType));
|
||||
}
|
||||
|
||||
protected ResultActions getAndVerifyDeploymentBasePayload(final String controllerId, final MediaType mediaType,
|
||||
protected ResultActions getAndVerifyDeploymentBasePayload(
|
||||
final String controllerId, final MediaType mediaType,
|
||||
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
||||
final Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
||||
final ResultActions resultActions = performGet(DEPLOYMENT_BASE, mediaType, status().isOk(),
|
||||
tenantAware.getCurrentTenant(), controllerId, actionId.toString());
|
||||
return verifyBasePayload("$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId,
|
||||
downloadType, updateType);
|
||||
return verifyBasePayload(
|
||||
"$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId, downloadType, updateType);
|
||||
}
|
||||
|
||||
protected ResultActions getAndVerifyDeploymentBasePayload(final String controllerId, final MediaType mediaType,
|
||||
protected ResultActions getAndVerifyDeploymentBasePayload(
|
||||
final String controllerId, final MediaType mediaType,
|
||||
final DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
|
||||
final Long osModuleId, final Action.ActionType actionType) throws Exception {
|
||||
return getAndVerifyDeploymentBasePayload(controllerId, mediaType, ds, artifact, artifactSignature, actionId,
|
||||
@@ -198,127 +206,139 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
}
|
||||
|
||||
protected String installedBaseLink(final String controllerId, final String actionId) {
|
||||
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
+ "/installedBase/" + actionId;
|
||||
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" +
|
||||
controllerId + "/installedBase/" + actionId;
|
||||
}
|
||||
|
||||
protected String deploymentBaseLink(final String controllerId, final String actionId) {
|
||||
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId
|
||||
+ "/deploymentBase/" + actionId;
|
||||
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" +
|
||||
controllerId + "/deploymentBase/" + actionId;
|
||||
}
|
||||
|
||||
protected String getJsonRejectedCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("rejected"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("rejected"));
|
||||
}
|
||||
|
||||
protected String getJsonRejectedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("rejected"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.NONE, Collections.singletonList("rejected"));
|
||||
}
|
||||
|
||||
protected String getJsonDownloadDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.DOWNLOAD, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("download"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.DOWNLOAD, DdiResult.FinalResult.NONE, Collections.singletonList("download"));
|
||||
}
|
||||
|
||||
protected String getJsonDownloadedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.DOWNLOADED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("download"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.DOWNLOADED, DdiResult.FinalResult.NONE, Collections.singletonList("download"));
|
||||
}
|
||||
|
||||
protected String getJsonCanceledCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("canceled"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("canceled"));
|
||||
}
|
||||
|
||||
protected String getJsonCanceledDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("canceled"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.NONE, Collections.singletonList("canceled"));
|
||||
}
|
||||
|
||||
protected String getJsonScheduledCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("scheduled"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("scheduled"));
|
||||
}
|
||||
|
||||
protected String getJsonScheduledDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("scheduled"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE, Collections.singletonList("scheduled"));
|
||||
}
|
||||
|
||||
protected String getJsonResumedCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("resumed"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("resumed"));
|
||||
}
|
||||
|
||||
protected String getJsonResumedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("resumed"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.NONE, Collections.singletonList("resumed"));
|
||||
}
|
||||
|
||||
protected String getJsonProceedingCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("proceeding"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.SUCCESS, Collections.singletonList("proceeding"));
|
||||
}
|
||||
|
||||
protected String getJsonProceedingDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("proceeding"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE, Collections.singletonList("proceeding"));
|
||||
}
|
||||
|
||||
protected String getJsonClosedCancelActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("closed"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("closed"));
|
||||
}
|
||||
|
||||
protected String getJsonClosedDeploymentActionFeedback() throws JsonProcessingException {
|
||||
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("closed"));
|
||||
return getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, Collections.singletonList("closed"));
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus,
|
||||
final DdiResult.FinalResult finalResult) throws JsonProcessingException {
|
||||
return getJsonActionFeedback(executionStatus, finalResult,
|
||||
Collections.singletonList(RandomStringUtils.randomAlphanumeric(1000)));
|
||||
protected String getJsonActionFeedback(
|
||||
final DdiStatus.ExecutionStatus executionStatus, final DdiResult.FinalResult finalResult) throws JsonProcessingException {
|
||||
return getJsonActionFeedback(
|
||||
executionStatus, finalResult, Collections.singletonList(RandomStringUtils.randomAlphanumeric(1000)));
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus, final DdiResult ddiResult,
|
||||
protected String getJsonActionFeedback(
|
||||
final DdiStatus.ExecutionStatus executionStatus, final DdiResult ddiResult,
|
||||
final List<String> messages) throws JsonProcessingException {
|
||||
final DdiStatus ddiStatus = new DdiStatus(executionStatus, ddiResult, null, messages);
|
||||
return objectMapper.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
|
||||
return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus,
|
||||
protected String getJsonActionFeedback(
|
||||
final DdiStatus.ExecutionStatus executionStatus,
|
||||
final DdiResult.FinalResult finalResult, final List<String> messages) throws JsonProcessingException {
|
||||
return getJsonActionFeedback(executionStatus, finalResult, null, messages);
|
||||
}
|
||||
|
||||
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus,
|
||||
protected String getJsonActionFeedback(
|
||||
final DdiStatus.ExecutionStatus executionStatus,
|
||||
final DdiResult.FinalResult finalResult, final Integer code, final List<String> messages) throws JsonProcessingException {
|
||||
final DdiStatus ddiStatus = new DdiStatus(executionStatus, new DdiResult(finalResult, new DdiProgress(2, 5)), code,
|
||||
messages);
|
||||
return objectMapper.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
|
||||
final DdiStatus ddiStatus = new DdiStatus(executionStatus, new DdiResult(finalResult, new DdiProgress(2, 5)), code, messages);
|
||||
return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
|
||||
}
|
||||
|
||||
protected String getJsonConfirmationFeedback(final DdiConfirmationFeedback.Confirmation confirmation,
|
||||
protected String getJsonConfirmationFeedback(
|
||||
final DdiConfirmationFeedback.Confirmation confirmation,
|
||||
final Integer code, final List<String> messages) throws JsonProcessingException {
|
||||
return objectMapper.writeValueAsString(new DdiConfirmationFeedback(confirmation, code, messages));
|
||||
return OBJECT_MAPPER.writeValueAsString(new DdiConfirmationFeedback(confirmation, code, messages));
|
||||
}
|
||||
|
||||
protected String getJsonInstalledBase(String name, String version) throws JsonProcessingException {
|
||||
return objectMapper.writeValueAsString(new DdiAssignedVersion(name, version));
|
||||
return OBJECT_MAPPER.writeValueAsString(new DdiAssignedVersion(name, version));
|
||||
}
|
||||
|
||||
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 Long osModuleId, final String downloadType, final String updateType) throws Exception {
|
||||
final ResultActions resultActions = performGet(CONFIRMATION_BASE_ACTION, mediaType, status().isOk(),
|
||||
final ResultActions resultActions = performGet(
|
||||
CONFIRMATION_BASE_ACTION, mediaType, status().isOk(),
|
||||
tenantAware.getCurrentTenant(), controllerId, actionId.toString());
|
||||
return verifyBasePayload("$.confirmation", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId,
|
||||
return verifyBasePayload(
|
||||
"$.confirmation", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId,
|
||||
downloadType, updateType);
|
||||
}
|
||||
|
||||
static byte[] nextBytes(final int size) {
|
||||
final byte[] bytes = new byte[size];
|
||||
RND.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static void implicitLock(final DistributionSet set) {
|
||||
((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1);
|
||||
}
|
||||
@@ -330,7 +350,8 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
return "attempt";
|
||||
}
|
||||
|
||||
private ResultActions verifyBasePayload(final String prefix, final ResultActions resultActions, final String controllerId,
|
||||
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))))
|
||||
@@ -354,13 +375,11 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
.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")))
|
||||
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")))
|
||||
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())))
|
||||
@@ -371,13 +390,11 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
|
||||
.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")))
|
||||
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")))
|
||||
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())
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
package org.eclipse.hawkbit.ddi.rest.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
@@ -24,6 +24,7 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -32,7 +33,6 @@ 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.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
|
||||
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
@@ -74,30 +74,34 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
public void invalidRequestsOnArtifactResource() throws Exception {
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final List<Target> targets = Arrays.asList(target);
|
||||
final List<Target> targets = Collections.singletonList(target);
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
// create artifact
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random),
|
||||
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
|
||||
final byte[] random = nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ArtifactUpload(
|
||||
new ByteArrayInputStream(random), ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
|
||||
|
||||
assignDistributionSet(ds, targets);
|
||||
|
||||
// no artifact available
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/123455",
|
||||
target.getControllerId(), getOsModule(ds))).andExpect(status().isNotFound());
|
||||
target.getControllerId(), getOsModule(ds)))
|
||||
.andExpect(status().isNotFound());
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/123455.MD5SUM",
|
||||
target.getControllerId(), getOsModule(ds))).andExpect(status().isNotFound());
|
||||
target.getControllerId(), getOsModule(ds)))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// SM does not exist
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/1234567890/artifacts/{filename}",
|
||||
target.getControllerId(), artifact.getFilename())).andExpect(status().isNotFound());
|
||||
target.getControllerId(), artifact.getFilename()))
|
||||
.andExpect(status().isNotFound());
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/1234567890/artifacts/{filename}.MD5SUM",
|
||||
target.getControllerId(), artifact.getFilename())).andExpect(status().isNotFound());
|
||||
target.getControllerId(), artifact.getFilename()))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// test now consistent data to test allowed methods
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
|
||||
@@ -163,34 +167,35 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final List<Target> targets = Arrays.asList(target);
|
||||
final List<Target> targets = Collections.singletonList(target);
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
// create artifact
|
||||
final int artifactSize = (int) quotaManagement.getMaxArtifactSize();
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final byte[] random = nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random),
|
||||
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
|
||||
|
||||
// download fails as artifact is not yet assigned
|
||||
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
target.getControllerId(), getOsModule(ds), artifact.getFilename())).andExpect(status().isNotFound());
|
||||
target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// now assign and download successful
|
||||
assignDistributionSet(ds, targets);
|
||||
final MvcResult result = mvc.perform(get(
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename()))
|
||||
.andReturn();
|
||||
|
||||
assertTrue(
|
||||
Arrays.equals(result.getResponse().getContentAsByteArray(), random),
|
||||
assertArrayEquals(result.getResponse().getContentAsByteArray(), random,
|
||||
"The same file that was uploaded is expected when downloaded");
|
||||
|
||||
// download complete
|
||||
@@ -209,7 +214,7 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// create artifact
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomUtils.nextBytes(artifactSize);
|
||||
final byte[] random = nextBytes(artifactSize);
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, artifactSize));
|
||||
|
||||
@@ -219,7 +224,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
final MvcResult result = mvc.perform(get(
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
|
||||
.andExpect(status().isOk()).andExpect(header().string("Content-Disposition",
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string("Content-Disposition",
|
||||
"attachment;filename=" + artifact.getFilename() + ".MD5SUM"))
|
||||
.andReturn();
|
||||
|
||||
@@ -233,7 +239,7 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
public void rangeDownloadArtifact() throws Exception {
|
||||
// create target
|
||||
final Target target = testdataFactory.createTarget();
|
||||
final List<Target> targets = Arrays.asList(target);
|
||||
final List<Target> targets = Collections.singletonList(target);
|
||||
|
||||
// create ds
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
@@ -241,7 +247,7 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
final int resultLength = (int) quotaManagement.getMaxArtifactSize();
|
||||
|
||||
// create artifact
|
||||
final byte random[] = RandomUtils.nextBytes(resultLength);
|
||||
final byte[] random = nextBytes(resultLength);
|
||||
final Artifact artifact = artifactManagement.create(
|
||||
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, resultLength));
|
||||
|
||||
@@ -255,19 +261,21 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
// full file download with standard range request
|
||||
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < resultLength / range; i++) {
|
||||
final String rangeString = "" + i * range + "-" + ((i + 1) * range - 1);
|
||||
final String rangeString = i * range + "-" + ((i + 1) * range - 1);
|
||||
|
||||
final MvcResult result = mvc.perform(get(
|
||||
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range",
|
||||
"bytes=" + rangeString))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(status().isPartialContent())
|
||||
.andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().longValue("Content-Length", range))
|
||||
.andExpect(header().string("Content-Range", "bytes " + rangeString + "/" + resultLength))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1"))
|
||||
.andReturn();
|
||||
|
||||
outputStream.write(result.getResponse().getContentAsByteArray());
|
||||
}
|
||||
@@ -279,14 +287,16 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=-1000"))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(status().isPartialContent())
|
||||
.andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().longValue("Content-Length", 1000))
|
||||
.andExpect(header().string("Content-Range",
|
||||
"bytes " + (resultLength - 1000) + "-" + (resultLength - 1) + "/" + resultLength))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1"))
|
||||
.andReturn();
|
||||
|
||||
assertThat(result.getResponse().getContentAsByteArray())
|
||||
.isEqualTo(Arrays.copyOfRange(random, resultLength - 1000, resultLength));
|
||||
@@ -296,14 +306,16 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=1000-"))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(status().isPartialContent())
|
||||
.andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().longValue("Content-Length", resultLength - 1000))
|
||||
.andExpect(header().string("Content-Range",
|
||||
"bytes " + 1000 + "-" + (resultLength - 1) + "/" + resultLength))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1"))
|
||||
.andReturn();
|
||||
|
||||
assertThat(result.getResponse().getContentAsByteArray())
|
||||
.isEqualTo(Arrays.copyOfRange(random, 1000, resultLength));
|
||||
@@ -325,11 +337,13 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
|
||||
.header("Range", "bytes=0-9,10-19"))
|
||||
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(status().isPartialContent())
|
||||
.andExpect(header().string("ETag", artifact.getSha1Hash()))
|
||||
.andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART"))
|
||||
.andExpect(header().string("Accept-Ranges", "bytes"))
|
||||
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn();
|
||||
.andExpect(header().string("Content-Disposition", "attachment;filename=file1"))
|
||||
.andReturn();
|
||||
|
||||
outputStream.reset();
|
||||
|
||||
@@ -365,5 +379,4 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -68,8 +68,10 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId(), tenantAware.getCurrentTenant())
|
||||
.accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andReturn().getResponse()
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andReturn().getResponse()
|
||||
.getContentAsByteArray();
|
||||
assertThat(JsonPathUtils.<String> evaluate(cborToJson(result), "$.id"))
|
||||
.isEqualTo(String.valueOf(cancelAction.getId()));
|
||||
@@ -81,7 +83,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(jsonToCbor(getJsonProceedingCancelActionFeedback()))
|
||||
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -102,7 +105,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
|
||||
@@ -110,7 +114,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId,
|
||||
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(jsonPath("$.id", equalTo(String.valueOf(actionId))))
|
||||
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
|
||||
@@ -128,7 +133,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
|
||||
Collections.singletonList("message")))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// check database after test
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||
@@ -152,8 +158,10 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final long timeBeforeFirstPoll = System.currentTimeMillis();
|
||||
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
|
||||
@@ -181,7 +189,9 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final long timeBefore2ndPoll = System.currentTimeMillis();
|
||||
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(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
@@ -193,7 +203,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId))));
|
||||
@@ -205,7 +216,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent();
|
||||
@@ -222,27 +234,32 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// not allowed methods
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
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());
|
||||
|
||||
// non existing target
|
||||
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());
|
||||
|
||||
createCancelAction("34534543");
|
||||
|
||||
// wrong media type
|
||||
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());
|
||||
|
||||
}
|
||||
@@ -267,7 +284,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
assertThat(countActionStatusAll()).isEqualTo(3);
|
||||
@@ -276,7 +294,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
assertThat(countActionStatusAll()).isEqualTo(4);
|
||||
|
||||
@@ -284,7 +303,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(5);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
@@ -294,7 +314,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(6);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
@@ -307,7 +328,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(7);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
@@ -316,7 +338,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(8);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
}
|
||||
@@ -352,14 +375,17 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId))));
|
||||
assertThat(countActionStatusAll()).isEqualTo(6);
|
||||
|
||||
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(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
@@ -371,7 +397,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(7);
|
||||
|
||||
// 1 update actions, 1 cancel actions
|
||||
@@ -379,14 +406,17 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId2))));
|
||||
assertThat(countActionStatusAll()).isEqualTo(8);
|
||||
|
||||
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(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.cancelAction.href",
|
||||
@@ -398,7 +428,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(9);
|
||||
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
|
||||
@@ -406,7 +437,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
|
||||
tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(10);
|
||||
|
||||
// 1 update actions, 0 cancel actions
|
||||
@@ -422,7 +454,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
|
||||
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId3))));
|
||||
@@ -433,7 +466,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
assertThat(countActionStatusAll()).isEqualTo(13);
|
||||
|
||||
// final status
|
||||
@@ -480,49 +514,57 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(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/"
|
||||
+ 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/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// bad content type
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isUnsupportedMediaType());
|
||||
|
||||
// bad body
|
||||
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/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
|
||||
tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback())
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// invalid action
|
||||
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/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// finaly, get it right :)
|
||||
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
|
||||
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
|
||||
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
private Action createCancelAction(final String targetid) {
|
||||
|
||||
@@ -52,10 +52,10 @@ import org.springframework.test.context.ActiveProfiles;
|
||||
@Story("Config Data Resource")
|
||||
class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
public static final String TARGET1_ID = "4717";
|
||||
public static final String TARGET1_CONFIGDATA_PATH = "/{tenant}/controller/v1/" + TARGET1_ID + "/configData";
|
||||
public static final String TARGET2_ID = "4718";
|
||||
public static final String TARGET2_CONFIGDATA_PATH = "/{tenant}/controller/v1/" + TARGET2_ID + "/configData";
|
||||
private static final String TARGET1_ID = "4717";
|
||||
private static final String TARGET1_CONFIG_DATA_PATH = "/{tenant}/controller/v1/" + TARGET1_ID + "/configData";
|
||||
private static final String TARGET2_ID = "4718";
|
||||
private static final String TARGET2_CONFIG_DATA_PATH = "/{tenant}/controller/v1/" + TARGET2_ID + "/configData";
|
||||
|
||||
@Test
|
||||
@Description("Verify that config data can be uploaded as CBOR")
|
||||
@@ -65,31 +65,31 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
||||
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.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());
|
||||
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "are requested only once from the device.")
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " +
|
||||
"are requested only once from the device.")
|
||||
@SuppressWarnings("squid:S2925")
|
||||
void requestConfigDataIfEmpty() throws Exception {
|
||||
final Target savedTarget = testdataFactory.createTarget("4712");
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.configData.href", equalTo(
|
||||
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
|
||||
Thread.sleep(1); // is required: otherwise processing the next line is
|
||||
// often too fast and
|
||||
// the following assert will fail
|
||||
// often too fast and // the following assert will fail
|
||||
assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new)
|
||||
.getLastTargetQuery())
|
||||
.isLessThanOrEqualTo(System.currentTimeMillis());
|
||||
@@ -97,26 +97,23 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
.getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
|
||||
final Map<String, String> attributes = new HashMap<>(1);
|
||||
attributes.put("dsafsdf", "sdsds");
|
||||
|
||||
final Target updateControllerAttributes = controllerManagement
|
||||
.updateControllerAttributes(savedTarget.getControllerId(), attributes, null);
|
||||
.updateControllerAttributes(savedTarget.getControllerId(), Map.of("dsafsdf", "sdsds"), null);
|
||||
// request controller attributes need to be false because we don't want
|
||||
// to request the controller attributes again
|
||||
assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse();
|
||||
|
||||
mvc.perform(
|
||||
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.configData.href").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "can be uploaded correctly by the controller.")
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " +
|
||||
"can be uploaded correctly by the controller.")
|
||||
void putConfigData() throws Exception {
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
@@ -124,38 +121,38 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
|
||||
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.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);
|
||||
|
||||
// update
|
||||
attributes.put("sdsds", "123412");
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.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);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) "
|
||||
+ "upload quota is enforced to protect the server from malicious attempts.")
|
||||
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " +
|
||||
"upload quota is enforced to protect the server from malicious attempts.")
|
||||
void putTooMuchConfigData() throws Exception {
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
// initial
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) {
|
||||
attributes.put("dsafsdf" + i, "sdsds" + i);
|
||||
}
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
attributes = new HashMap<>();
|
||||
attributes.put("on too many", "sdsds");
|
||||
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(Map.of("on too many", "sdsds")).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
@@ -174,27 +171,31 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(get("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// bad content type
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("dsafsdf", "sdsds");
|
||||
final Map<String, String> attributes = Map.of("dsafsdf", "sdsds");
|
||||
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isUnsupportedMediaType());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// bad body
|
||||
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
|
||||
.content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -209,7 +210,6 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
@Test
|
||||
@Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).")
|
||||
void putConfigDataWithDifferentUpdateModes() throws Exception {
|
||||
|
||||
// create a target
|
||||
testdataFactory.createTarget(TARGET1_ID);
|
||||
|
||||
@@ -232,7 +232,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
@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())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
||||
@@ -242,7 +242,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
@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())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET2_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
|
||||
@@ -252,14 +252,15 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
@Step
|
||||
private void putConfigDataWithInvalidUpdateMode() throws Exception {
|
||||
// create some attriutes
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("k0", "v0");
|
||||
attributes.put("k1", "v1");
|
||||
final Map<String, String> attributes = Map.of(
|
||||
"k0", "v0",
|
||||
"k1", "v1");
|
||||
|
||||
// use an invalid update mode
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@@ -269,13 +270,14 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
final int previousSize = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID).size();
|
||||
|
||||
// update the attributes using update mode REMOVE
|
||||
final Map<String, String> removeAttributes = new HashMap<>();
|
||||
removeAttributes.put("k1", "foo");
|
||||
removeAttributes.put("k3", "bar");
|
||||
final Map<String, String> removeAttributes = Map.of(
|
||||
"k1", "foo",
|
||||
"k3", "bar");
|
||||
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(removeAttributes, "remove").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute removal
|
||||
@@ -287,74 +289,68 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeMerge()
|
||||
throws Exception {
|
||||
private void putConfigDataWithUpdateModeMerge() throws Exception {
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
|
||||
|
||||
// update the attributes using update mode MERGE
|
||||
final Map<String, String> mergeAttributes = new HashMap<>();
|
||||
mergeAttributes.put("k1", "v1_modified_again");
|
||||
mergeAttributes.put("k4", "v4");
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
final Map<String, String> mergeAttributes = Map.of(
|
||||
"k1", "v1_modified_again",
|
||||
"k4", "v4");
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(mergeAttributes, "merge").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute merge
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).hasSize(4);
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes);
|
||||
assertThat(updatedAttributes).containsEntry("k1", "v1_modified_again");
|
||||
attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithUpdateModeReplace()
|
||||
throws Exception {
|
||||
private void putConfigDataWithUpdateModeReplace() throws Exception {
|
||||
// get the current attributes
|
||||
final Map<String, String> attributes = new HashMap<>(
|
||||
targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
|
||||
final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
|
||||
|
||||
// update the attributes using update mode REPLACE
|
||||
final Map<String, String> replacementAttributes = new HashMap<>();
|
||||
replacementAttributes.put("k1", "v1_modified");
|
||||
replacementAttributes.put("k2", "v2");
|
||||
replacementAttributes.put("k3", "v3");
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
final Map<String, String> replacementAttributes = Map.of(
|
||||
"k1", "v1_modified",
|
||||
"k2", "v2",
|
||||
"k3", "v3");
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.content(JsonBuilder.configData(replacementAttributes, "replace").toString())
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify attribute replacement
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).hasSize(replacementAttributes.size());
|
||||
assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes);
|
||||
assertThat(updatedAttributes).containsEntry("k1", "v1_modified");
|
||||
attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain);
|
||||
|
||||
}
|
||||
|
||||
@Step
|
||||
private void putConfigDataWithoutUpdateMode()
|
||||
throws Exception {
|
||||
// create some attriutes
|
||||
final Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("k0", "v0");
|
||||
attributes.put("k1", "v1");
|
||||
private void putConfigDataWithoutUpdateMode() throws Exception {
|
||||
// create some attributes
|
||||
final Map<String, String> attributes = Map.of(
|
||||
"k0", "v0",
|
||||
"k1", "v1");
|
||||
|
||||
// set the initial attributes
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
|
||||
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
|
||||
.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
|
||||
final Map<String, String> updatedAttributes = targetManagement
|
||||
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
|
||||
assertThat(updatedAttributes).containsExactlyEntriesOf(attributes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ 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.RandomUtils;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiActivateAutoConfirmation;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
@@ -80,44 +79,41 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final Artifact artifact = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
"test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
final Artifact artifact = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(
|
||||
nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget(DdiConfirmationBaseTest.DEFAULT_CONTROLLER_ID);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
|
||||
|
||||
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||
Action.ActionType.FORCED).getAssignedEntity().stream().map(Action::getTarget)
|
||||
final List<Target> targetsAssignedToDs = assignDistributionSet(
|
||||
ds.getId(), savedTarget.getControllerId(), Action.ActionType.FORCED).getAssignedEntity().stream()
|
||||
.map(Action::getTarget)
|
||||
.collect(Collectors.toList());
|
||||
implicitLock(ds);
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
|
||||
assignDistributionSet(ds2, targetsAssignedToDs).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
final long current = System.currentTimeMillis();
|
||||
final String expectedConfirmationBaseLink = String.format("/%s/controller/v1/%s/confirmationBase/%d",
|
||||
final String expectedConfirmationBaseLink = String.format(
|
||||
"/%s/controller/v1/%s/confirmationBase/%d",
|
||||
tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, uaction.getId());
|
||||
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.confirmationBase.href",
|
||||
containsString(expectedConfirmationBaseLink)))
|
||||
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
||||
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -128,7 +124,8 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
getAndVerifyConfirmationBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
|
||||
getAndVerifyConfirmationBasePayload(
|
||||
DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
|
||||
artifactSignature, action.getId(),
|
||||
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
|
||||
|
||||
@@ -151,8 +148,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), target.getName());
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
|
||||
|
||||
// get confirmation base
|
||||
performGet(CONFIRMATION_BASE_ACTION, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR),
|
||||
@@ -172,17 +168,16 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
|
||||
final String controllerId = savedTarget.getControllerId();
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
|
||||
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
|
||||
.get(0);
|
||||
|
||||
mvc.perform(
|
||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -197,20 +192,21 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final String controllerId = savedTarget.getControllerId();
|
||||
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
|
||||
.get(0);
|
||||
|
||||
mvc.perform(
|
||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
|
||||
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, savedAction.getId())
|
||||
.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())
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@@ -225,8 +221,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final String controllerId = savedTarget.getControllerId();
|
||||
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
|
||||
.get(0);
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
|
||||
|
||||
// disable confirmation flow
|
||||
disableConfirmationFlow();
|
||||
@@ -235,15 +230,17 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId());
|
||||
|
||||
// verify confirmation endpoint is still accessible
|
||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 20,
|
||||
"Action denied message.").andExpect(status().isOk());
|
||||
sendConfirmationFeedback(
|
||||
savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 20, "Action denied message.")
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// confirmation base should still be exposed
|
||||
verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId());
|
||||
|
||||
// verify confirmation endpoint is still accessible
|
||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10,
|
||||
"Action confirmed message.").andExpect(status().isOk());
|
||||
sendConfirmationFeedback(
|
||||
savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10, "Action confirmed message.")
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// assert deployment link is exposed to the target
|
||||
verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
|
||||
@@ -251,7 +248,8 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Controller sends a confirmed action state.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@@ -273,8 +271,9 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
|
||||
.get(0);
|
||||
|
||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10,
|
||||
"Action confirmed message.").andExpect(status().isOk());
|
||||
sendConfirmationFeedback(
|
||||
savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10, "Action confirmed message.")
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// assert deployment link is exposed to the target
|
||||
verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
|
||||
@@ -287,18 +286,19 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final String controllerId = testdataFactory.createTarget("989").getControllerId();
|
||||
assignDistributionSet(testdataFactory.createDistributionSet("").getId(), controllerId);
|
||||
final long actionId = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0)
|
||||
.getId();
|
||||
final long actionId = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0).getId();
|
||||
|
||||
final String confirmationBaseActionLink = String.format("/%s/controller/v1/%s/confirmationBase/%d",
|
||||
final String confirmationBaseActionLink = String.format(
|
||||
"/%s/controller/v1/%s/confirmationBase/%d",
|
||||
tenantAware.getCurrentTenant(), controllerId, actionId);
|
||||
|
||||
final String activateAutoConfLink = String.format("/%s/controller/v1/%s/confirmationBase/activateAutoConfirm",
|
||||
final String activateAutoConfLink = String.format(
|
||||
"/%s/controller/v1/%s/confirmationBase/activateAutoConfirm",
|
||||
tenantAware.getCurrentTenant(), controllerId);
|
||||
|
||||
mvc.perform(
|
||||
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE)))
|
||||
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(confirmationBaseActionLink)))
|
||||
.andExpect(jsonPath("$._links.activateAutoConfirm.href", containsString(activateAutoConfLink)))
|
||||
@@ -308,23 +308,24 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("possibleActiveStates")
|
||||
@Description("Confirmation base provides right values if auto-confirm is active.")
|
||||
void getConfirmationBaseProvidesAutoConfirmStatusActive(final String initiator, final String remark)
|
||||
throws Exception {
|
||||
void getConfirmationBaseProvidesAutoConfirmStatusActive(final String initiator, final String remark) throws Exception {
|
||||
final String controllerId = testdataFactory.createTarget("988").getControllerId();
|
||||
|
||||
confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark);
|
||||
|
||||
final String deactivateAutoConfLink = String.format(
|
||||
"/%s/controller/v1/%s/confirmationBase/deactivateAutoConfirm", tenantAware.getCurrentTenant(),
|
||||
controllerId);
|
||||
"/%s/controller/v1/%s/confirmationBase/deactivateAutoConfirm",
|
||||
tenantAware.getCurrentTenant(), controllerId);
|
||||
|
||||
mvc.perform(
|
||||
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE)))
|
||||
.andExpect(initiator == null ? jsonPath("autoConfirm.initiator").doesNotExist()
|
||||
.andExpect(initiator == null
|
||||
? jsonPath("autoConfirm.initiator").doesNotExist()
|
||||
: jsonPath("autoConfirm.initiator", equalTo(initiator)))
|
||||
.andExpect(remark == null ? jsonPath("autoConfirm.remark").doesNotExist()
|
||||
.andExpect(remark == null
|
||||
? jsonPath("autoConfirm.remark").doesNotExist()
|
||||
: jsonPath("autoConfirm.remark", equalTo(remark)))
|
||||
.andExpect(jsonPath("$._links.deactivateAutoConfirm.href", containsString(deactivateAutoConfLink)))
|
||||
.andExpect(jsonPath("$._links.activateAutoConfirm").doesNotExist());
|
||||
@@ -340,7 +341,8 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
mvc.perform(post(ACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId)
|
||||
.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(status.getInitiator()).isEqualTo(initiator);
|
||||
@@ -357,14 +359,16 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
confirmationManagement.activateAutoConfirmation(controllerId, null, null);
|
||||
|
||||
mvc.perform(post(DEACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
assertThat(confirmationManagement.getStatus(controllerId)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller sends a denied action state.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@@ -383,30 +387,33 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
Target savedTarget = testdataFactory.createTarget("989");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
String controllerId = savedTarget.getControllerId();
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
|
||||
.get(0);
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
|
||||
|
||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 10,
|
||||
"Action denied message.").andExpect(status().isOk());
|
||||
sendConfirmationFeedback(
|
||||
savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 10, "Action denied message.")
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// asserts that deployment link is not available
|
||||
final String expectedConfirmationBaseLink = String.format("/%s/controller/v1/%s/confirmationBase/%d",
|
||||
final String expectedConfirmationBaseLink = String.format(
|
||||
"/%s/controller/v1/%s/confirmationBase/%d",
|
||||
tenantAware.getCurrentTenant(), controllerId, savedAction.getId());
|
||||
|
||||
mvc.perform(
|
||||
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)));
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@@ -422,71 +429,80 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
Target savedTarget = testdataFactory.createTarget("990");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
|
||||
String controllerId = savedTarget.getControllerId();
|
||||
final String controllerId = savedTarget.getControllerId();
|
||||
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
|
||||
.get(0);
|
||||
final String CONFIRMED_MESSAGE = "Action confirmed message.";
|
||||
final Integer CONFIRMED_CODE = 10;
|
||||
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED,
|
||||
CONFIRMED_CODE, CONFIRMED_MESSAGE).andExpect(status().isOk());
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
|
||||
final String confirmedMessage = "Action confirmed message.";
|
||||
final Integer confirmedCode = 10;
|
||||
sendConfirmationFeedback(
|
||||
savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, confirmedCode, confirmedMessage)
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// confirmationBase not available in RUNNING state anymore
|
||||
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
||||
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
|
||||
// this call will update the action due to retrieved action status update
|
||||
mvc.perform(
|
||||
get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
||||
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString(CONFIRMED_MESSAGE))))
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
|
||||
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString(confirmedMessage))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
hasItem(containsString(String.format(CONFIRMATION_CODE_MSG_PREFIX, CONFIRMED_CODE)))));
|
||||
hasItem(containsString(String.format(CONFIRMATION_CODE_MSG_PREFIX, confirmedCode)))));
|
||||
}
|
||||
|
||||
private static Stream<Arguments> possibleActiveStates() {
|
||||
return Stream.of(Arguments.of("someInitiator", "someRemark"), Arguments.of(null, "someRemark"),
|
||||
Arguments.of("someInitiator", null), Arguments.of(null, null));
|
||||
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",
|
||||
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())
|
||||
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());
|
||||
.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())
|
||||
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());
|
||||
.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())
|
||||
.accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
private ResultActions sendConfirmationFeedback(final Target target, final Action action,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ 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.assertj.core.api.Condition;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
@@ -94,8 +93,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
testdataFactory.createArtifacts(softwareModuleId);
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), target.getName());
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
|
||||
|
||||
// get deployment base
|
||||
performGet(DEPLOYMENT_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
|
||||
@@ -107,17 +105,17 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
String.valueOf(softwareModuleId));
|
||||
|
||||
final byte[] feedback = jsonToCbor(getJsonProceedingDeploymentActionFeedback());
|
||||
|
||||
postDeploymentFeedback(MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), target.getControllerId(),
|
||||
action.getId(), feedback, status().isOk());
|
||||
postDeploymentFeedback(
|
||||
MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), target.getControllerId(), action.getId(), feedback,
|
||||
status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that artifacts are not found, when software module does not exists.")
|
||||
void artifactsNotFound() throws Exception {
|
||||
final Target target = testdataFactory.createTarget();
|
||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isNotFound(),
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), "1");
|
||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isNotFound(), tenantAware.getCurrentTenant(),
|
||||
target.getControllerId(), "1");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -131,8 +129,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
assignDistributionSet(distributionSet.getId(), target.getName());
|
||||
|
||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
|
||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
target.getControllerId(), softwareModuleId.toString())
|
||||
.andExpect(jsonPath("$", hasSize(3)))
|
||||
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
|
||||
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
|
||||
@@ -145,36 +143,37 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final Artifact artifact = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
"test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
final Artifact artifact = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(
|
||||
nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
final Target savedTarget = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||
ActionType.FORCED).getAssignedEntity().stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), ActionType.FORCED)
|
||||
.getAssignedEntity().stream()
|
||||
.map(Action::getTarget)
|
||||
.collect(Collectors.toList());
|
||||
implicitLock(ds);
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
|
||||
assignDistributionSet(ds2, targetsAssignedToDs).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
final long current = System.currentTimeMillis();
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href",
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath(
|
||||
"$._links.deploymentBase.href",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
@@ -183,7 +182,6 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
|
||||
artifactSignature, action.getId(),
|
||||
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
|
||||
@@ -207,14 +205,16 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
ActionType.TIMEFORCED, System.currentTimeMillis() + 2_000));
|
||||
|
||||
MvcResult mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(),
|
||||
tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID).andReturn();
|
||||
tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID)
|
||||
.andReturn();
|
||||
|
||||
final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
|
||||
.read(mvcResult.getResponse().getContentAsString()).toString();
|
||||
|
||||
// Time is not yet over, so we should see the same URL
|
||||
mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID).andReturn();
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andReturn();
|
||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).isEqualTo(urlBeforeSwitch)
|
||||
.startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, actionId.toString()));
|
||||
@@ -223,7 +223,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
TimeUnit.MILLISECONDS.sleep(2_000);
|
||||
|
||||
mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
|
||||
DEFAULT_CONTROLLER_ID).andReturn();
|
||||
DEFAULT_CONTROLLER_ID)
|
||||
.andReturn();
|
||||
|
||||
assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
|
||||
.toString()).isNotEqualTo(urlBeforeSwitch);
|
||||
@@ -238,9 +239,9 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final String visibleMetadataOsKey = "metaDataVisible";
|
||||
final String visibleMetadataOsValue = "withValue";
|
||||
|
||||
final Artifact artifact = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
final Artifact artifact = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
"test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
|
||||
@@ -255,23 +256,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
implicitLock(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
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",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -301,9 +300,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
|
||||
final Artifact artifact = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
"test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifact = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
final Target savedTarget = createTargetAndAssertNoActiveActions();
|
||||
@@ -313,23 +311,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
implicitLock(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
// Run test
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
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",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -339,7 +335,6 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
|
||||
artifactSignature, action.getId(),
|
||||
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
|
||||
@@ -362,10 +357,9 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// Prepare test data
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final Artifact artifact = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
"test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
final Artifact artifact = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(
|
||||
nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
|
||||
.key("metaDataVisible").value("withValue").targetVisible(true));
|
||||
@@ -374,21 +368,20 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final Target savedTarget = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(),
|
||||
ActionType.DOWNLOAD_ONLY).getAssignedEntity().stream().map(Action::getTarget)
|
||||
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), ActionType.DOWNLOAD_ONLY)
|
||||
.getAssignedEntity().stream()
|
||||
.map(Action::getTarget)
|
||||
.collect(Collectors.toList());
|
||||
implicitLock(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
|
||||
assignDistributionSet(ds2, saved).getAssignedEntity();
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
assertThat(uaction.getDistributionSet()).isEqualTo(ds);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
|
||||
|
||||
@@ -396,7 +389,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
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",
|
||||
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
|
||||
@@ -406,7 +400,6 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(countActionStatusAll()).isEqualTo(2);
|
||||
|
||||
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
|
||||
|
||||
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, "metaDataVisible",
|
||||
"withValue", artifact, artifactSignature, action.getId(), "forced", "skip",
|
||||
getOsModule(findDistributionSetByAction));
|
||||
@@ -426,22 +419,26 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "not-existing", "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// no deployment
|
||||
mvc.perform(
|
||||
MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// wrong media type
|
||||
final List<Target> toAssign = Collections.singletonList(target);
|
||||
@@ -449,23 +446,25 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
|
||||
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
|
||||
.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());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("The server protects itself against to many feedback upload attempts. The test verifies that "
|
||||
+ "it is not possible to exceed the configured maximum number of feedback uploads.")
|
||||
@Description("The server protects itself against to many feedback upload attempts. The test verifies that " +
|
||||
"it is not possible to exceed the configured maximum number of feedback uploads.")
|
||||
void tooMuchDeploymentActionFeedback() throws Exception {
|
||||
final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), DEFAULT_CONTROLLER_ID);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
|
||||
|
||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||
// assign distribution set creates an action status, so only 99 left
|
||||
@@ -477,23 +476,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("The server protects itself against too large feedback bodies. The test verifies that "
|
||||
+ "it is not possible to exceed the configured maximum number of feedback details.")
|
||||
@Description("The server protects itself against too large feedback bodies. The test verifies that " +
|
||||
"it is not possible to exceed the configured maximum number of feedback details.")
|
||||
void tooMuchDeploymentActionMessagesInFeedback() throws Exception {
|
||||
final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), DEFAULT_CONTROLLER_ID);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
|
||||
|
||||
final List<String> messages = new ArrayList<>();
|
||||
for (int i = 0; i < quotaManagement.getMaxMessagesPerActionStatus() + 1; i++) {
|
||||
messages.add(String.valueOf(i));
|
||||
}
|
||||
|
||||
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE,
|
||||
null, messages);
|
||||
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE, null, messages);
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(), feedback, status().isForbidden());
|
||||
}
|
||||
|
||||
@@ -519,27 +516,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.UNKNOWN)).hasSize(2);
|
||||
|
||||
// action1 done
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId1, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId1, getJsonClosedDeploymentActionFeedback(), status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 2,
|
||||
Optional.of(ds1));
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 2, Optional.of(ds1));
|
||||
assertStatusMessagesCount(4);
|
||||
|
||||
// action2 done
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId2, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId2, getJsonClosedDeploymentActionFeedback(), status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 1,
|
||||
Optional.of(ds2));
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 1, Optional.of(ds2));
|
||||
assertStatusMessagesCount(5);
|
||||
|
||||
// action3 done
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId3, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId3, getJsonClosedDeploymentActionFeedback(), status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.IN_SYNC, 0,
|
||||
Optional.of(ds3));
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds3));
|
||||
assertStatusMessagesCount(6);
|
||||
}
|
||||
|
||||
@@ -549,16 +540,15 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
|
||||
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
assignDistributionSet(ds, Collections.singletonList(savedTarget));
|
||||
final Action action = actionRepository
|
||||
.findAll(ActionSpecifications.byDistributionSetId(ds.getId()), PAGE)
|
||||
.map(Action.class::cast).getContent().get(0);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.FAILURE,
|
||||
Collections.singletonList("Error message")),
|
||||
getJsonActionFeedback(
|
||||
DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.FAILURE, Collections.singletonList("Error message")),
|
||||
status().isOk());
|
||||
|
||||
findTargetAndAssertUpdateStatus(Optional.empty(), TargetUpdateStatus.ERROR, 0, Optional.empty());
|
||||
@@ -567,60 +557,51 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// redo
|
||||
ds = distributionSetManagement.getWithDetails(ds.getId()).get();
|
||||
assignDistributionSet(ds,
|
||||
Collections.singletonList(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get()));
|
||||
final Action action2 = deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent()
|
||||
.get(0);
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(),
|
||||
status().isOk());
|
||||
assignDistributionSet(ds, Collections.singletonList(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get()));
|
||||
final Action action2 = deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent().get(0);
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(), status().isOk());
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds));
|
||||
assertTargetCountByStatus(0, 0, 1);
|
||||
assertThat(deploymentManagement.findInActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID)).hasSize(2);
|
||||
assertThat(countActionStatusAll()).isEqualTo(4);
|
||||
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action.getId()).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.ERROR));
|
||||
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action2.getId()).getContent()).haveAtLeast(1,
|
||||
new ActionStatusCondition(Status.FINISHED));
|
||||
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action.getId()).getContent())
|
||||
.haveAtLeast(1, new ActionStatusCondition(Status.ERROR));
|
||||
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action2.getId()).getContent())
|
||||
.haveAtLeast(1, new ActionStatusCondition(Status.FINISHED));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that the controller can provided as much feedback entries as necessary as long as it is in the configured limits.")
|
||||
void rootRsSingleDeploymentActionFeedback() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds,
|
||||
Collections.singletonList(testdataFactory.createTarget(DEFAULT_CONTROLLER_ID))));
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds,
|
||||
Collections.singletonList(testdataFactory.createTarget(DEFAULT_CONTROLLER_ID))));
|
||||
implicitLock(ds);
|
||||
findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.PENDING, 1, Optional.empty());
|
||||
|
||||
// Now valid Feedback
|
||||
for (int i = 0; i < 4; i++) {
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonProceedingDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonProceedingDeploymentActionFeedback(), status().isOk());
|
||||
assertActionStatusCount(i + 2, i);
|
||||
|
||||
}
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonScheduledDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonScheduledDeploymentActionFeedback(), status().isOk());
|
||||
assertActionStatusCount(6, 5);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonResumedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonResumedDeploymentActionFeedback(), status().isOk());
|
||||
assertActionStatusCount(7, 6);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonCanceledDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonCanceledDeploymentActionFeedback(), status().isOk());
|
||||
assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1);
|
||||
assertActionStatusCount(8, 7, 0, 0, 1);
|
||||
assertTargetCountByStatus(1, 0, 0);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonRejectedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonRejectedDeploymentActionFeedback(), status().isOk());
|
||||
assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1);
|
||||
assertActionStatusCount(9, 6, 1, 0, 1);
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
|
||||
assertStatusAndActiveActionsCount(TargetUpdateStatus.IN_SYNC, 0);
|
||||
assertActionStatusCount(10, 7, 1, 1, 1);
|
||||
assertTargetCountByStatus(0, 0, 1);
|
||||
@@ -636,9 +617,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet savedSet2 = testdataFactory.createDistributionSet("1");
|
||||
|
||||
// target does not exist
|
||||
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, 1234L, getJsonProceedingDeploymentActionFeedback(),
|
||||
status().isNotFound());
|
||||
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, 1234L, getJsonProceedingDeploymentActionFeedback(), status().isNotFound());
|
||||
|
||||
final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
|
||||
|
||||
@@ -648,8 +627,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(savedSet, Collections.singletonList(savedTarget)).getAssignedEntity().iterator().next();
|
||||
assignDistributionSet(savedSet2, Collections.singletonList(testdataFactory.createTarget("4713")));
|
||||
|
||||
final Action updateAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action updateAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
|
||||
// action exists but is not assigned to this target
|
||||
postDeploymentFeedback("4713", updateAction.getId(), getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING,
|
||||
@@ -657,53 +635,57 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// not allowed methods
|
||||
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());
|
||||
|
||||
mvc.perform(put(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that an invalid id in feedback body returns a bad request.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
void invalidIdInFeedbackReturnsBadRequest() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
|
||||
final String invalidFeedback = "{\"id\":\"AAAA\",\"status\":{\"execution\":\"proceeding\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
|
||||
postDeploymentFeedback("1080", action.getId(), invalidFeedback, status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a missing feedback result in feedback body returns a bad request.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
void missingResultAttributeInFeedbackReturnsBadRequest() throws Exception {
|
||||
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
|
||||
|
||||
final String missingResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, (DdiResult) null,
|
||||
Collections.singletonList("test"));
|
||||
@@ -714,20 +696,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a missing finished result in feedback body returns a bad request.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1) })
|
||||
void missingFinishedAttributeInFeedbackReturnsBadRequest() throws Exception {
|
||||
final Target target = testdataFactory.createTarget("1080");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
assignDistributionSet(ds.getId(), "1080");
|
||||
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent()
|
||||
.get(0);
|
||||
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
|
||||
final String missingFinishedResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED,
|
||||
new DdiResult(null, null),
|
||||
Collections.singletonList("test"));
|
||||
@@ -741,15 +724,15 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
return actionStatusRepository.count();
|
||||
}
|
||||
|
||||
private void getAndVerifyDeploymentBasePayload(final String controllerId, final MediaType mediaType,
|
||||
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));
|
||||
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) {
|
||||
@@ -760,8 +743,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(1);
|
||||
assertThat(countActionStatusAll()).isEqualTo(actionStatusCount);
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(minActionStatusCountInPage,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
assertThat(findActionStatusAll(PAGE).getContent())
|
||||
.haveAtLeast(minActionStatusCountInPage, new ActionStatusCondition(Status.RUNNING));
|
||||
}
|
||||
|
||||
private Target createTargetAndAssertNoActiveActions() {
|
||||
@@ -774,13 +757,13 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
private void assertStatusMessagesCount(final int actionStatusMessagesCount) {
|
||||
final Iterable<ActionStatus> actionStatusMessages;
|
||||
actionStatusMessages = findActionStatusAll(PageRequest.of(0, 100, Direction.DESC, "id"))
|
||||
.getContent();
|
||||
actionStatusMessages = findActionStatusAll(PageRequest.of(0, 100, Direction.DESC, "id")).getContent();
|
||||
assertThat(actionStatusMessages).hasSize(actionStatusMessagesCount);
|
||||
assertThat(actionStatusMessages).haveAtLeast(1, new ActionStatusCondition(Status.FINISHED));
|
||||
}
|
||||
|
||||
private void findTargetAndAssertUpdateStatus(final Optional<DistributionSet> ds,
|
||||
private void findTargetAndAssertUpdateStatus(
|
||||
final Optional<DistributionSet> ds,
|
||||
final TargetUpdateStatus updateStatus, final int activeActions,
|
||||
final Optional<DistributionSet> installedDs) {
|
||||
final Target myT = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
|
||||
@@ -791,31 +774,23 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
private void assertTargetCountByStatus(final int pending, final int error, final int inSync) {
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.PENDING))
|
||||
.hasSize(pending);
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.PENDING)).hasSize(pending);
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.ERROR)).hasSize(error);
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.IN_SYNC))
|
||||
.hasSize(inSync);
|
||||
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(inSync);
|
||||
}
|
||||
|
||||
private void assertActionStatusCount(final int total, final int running, final int warning, final int finished,
|
||||
final int canceled) {
|
||||
private void assertActionStatusCount(final int total, final int running, final int warning, final int finished, final int canceled) {
|
||||
assertThat(countActionStatusAll()).isEqualTo(total);
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(running,
|
||||
new ActionStatusCondition(Status.RUNNING));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(warning,
|
||||
new ActionStatusCondition(Status.WARNING));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(canceled,
|
||||
new ActionStatusCondition(Status.CANCELED));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(finished,
|
||||
new ActionStatusCondition(Status.FINISHED));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(running, new ActionStatusCondition(Status.RUNNING));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(warning, new ActionStatusCondition(Status.WARNING));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(canceled, new ActionStatusCondition(Status.CANCELED));
|
||||
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(finished, new ActionStatusCondition(Status.FINISHED));
|
||||
}
|
||||
|
||||
private void assertStatusAndActiveActionsCount(final TargetUpdateStatus status, final int activeActions) {
|
||||
final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
|
||||
assertThat(target.getUpdateStatus()).isEqualTo(status);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()))
|
||||
.hasSize(activeActions);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(activeActions);
|
||||
}
|
||||
|
||||
private Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
|
||||
@@ -835,4 +810,4 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
return value.getStatus() == status;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ 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.eclipse.hawkbit.ddi.json.model.DdiResult;
|
||||
import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
|
||||
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
|
||||
@@ -87,8 +86,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
testdataFactory.createArtifacts(softwareModuleId);
|
||||
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
|
||||
|
||||
// get installed base
|
||||
performGet(INSTALLED_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
|
||||
@@ -107,11 +105,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
// update assigned version
|
||||
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status()
|
||||
.isCreated());
|
||||
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isCreated());
|
||||
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId())
|
||||
.isEqualTo(ds.getId());
|
||||
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()).isEqualTo(ds.getId());
|
||||
|
||||
// update assigned version while version already assigned
|
||||
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isOk());
|
||||
@@ -137,15 +133,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target target = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true);
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
final Artifact artifact2 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifact2 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds2), "test2", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature2 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature2 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds2), "test2.signature", ARTIFACT_SIZE);
|
||||
|
||||
// Run test with 1st action
|
||||
@@ -161,8 +157,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId1,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Closed")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
|
||||
status().isOk());
|
||||
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
|
||||
@@ -182,8 +177,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED);
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId2,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Closed")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
|
||||
status().isOk());
|
||||
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2,
|
||||
@@ -195,8 +189,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
startsWith(installedBaseLink(CONTROLLER_ID, actionId2.toString()))))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
|
||||
|
||||
// older installed action is still accessible, although not part of controller
|
||||
// base
|
||||
// older installed action is still accessible, although not part of controller base
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
|
||||
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
|
||||
}
|
||||
@@ -208,9 +201,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target target = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true);
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
// assign ds1, action1 - and provide cancel feedback
|
||||
@@ -218,8 +211,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
deploymentManagement.cancelAction(actionId1);
|
||||
postCancelFeedback(target.getControllerId(), actionId1,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds1, action2 - and provide cancel feedback
|
||||
@@ -227,16 +219,14 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.FORCED));
|
||||
deploymentManagement.cancelAction(actionId2);
|
||||
postCancelFeedback(target.getControllerId(), actionId2,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds1, action 3 - and provide success feedback
|
||||
final Long actionId3 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId3,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// Test: latest succeeded action is returned in installedBase
|
||||
@@ -251,9 +241,13 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// cancelled action are not accessible
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId1.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId1.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId2.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId2.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -263,9 +257,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target target = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true);
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
@@ -274,8 +268,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Long actionId1 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId1,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Success")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Success")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds2, action2 - assign ds1, action 3 - and cancel both
|
||||
@@ -285,13 +278,11 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
deploymentManagement.cancelAction(actionId2);
|
||||
postCancelFeedback(target.getControllerId(), actionId2,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
deploymentManagement.cancelAction(actionId3);
|
||||
postCancelFeedback(target.getControllerId(), actionId3,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// Test: the succeeded action is returned in installedBase instead of the latest
|
||||
@@ -307,9 +298,13 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// cancelled action are not accessible
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId2.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId2.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId3.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId3.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -319,9 +314,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target target = createTargetAndAssertNoActiveActions();
|
||||
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true);
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifact1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature1 = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
|
||||
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
|
||||
@@ -330,8 +325,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Long actionId1 = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
postDeploymentFeedback(target.getControllerId(), actionId1,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Success")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Success")),
|
||||
status().isOk());
|
||||
|
||||
// assign ds2, action2 - assign ds1, action 3 - and cancel action 2
|
||||
@@ -341,12 +335,10 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
|
||||
deploymentManagement.cancelAction(actionId2);
|
||||
postCancelFeedback(target.getControllerId(), actionId2,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Canceled")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
|
||||
status().isOk());
|
||||
|
||||
// Test: the succeeded action is returned in installedBase instead of the latest
|
||||
// cancelled action
|
||||
// Test: the succeeded action is returned in installedBase instead of the latest cancelled action
|
||||
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID)
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.installedBase.href",
|
||||
@@ -359,9 +351,13 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// cancelled action are not accessible
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId2.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId2.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId3.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId3.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -382,7 +378,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
target.getControllerId(), actionId.toString());
|
||||
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
|
||||
actionId.toString())).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
actionId.toString()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -396,8 +394,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
|
||||
|
||||
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
|
||||
@@ -410,13 +407,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
@ParameterizedTest
|
||||
@MethodSource("org.eclipse.hawkbit.ddi.rest.resource.DdiInstalledBaseTest#actionTypeForDeployment")
|
||||
@Description("Test forced deployment to a controller. Checks that action is represented as installedBase after installation.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 5), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
@@ -424,26 +423,26 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// Prepare test data
|
||||
final Target target = createTargetAndAssertNoActiveActions();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("", true);
|
||||
final Artifact artifact = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
final Artifact artifact = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE), getOsModule(ds),
|
||||
"test1", ARTIFACT_SIZE);
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
|
||||
final Artifact artifactSignature = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
|
||||
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
|
||||
final Long actionId = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds.getId(), target.getControllerId(), actionType));
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId,
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS,
|
||||
Collections.singletonList("Closed")),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
|
||||
status().isOk());
|
||||
|
||||
// Run test
|
||||
final ResultActions resultActions = performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(),
|
||||
tenantAware.getCurrentTenant(), target.getControllerId());
|
||||
resultActions.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
resultActions.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||
.andExpect(jsonPath("$._links.installedBase.href",
|
||||
containsString(String.format("/%s/controller/v1/%s/installedBase/%d",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), actionId))));
|
||||
.andExpect(jsonPath("$._links.installedBase.href", containsString(String.format(
|
||||
"/%s/controller/v1/%s/installedBase/%d",
|
||||
tenantAware.getCurrentTenant(), target.getControllerId(), actionId))));
|
||||
|
||||
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature,
|
||||
actionId, ds.findFirstModuleByType(osType).get().getId(), actionType);
|
||||
@@ -461,13 +460,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test download-only deployment to a controller. Checks that download-only is not represented as installedBase.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 2) })
|
||||
@@ -479,18 +480,20 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds.getId(), target.getControllerId(), Action.ActionType.DOWNLOAD_ONLY));
|
||||
|
||||
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.installedBase.href").doesNotExist());
|
||||
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(),
|
||||
status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(), status().isOk());
|
||||
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(), status().isOk());
|
||||
|
||||
// Test
|
||||
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.installedBase.href").doesNotExist());
|
||||
}
|
||||
@@ -506,7 +509,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds.getId(), target.getControllerId(), actionType));
|
||||
|
||||
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.installedBase.href").doesNotExist());
|
||||
|
||||
@@ -520,7 +525,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// Test
|
||||
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.installedBase.href").doesNotExist());
|
||||
}
|
||||
@@ -531,8 +538,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
|
||||
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(),
|
||||
getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE,
|
||||
@@ -553,14 +559,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// for zero input no action history is returned
|
||||
mvc.perform(get(INSTALLED_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, 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").doesNotExist());
|
||||
|
||||
// depending on given query parameter value, only the latest messages are
|
||||
// returned
|
||||
// depending on given query parameter value, only the latest messages are returned
|
||||
mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, 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("Installation completed"))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
|
||||
.andExpect(
|
||||
@@ -569,7 +576,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
// for negative input the entire action history is returned
|
||||
mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", tenantAware.getCurrentTenant(), 911, 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("Installation completed"))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation scheduled"))));
|
||||
@@ -582,21 +590,26 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
// non existing target
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), "not-existing", "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// no deployment
|
||||
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// wrong media type
|
||||
final List<Target> toAssign = Collections.singletonList(target);
|
||||
@@ -605,9 +618,11 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
|
||||
postDeploymentFeedback(CONTROLLER_ID, actionId, getJsonClosedCancelActionFeedback(), status().isOk());
|
||||
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)
|
||||
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print())
|
||||
.accept(MediaType.APPLICATION_ATOM_XML))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotAcceptable());
|
||||
}
|
||||
|
||||
@@ -622,4 +637,4 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(actionStatusRepository.count()).isZero();
|
||||
return savedTarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
private static final String TARGET_COMPLETED_INSTALLATION_MSG = "Target completed installation.";
|
||||
private static final String TARGET_PROCEEDING_INSTALLATION_MSG = "Target proceeding installation.";
|
||||
private static final String TARGET_SCHEDULED_INSTALLATION_MSG = "Target scheduled installation.";
|
||||
|
||||
@Autowired
|
||||
private HawkbitSecurityProperties securityProperties;
|
||||
|
||||
@@ -93,7 +94,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensure that the root poll resource is available as CBOR")
|
||||
void rootPollResourceCbor() throws Exception {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@@ -101,46 +103,51 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensures that the API returns JSON when no Accept header is specified by the client.")
|
||||
void apiReturnsJSONByDefault() throws Exception {
|
||||
final MvcResult result = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn();
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andReturn();
|
||||
|
||||
// verify that we did not specify a content-type in the request, in case
|
||||
// there are any default values
|
||||
// verify that we did not specify a content-type in the request, in case there are any default values
|
||||
assertThat(result.getRequest().getHeader("Accept")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that targets cannot be created e.g. in plug'n play scenarios when tenant does not exists but can be created if the tenant exists.")
|
||||
@WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true, authorities = { CONTROLLER_ROLE,
|
||||
SYSTEM_ROLE }, autoCreateTenant = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true,
|
||||
authorities = { CONTROLLER_ROLE, SYSTEM_ROLE }, autoCreateTenant = false)
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetTypeCreatedEvent.class, count = 3),
|
||||
@Expect(type = SoftwareModuleTypeCreatedEvent.class, count = 2) })
|
||||
void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception {
|
||||
|
||||
mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant()))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
// create tenant -- creates softwaremoduletypes and distributionsettypes
|
||||
// create tenant -- creates software module types and distribution set types
|
||||
systemManagement.createTenantMetadata("tenantDoesNotExists");
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), "aControllerId"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// delete tenant again, will also deleted target aControllerId
|
||||
systemManagement.deleteTenant("tenantDoesNotExists");
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), "aControllerId"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that target poll request does not change audit data on the entity.")
|
||||
@WithUser(principal = "knownPrincipal", authorities = { SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET,
|
||||
SpPermission.CREATE_TARGET }, allSpPermissions = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
@WithUser(principal = "knownPrincipal", authorities = { SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET, SpPermission.CREATE_TARGET })
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void targetPollDoesNotModifyAuditData() throws Exception {
|
||||
// create target first with "knownPrincipal" user and audit data
|
||||
final String knownTargetControllerId = "target1";
|
||||
@@ -149,12 +156,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId).get();
|
||||
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
|
||||
|
||||
// make a poll, audit information should not be changed, run as
|
||||
// controller principal!
|
||||
// make a poll, audit information should not be changed, run as controller principal!
|
||||
SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS),
|
||||
() -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownTargetControllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -170,20 +177,25 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
@Description("Ensures that server returns a not found response in case of empty controller ID.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
|
||||
void rootRsWithoutId() throws Exception {
|
||||
mvc.perform(get("/controller/v1/")).andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
mvc.perform(get("/controller/v1/"))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the system creates a new target in plug and play manner, i.e. target is authenticated but does not exist yet.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void rootRsPlugAndPlay() throws Exception {
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
final String controllerId = "4711";
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", controllerId)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", controllerId))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
|
||||
assertThat(targetManagement.getByControllerID(controllerId).get().getLastTargetQuery())
|
||||
.isGreaterThanOrEqualTo(current);
|
||||
@@ -192,33 +204,38 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.isEqualTo(TargetUpdateStatus.REGISTERED);
|
||||
|
||||
// not allowed methods
|
||||
mvc.perform(post(CONTROLLER_BASE, "default-tenant", controllerId)).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(post(CONTROLLER_BASE, "default-tenant", controllerId))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(put(CONTROLLER_BASE, "default-tenant", controllerId)).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(put(CONTROLLER_BASE, "default-tenant", controllerId))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
|
||||
mvc.perform(delete(CONTROLLER_BASE, "default-tenant", controllerId)).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(delete(CONTROLLER_BASE, "default-tenant", controllerId))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isMethodNotAllowed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that tenant specific polling time, which is saved in the db, is delivered to the controller.")
|
||||
@WithUser(principal = "knownpricipal", allSpPermissions = false)
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1),
|
||||
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
|
||||
void pollWithModifiedGlobalPollingTime() throws Exception {
|
||||
SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", TENANT_CONFIGURATION),
|
||||
() -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:02:00");
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, "00:02:00");
|
||||
return null;
|
||||
});
|
||||
|
||||
SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711))
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
|
||||
return null;
|
||||
});
|
||||
@@ -226,10 +243,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that etag check results in not modified response if provided etag by client is identical to entity in repository.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 6),
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 3),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 2),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock
|
||||
@@ -239,14 +258,17 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
void rootRsNotModified() throws Exception {
|
||||
final String controllerId = "4711";
|
||||
final String etag = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))).andReturn().getResponse()
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andReturn().getResponse()
|
||||
.getHeader("ETag");
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match", etag))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotModified());
|
||||
|
||||
final Target target = targetManagement.getByControllerID(controllerId).get();
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
@@ -258,7 +280,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final String etagWithFirstUpdate = mvc
|
||||
.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
|
||||
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON).with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist())
|
||||
@@ -270,10 +293,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match",
|
||||
etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotModified());
|
||||
|
||||
// now lets finish the update
|
||||
sendDeploymentActionFeedback(target, updateAction, "closed", null).andDo(MockMvcResultPrinter.print())
|
||||
sendDeploymentActionFeedback(target, updateAction, "closed", null)
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// as the update was installed, and we always receive the installed action, the
|
||||
@@ -282,7 +307,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
|
||||
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON)
|
||||
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
|
||||
@@ -295,13 +321,13 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
assignDistributionSet(ds2.getId(), controllerId);
|
||||
|
||||
final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
|
||||
.header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON)
|
||||
.with(new RequestOnHawkbitDefaultPortPostProcessor()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
|
||||
.andExpect(jsonPath("$._links.installedBase.href",
|
||||
@@ -317,16 +343,16 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
+ "UNKNOWN to REGISTERED when the target polls for the first time.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void rootRsPrecommissioned() throws Exception {
|
||||
void rootRsPreCommissioned() throws Exception {
|
||||
final String controllerId = "4711";
|
||||
testdataFactory.createTarget(controllerId);
|
||||
|
||||
assertThat(targetManagement.getByControllerID(controllerId).get().getUpdateStatus())
|
||||
.isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
assertThat(targetManagement.getByControllerID(controllerId).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
|
||||
|
||||
final long current = System.currentTimeMillis();
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
|
||||
|
||||
@@ -341,7 +367,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the source IP address of the polling target is correctly stored in repository")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void rootRsPlugAndPlayIpAddress() throws Exception {
|
||||
// test
|
||||
@@ -352,7 +379,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS),
|
||||
() -> {
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -363,12 +391,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create);
|
||||
assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY");
|
||||
assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the source IP address of the polling target is not stored in repository if disabled")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = TargetPollEvent.class, count = 1) })
|
||||
void rootRsIpAddressNotStoredIfDisabled() throws Exception {
|
||||
securityProperties.getClients().setTrackRemoteIp(false);
|
||||
@@ -376,7 +404,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
// test
|
||||
final String knownControllerId1 = "0815";
|
||||
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// verify
|
||||
final Target target = targetManagement.getByControllerID(knownControllerId1).get();
|
||||
@@ -387,13 +416,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Controller trys to finish an update process after it has been finished by an error action status.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 1),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2) })
|
||||
void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
@@ -401,26 +432,32 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null).andDo(MockMvcResultPrinter.print())
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null)
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "failure").andDo(MockMvcResultPrinter.print())
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "failure")
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success").andDo(MockMvcResultPrinter.print())
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success")
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isGone());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Controller sends attribute update request after device successfully closed software update.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 6), @Expect(type = TargetPollEvent.class, count = 4),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 2),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 6),
|
||||
@Expect(type = TargetPollEvent.class, count = 4),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
|
||||
void attributeUpdateRequestSendingAfterSuccessfulDeployment() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("1");
|
||||
@@ -440,13 +477,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
|
||||
void testActionHistoryCount() throws Exception {
|
||||
@@ -457,17 +496,21 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.getContent().get(0);
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "scheduled", null, TARGET_SCHEDULED_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null, TARGET_PROCEEDING_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, 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(TARGET_COMPLETED_INSTALLATION_MSG))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
@@ -478,45 +521,52 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that a zero input value of actionHistory results in no action history appended for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
|
||||
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = ActionCreatedEvent.class, count = 1),
|
||||
@Expect(type = ActionUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetUpdatedEvent.class, count = 2),
|
||||
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
|
||||
void testActionHistoryZeroInput() throws Exception {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
Target savedTarget = testdataFactory.createTarget("911");
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "scheduled", null, TARGET_SCHEDULED_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null, TARGET_PROCEEDING_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", tenantAware.getCurrentTenant(), 911, 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").doesNotExist());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, 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").doesNotExist());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test to verify that entire action history is returned if the input value for actionHistory is -1, for getControllerDeploymentActionFeedback endpoint.")
|
||||
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@ExpectEvents({
|
||||
@Expect(type = TargetCreatedEvent.class, count = 1),
|
||||
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
|
||||
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
|
||||
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
|
||||
@@ -533,17 +583,21 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.getContent().get(0);
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "scheduled", null, TARGET_SCHEDULED_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null, TARGET_PROCEEDING_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success", TARGET_COMPLETED_INSTALLATION_MSG)
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", tenantAware.getCurrentTenant(), 911, 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(TARGET_SCHEDULED_INSTALLATION_MSG))))
|
||||
.andExpect(jsonPath("$.actionHistory.messages",
|
||||
@@ -561,8 +615,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
() -> {
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
|
||||
"00:05:00");
|
||||
tenantConfigurationManagement
|
||||
.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL, "00:01:00");
|
||||
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL, "00:01:00");
|
||||
return null;
|
||||
});
|
||||
|
||||
@@ -570,7 +623,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(), getTestSchedule(16),
|
||||
getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk())
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", greaterThanOrEqualTo("00:05:00")));
|
||||
|
||||
final Target savedTarget1 = testdataFactory.createTarget("2911");
|
||||
@@ -578,7 +632,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSetWithMaintenanceWindow(ds1.getId(), savedTarget1.getControllerId(), getTestSchedule(10),
|
||||
getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "2911")).andExpect(status().isOk())
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "2911"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", lessThan("00:05:00")))
|
||||
.andExpect(jsonPath("$.config.polling.sleep", greaterThanOrEqualTo("00:03:00")));
|
||||
|
||||
@@ -587,7 +642,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSetWithMaintenanceWindow(ds2.getId(), savedTarget2.getControllerId(), getTestSchedule(5),
|
||||
getTestDuration(5), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "3911")).andExpect(status().isOk())
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "3911"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", lessThan("00:02:00")));
|
||||
|
||||
final Target savedTarget3 = testdataFactory.createTarget("4911");
|
||||
@@ -595,9 +651,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSetWithMaintenanceWindow(ds3.getId(), savedTarget3.getControllerId(), getTestSchedule(-5),
|
||||
getTestDuration(15), getTestTimeZone()).getAssignedEntity().iterator().next();
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "4911")).andExpect(status().isOk())
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "4911"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:05:00")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -608,13 +664,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(),
|
||||
savedTarget.getControllerId(), getTestSchedule(2), getTestDuration(1), getTestTimeZone()));
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk());
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911"))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
|
||||
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.update", equalTo("skip")))
|
||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable")));
|
||||
@@ -628,13 +686,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(),
|
||||
savedTarget.getControllerId(), getTestSchedule(-5), getTestDuration(10), getTestTimeZone()));
|
||||
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911")).andExpect(status().isOk());
|
||||
mvc.perform(get(CONTROLLER_BASE, "default-tenant", "1911"))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
|
||||
|
||||
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.update", equalTo("forced")))
|
||||
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available")));
|
||||
@@ -648,13 +708,11 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
|
||||
final Action action1 = getFirstAssignedAction(assignDistributionSet(ds1.getId(), target.getControllerId(), 56));
|
||||
final Long action2Id = getFirstAssignedActionId(
|
||||
assignDistributionSet(ds2.getId(), target.getControllerId(), 34));
|
||||
final Long action2Id = getFirstAssignedActionId(assignDistributionSet(ds2.getId(), target.getControllerId(), 34));
|
||||
|
||||
assertDeploymentActionIsExposedToTarget(target.getControllerId(), action1.getId());
|
||||
sendDeploymentActionFeedback(target, action1, "closed", "success");
|
||||
assertDeploymentActionIsExposedToTarget(target.getControllerId(), action2Id);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -666,39 +724,39 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
}
|
||||
|
||||
@Step
|
||||
private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds)
|
||||
throws Exception {
|
||||
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());
|
||||
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 {
|
||||
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());
|
||||
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())
|
||||
.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())
|
||||
.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 {
|
||||
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution, String finished,
|
||||
String message) throws Exception {
|
||||
if (finished == null) {
|
||||
finished = "none";
|
||||
}
|
||||
@@ -713,19 +771,18 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
|
||||
.content(feedback).contentType(MediaType.APPLICATION_JSON));
|
||||
}
|
||||
|
||||
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution,
|
||||
final String finished) throws Exception {
|
||||
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)
|
||||
throws Exception {
|
||||
private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId) throws Exception {
|
||||
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
|
||||
tenantAware.getCurrentTenant(), controllerId, expectedActionId);
|
||||
mvc.perform(
|
||||
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)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,28 +46,26 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
@Override
|
||||
protected DefaultMockMvcBuilder createMvcWebAppContext(final WebApplicationContext context) {
|
||||
return super.createMvcWebAppContext(context).addFilter(
|
||||
new DosFilter(null, 10, 10,
|
||||
"127\\.0\\.0\\.1|\\[0:0:0:0:0:0:0:1\\]", "(^192\\.168\\.)",
|
||||
"X-Forwarded-For"));
|
||||
new DosFilter(null, 10, 10, "127\\.0\\.0\\.1|\\[0:0:0:0:0:0:0:1\\]", "(^192\\.168\\.)", "X-Forwarded-For"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that clients that are on the blacklist are forbidden")
|
||||
void blackListedClientIsForbidden() throws Exception {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 ")).andExpect(status().isForbidden());
|
||||
.header(X_FORWARDED_FOR, "192.168.0.4 , 10.0.0.1 "))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a READ DoS attempt is blocked ")
|
||||
void getFloodingAttackThatIsPrevented() throws Exception {
|
||||
|
||||
MvcResult result = null;
|
||||
|
||||
int requests = 0;
|
||||
MvcResult result;
|
||||
do {
|
||||
result = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(X_FORWARDED_FOR, "10.0.0.1")).andReturn();
|
||||
.header(X_FORWARDED_FOR, "10.0.0.1"))
|
||||
.andReturn();
|
||||
requests++;
|
||||
|
||||
// we give up after 1.000 requests
|
||||
@@ -83,7 +81,8 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(X_FORWARDED_FOR, "127.0.0.1")).andExpect(status().isOk());
|
||||
.header(X_FORWARDED_FOR, "127.0.0.1"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,22 +91,23 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(X_FORWARDED_FOR, "0:0:0:0:0:0:0:1")).andExpect(status().isOk());
|
||||
.header(X_FORWARDED_FOR, "0:0:0:0:0:0:0:1"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
|
||||
// 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 {
|
||||
|
||||
for (int x = 0; x < 3; x++) {
|
||||
// sleep for one second
|
||||
Thread.sleep(1100);
|
||||
for (int i = 0; i < 9; i++) {
|
||||
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant())
|
||||
.header(X_FORWARDED_FOR, "10.0.0.1")).andExpect(status().isOk());
|
||||
.header(X_FORWARDED_FOR, "10.0.0.1"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,8 +118,8 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||
|
||||
MvcResult result = null;
|
||||
int requests = 0;
|
||||
MvcResult result;
|
||||
do {
|
||||
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
|
||||
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback)
|
||||
@@ -133,13 +133,12 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
|
||||
// the filter shuts down after 10 POST requests
|
||||
assertThat(requests).isGreaterThanOrEqualTo(10);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
|
||||
// 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 {
|
||||
final Long actionId = prepareDeploymentBase();
|
||||
final String feedback = getJsonProceedingDeploymentActionFeedback();
|
||||
@@ -166,8 +165,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
|
||||
assignDistributionSet(ds, toAssign);
|
||||
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(1);
|
||||
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())
|
||||
.getContent().get(0);
|
||||
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
|
||||
|
||||
return uaction.getId();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user