Code refactoring of hawkbit-ddi-resource (#2053)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-11-16 20:17:27 +02:00
committed by GitHub
parent ca2c50ffa5
commit c90e3384ef
12 changed files with 979 additions and 855 deletions

View File

@@ -13,6 +13,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; 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.ApiType;
import org.eclipse.hawkbit.artifact.repository.urlhandler.ArtifactUrlHandler; import org.eclipse.hawkbit.artifact.repository.urlhandler.ArtifactUrlHandler;
import org.eclipse.hawkbit.artifact.repository.urlhandler.URLPlaceholder; import org.eclipse.hawkbit.artifact.repository.urlhandler.URLPlaceholder;
@@ -44,14 +46,11 @@ import org.springframework.util.CollectionUtils;
/** /**
* Utility class for the DDI API. * Utility class for the DDI API.
*/ */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class DataConversionHelper { public final class DataConversionHelper {
// utility class, private constructor. public static DdiConfirmationBase createConfirmationBase(
private DataConversionHelper() { final Target target, final Action activeAction,
}
public static DdiConfirmationBase createConfirmationBase(final Target target, final Action activeAction,
final DdiAutoConfirmationState autoConfirmationState, final TenantAware tenantAware) { final DdiAutoConfirmationState autoConfirmationState, final TenantAware tenantAware) {
final String controllerId = target.getControllerId(); final String controllerId = target.getControllerId();
final DdiConfirmationBase confirmationBase = new DdiConfirmationBase(autoConfirmationState); final DdiConfirmationBase confirmationBase = new DdiConfirmationBase(autoConfirmationState);
@@ -77,7 +76,8 @@ public final class DataConversionHelper {
return confirmationBase; 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 Action activeAction, final String defaultControllerPollTime, final TenantAware tenantAware) {
final DdiControllerBase result = new DdiControllerBase( final DdiControllerBase result = new DdiControllerBase(
new DdiConfig(new DdiPolling(defaultControllerPollTime))); new DdiConfig(new DdiPolling(defaultControllerPollTime)));
@@ -97,14 +97,13 @@ public final class DataConversionHelper {
activeAction.getId())) activeAction.getId()))
.withRel(DdiRestConstants.CANCEL_ACTION).expand()); .withRel(DdiRestConstants.CANCEL_ACTION).expand());
} else { } else {
// we need to add the hashcode here of the actionWithStatus // we need to add the hashcode here of the actionWithStatus because the action might
// because the action might // have changed from 'soft' to 'forced' type, and we need to change the payload of the
// have changed from 'soft' to 'forced' type and we need to
// change the payload of the
// response because of eTags. // response because of eTags.
result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder result.add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
.getControllerDeploymentBaseAction(tenantAware.getCurrentTenant(), target.getControllerId(), .getControllerDeploymentBaseAction(
tenantAware.getCurrentTenant(), target.getControllerId(),
activeAction.getId(), calculateEtag(activeAction), null)) activeAction.getId(), calculateEtag(activeAction), null))
.withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand()); .withRel(DdiRestConstants.DEPLOYMENT_BASE_ACTION).expand());
} }
@@ -121,7 +120,8 @@ public final class DataConversionHelper {
if (target.isRequestControllerAttributes()) { if (target.isRequestControllerAttributes()) {
result.add(WebMvcLinkBuilder result.add(WebMvcLinkBuilder
.linkTo(WebMvcLinkBuilder.methodOn(DdiRootController.class, tenantAware.getCurrentTenant()) .linkTo(WebMvcLinkBuilder
.methodOn(DdiRootController.class, tenantAware.getCurrentTenant())
.putConfigData(null, tenantAware.getCurrentTenant(), target.getControllerId())) .putConfigData(null, tenantAware.getCurrentTenant(), target.getControllerId()))
.withRel(DdiRestConstants.CONFIG_DATA_ACTION).expand()); .withRel(DdiRestConstants.CONFIG_DATA_ACTION).expand());
} }
@@ -129,10 +129,10 @@ public final class DataConversionHelper {
return result; 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 ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
final HttpRequest request, final ControllerManagement controllerManagement) { final HttpRequest request, final ControllerManagement controllerManagement) {
final Map<Long, List<SoftwareModuleMetadata>> metadata = controllerManagement final Map<Long, List<SoftwareModuleMetadata>> metadata = controllerManagement
.findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream() .findTargetVisibleMetaDataBySoftwareModuleId(uAction.getDistributionSet().getModules().stream()
.map(SoftwareModule::getId).collect(Collectors.toList())); .map(SoftwareModule::getId).collect(Collectors.toList()));
@@ -156,7 +156,8 @@ public final class DataConversionHelper {
} }
private static List<DdiMetadata> mapMetadata(final List<SoftwareModuleMetadata> metadata) { 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()); : 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)) { if ("runtime".equals(key)) {
return "jvm"; return "jvm";
} }
return key; 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 Artifact artifact, final SystemManagement systemManagement, final HttpRequest request) {
final DdiArtifact file = new DdiArtifact(); final DdiArtifact file = new DdiArtifact();
file.setHashes(new DdiArtifactHash(artifact.getSha1Hash(), artifact.getMd5Hash(), artifact.getSha256Hash())); 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())); .forEach(entry -> file.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand()));
return file; return file;
} }
/** /**
* Calculates an etag for the given {@link Action} based on the entities * Calculates an etag for the given {@link Action} based on the entities hashcode and the {@link Action#isHitAutoForceTime(long)}
* hashcode and the {@link Action#isHitAutoForceTime(long)} to reflect a * to reflect a force switch.
* force switch.
* *
* @param action to calculate the etag for * @param action to calculate the etag for
* @return the etag * @return the etag
@@ -207,5 +206,4 @@ public final class DataConversionHelper {
result = prime * result + offsetPrime; result = prime * result + offsetPrime;
return result; return result;
} }
}
}

View File

@@ -23,7 +23,5 @@ import org.springframework.stereotype.Controller;
*/ */
@Configuration @Configuration
@ComponentScan @ComponentScan
@Import({ RestConfiguration.class, OpenApiConfiguration.class }) @Import({ RestConfiguration.class, OpenApiConfiguration.class, DdiOpenApiConfiguration.class })
public class DdiApiConfiguration { public class DdiApiConfiguration {}
}

View File

@@ -91,9 +91,9 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.WebApplicationContext;
/** /**
* The {@link DdiRootController} of the hawkBit server DDI API that is queried * The {@link DdiRootController} of the hawkBit server DDI API that is queried by the hawkBit
* by the hawkBit controller in order to pull {@link Action}s that have to be * controller in order to pull {@link Action}s that have to be fulfilled and report status updates concerning
* fulfilled and report status updates concerning the {@link Action} processing. * the {@link Action} processing.
* *
* Transactional (read-write) as all queries at least update the last poll time. * 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; private EntityFactory entityFactory;
@Override @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("controllerId") final String controllerId,
@PathVariable("softwareModuleId") final Long softwareModuleId) { @PathVariable("softwareModuleId") final Long softwareModuleId) {
log.debug("getSoftwareModulesArtifacts({})", controllerId); log.debug("getSoftwareModulesArtifacts({})", controllerId);
@@ -156,7 +157,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @Override
public ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("tenant") final String tenant, public ResponseEntity<DdiControllerBase> getControllerBase(
@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") final String controllerId) { @PathVariable("controllerId") final String controllerId) {
log.debug("getControllerBase({})", controllerId); log.debug("getControllerBase({})", controllerId);
@@ -170,9 +172,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
// activeAction // activeAction
return new ResponseEntity<>(DataConversionHelper.fromTarget(target, installedAction, activeAction, return new ResponseEntity<>(DataConversionHelper.fromTarget(target, installedAction, activeAction,
activeAction == null ? controllerManagement.getPollingTime() activeAction == null
: controllerManagement.getPollingTimeForAction(activeAction.getId()), ? controllerManagement.getPollingTime()
tenantAware), HttpStatus.OK); : controllerManagement.getPollingTimeForAction(activeAction.getId()), tenantAware),
HttpStatus.OK);
} }
@Override @Override
@@ -200,11 +203,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) { if (ifMatch != null && !HttpUtil.matchesHttpHeader(ifMatch, artifact.getSha1Hash())) {
result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED); result = new ResponseEntity<>(HttpStatus.PRECONDITION_FAILED);
} else { } else {
final ActionStatus action = checkAndLogDownload(RequestResponseContextHolder.getHttpServletRequest(), final ActionStatus action = checkAndLogDownload(RequestResponseContextHolder.getHttpServletRequest(), target, module.getId());
target, module.getId());
final Long statusId = action.getId(); final Long statusId = action.getId();
result = FileStreamingUtil.writeFileResponse(file, artifact.getFilename(), artifact.getCreatedAt(), result = FileStreamingUtil.writeFileResponse(file, artifact.getFilename(), artifact.getCreatedAt(),
RequestResponseContextHolder.getHttpServletResponse(), RequestResponseContextHolder.getHttpServletResponse(),
RequestResponseContextHolder.getHttpServletRequest(), RequestResponseContextHolder.getHttpServletRequest(),
@@ -218,11 +218,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
return result; 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") @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("controllerId") final String controllerId,
@PathVariable("softwareModuleId") final Long softwareModuleId, @PathVariable("softwareModuleId") final Long softwareModuleId,
@PathVariable("fileName") final String fileName) { @PathVariable("fileName") final String fileName) {
@@ -249,12 +249,12 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@Override @Override
public ResponseEntity<DdiDeploymentBase> getControllerDeploymentBaseAction( 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, @PathVariable("actionId") final Long actionId,
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource, @RequestParam(value = "c", required = false, defaultValue = "-1") final int resource,
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) { @RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
@@ -266,13 +266,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
checkAndCancelExpiredAction(action); checkAndCancelExpiredAction(action);
if (!action.isCancelingOrCanceled() && !action.isWaitingConfirmation()) { if (!action.isCancelingOrCanceled() && !action.isWaitingConfirmation()) {
final DdiDeploymentBase base = generateDdiDeploymentBase(target, action, actionHistoryMessageCount); final DdiDeploymentBase base = generateDdiDeploymentBase(target, action, actionHistoryMessageCount);
log.debug("Found an active UpdateAction for target {}. returning deployment: {}", controllerId, base); log.debug("Found an active UpdateAction for target {}. returning deployment: {}", controllerId, base);
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX +
+ "Target retrieved update action and should start now the download."); "Target retrieved update action and should start now the download.");
return new ResponseEntity<>(base, HttpStatus.OK); return new ResponseEntity<>(base, HttpStatus.OK);
} }
@@ -281,8 +279,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @Override
public ResponseEntity<Void> postDeploymentBaseActionFeedback(@Valid @RequestBody final DdiActionFeedback feedback, public ResponseEntity<Void> postDeploymentBaseActionFeedback(
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId, @Valid @RequestBody final DdiActionFeedback feedback,
@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") final String controllerId,
@PathVariable("actionId") @NotNull final Long actionId) { @PathVariable("actionId") @NotNull final Long actionId) {
log.debug("postDeploymentBaseActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback); log.debug("postDeploymentBaseActionFeedback for target [{},{}]: {}", controllerId, actionId, feedback);
@@ -294,8 +294,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
if (!action.isActive()) { if (!action.isActive()) {
log.warn("Updating action {} with feedback {} not possible since action not active anymore.", log.warn("Updating action {} with feedback {} not possible since action not active anymore.", action.getId(), feedback.getStatus());
action.getId(), feedback.getStatus());
return new ResponseEntity<>(HttpStatus.GONE); return new ResponseEntity<>(HttpStatus.GONE);
} }
@@ -305,9 +304,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @Override
public ResponseEntity<Void> putConfigData(@Valid @RequestBody final DdiConfigData configData, public ResponseEntity<Void> putConfigData(
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) { @Valid @RequestBody final DdiConfigData configData,
@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") final String controllerId) {
controllerManagement.updateControllerAttributes(controllerId, configData.getData(), getUpdateMode(configData)); controllerManagement.updateControllerAttributes(controllerId, configData.getData(), getUpdateMode(configData));
return ResponseEntity.ok().build(); return ResponseEntity.ok().build();
} }
@@ -322,13 +322,11 @@ public class DdiRootController implements DdiRootControllerRestApi {
final Action action = findActionForTarget(actionId, target); final Action action = findActionForTarget(actionId, target);
if (action.isCancelingOrCanceled()) { if (action.isCancelingOrCanceled()) {
final DdiCancel cancel = new DdiCancel(String.valueOf(action.getId()), final DdiCancel cancel = new DdiCancel(String.valueOf(action.getId()), new DdiCancelActionToStop(String.valueOf(action.getId())));
new DdiCancelActionToStop(String.valueOf(action.getId())));
log.debug("Found an active CancelAction for target {}. returning cancel: {}", controllerId, cancel); log.debug("Found an active CancelAction for target {}. returning cancel: {}", controllerId, cancel);
controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX controllerManagement.registerRetrieved(action.getId(), RepositoryConstants.SERVER_MESSAGE_PREFIX +
+ "Target retrieved cancel action and should start now the cancellation."); "Target retrieved cancel action and should start now the cancellation.");
return new ResponseEntity<>(cancel, HttpStatus.OK); return new ResponseEntity<>(cancel, HttpStatus.OK);
} }
@@ -337,7 +335,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @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("tenant") final String tenant,
@PathVariable("controllerId") @NotEmpty final String controllerId, @PathVariable("controllerId") @NotEmpty final String controllerId,
@PathVariable("actionId") @NotNull final Long actionId) { @PathVariable("actionId") @NotNull final Long actionId) {
@@ -352,7 +351,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @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, @PathVariable("controllerId") final String controllerId, @PathVariable("actionId") final Long actionId,
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) { @RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
log.debug("getControllerInstalledAction({})", controllerId); log.debug("getControllerInstalledAction({})", controllerId);
@@ -380,14 +380,15 @@ public class DdiRootController implements DdiRootControllerRestApi {
final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId); final DdiAutoConfirmationState autoConfirmationState = getAutoConfirmationState(controllerId);
final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase(target, activeAction, final DdiConfirmationBase confirmationBase = DataConversionHelper.createConfirmationBase(
autoConfirmationState, tenantAware); target, activeAction, autoConfirmationState, tenantAware);
return new ResponseEntity<>(confirmationBase, HttpStatus.OK); return new ResponseEntity<>(confirmationBase, HttpStatus.OK);
} }
@Override @Override
public ResponseEntity<DdiConfirmationBaseAction> getConfirmationBaseAction( 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, @PathVariable("actionId") final Long actionId,
@RequestParam(value = "c", required = false, defaultValue = "-1") final int resource, @RequestParam(value = "c", required = false, defaultValue = "-1") final int resource,
@RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) { @RequestParam(value = "actionHistory", defaultValue = DdiRestConstants.NO_ACTION_HISTORY) final Integer actionHistoryMessageCount) {
@@ -399,10 +400,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
checkAndCancelExpiredAction(action); checkAndCancelExpiredAction(action);
if (!action.isCancelingOrCanceled() && action.isWaitingConfirmation()) { 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); log.debug("Found an active UpdateAction for target {}. Returning confirmation: {}", controllerId, base);
return new ResponseEntity<>(base, HttpStatus.OK); return new ResponseEntity<>(base, HttpStatus.OK);
@@ -413,17 +411,15 @@ public class DdiRootController implements DdiRootControllerRestApi {
@Override @Override
public ResponseEntity<Void> postConfirmationActionFeedback( 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("controllerId") final String controllerId,
@PathVariable("actionId") @NotNull final Long actionId) { @PathVariable("actionId") @NotNull final Long actionId) {
log.debug("provideConfirmationActionFeedback with feedback [controllerId={}, actionId={}]: {}", controllerId, log.debug("provideConfirmationActionFeedback with feedback [controllerId={}, actionId={}]: {}", controllerId, actionId, feedback);
actionId, feedback);
final Target target = findTarget(controllerId); final Target target = findTarget(controllerId);
final Action action = findActionForTarget(actionId, target); final Action action = findActionForTarget(actionId, target);
try { try {
switch (feedback.getConfirmation()) { switch (feedback.getConfirmation()) {
case CONFIRMED: case CONFIRMED:
log.info("Controller confirmed the action (actionId: {}, controllerId: {}) as we got {} report.", log.info("Controller confirmed the action (actionId: {}, controllerId: {}) as we got {} report.",
@@ -452,8 +448,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @Override
public ResponseEntity<Void> activateAutoConfirmation(final String tenant, final String controllerId, public ResponseEntity<Void> activateAutoConfirmation(
final DdiActivateAutoConfirmation body) { final String tenant, final String controllerId, final DdiActivateAutoConfirmation body) {
final String initiator = body == null ? null : body.getInitiator(); final String initiator = body == null ? null : body.getInitiator();
final String remark = body == null ? FALLBACK_REMARK : body.getRemark(); final String remark = body == null ? FALLBACK_REMARK : body.getRemark();
log.debug("Activate auto-confirmation request for device '{}' with payload: [initiator='{}' | remark='{}'", log.debug("Activate auto-confirmation request for device '{}' with payload: [initiator='{}' | remark='{}'",
@@ -470,8 +466,10 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
@Override @Override
public ResponseEntity<Void> setAsssignedOfflineVersion(@Valid @RequestBody DdiAssignedVersion ddiAssignedVersion, public ResponseEntity<Void> setAsssignedOfflineVersion(
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId) { @Valid @RequestBody DdiAssignedVersion ddiAssignedVersion,
@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") final String controllerId) {
boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId, boolean updated = controllerManagement.updateOfflineAssignedVersion(controllerId,
ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion()); ddiAssignedVersion.getName(), ddiAssignedVersion.getVersion());
if (updated) { if (updated) {
@@ -514,29 +512,31 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
} }
private static ActionStatusCreate generateActionCancelStatus(final DdiActionFeedback feedback, final Target target, private static ActionStatusCreate generateActionCancelStatus(
final Long actionId, final EntityFactory entityFactory) { final DdiActionFeedback feedback, final Target target, final Long actionId, final EntityFactory entityFactory) {
final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId); final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
final List<String> messages = new ArrayList<>(); final List<String> messages = new ArrayList<>();
final Status status; final Status status;
switch (feedback.getStatus().getExecution()) { switch (feedback.getStatus().getExecution()) {
case CANCELED: case CANCELED: {
status = handleCaseCancelCanceled(feedback, target, actionId, messages); status = handleCaseCancelCanceled(feedback, target, actionId, messages);
break; break;
case REJECTED: }
case REJECTED: {
log.info("Target rejected the cancellation request (actionId: {}, controllerId: {}).", actionId, log.info("Target rejected the cancellation request (actionId: {}, controllerId: {}).", actionId,
target.getControllerId()); target.getControllerId());
status = Status.CANCEL_REJECTED; status = Status.CANCEL_REJECTED;
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancellation request."); messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancellation request.");
break; break;
case CLOSED: }
case CLOSED: {
status = handleCancelClosedCase(feedback, messages); status = handleCancelClosedCase(feedback, messages);
break; break;
default: }
default: {
status = Status.RUNNING; status = Status.RUNNING;
break; break;
}
} }
if (feedback.getStatus().getDetails() != null) { if (feedback.getStatus().getDetails() != null) {
@@ -550,7 +550,6 @@ public class DdiRootController implements DdiRootControllerRestApi {
} }
return actionStatusCreate.status(status).messages(messages); return actionStatusCreate.status(status).messages(messages);
} }
private static Status handleCancelClosedCase(final DdiActionFeedback feedback, final List<String> messages) { private static Status handleCancelClosedCase(final DdiActionFeedback feedback, final List<String> messages) {
@@ -565,15 +564,15 @@ public class DdiRootController implements DdiRootControllerRestApi {
return status; return status;
} }
private static Status handleCaseCancelCanceled(final DdiActionFeedback feedback, final Target target, private static Status handleCaseCancelCanceled(
final Long actionId, final List<String> messages) { final DdiActionFeedback feedback, final Target target, final Long actionId, final List<String> messages) {
final Status status; final Status status;
log.error( log.error(
"Target reported cancel for a cancel which is not supported by the server (actionId: {}, controllerId: {}) as we got {} report.", "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()); actionId, target.getControllerId(), feedback.getStatus().getExecution());
status = Status.WARNING; status = Status.WARNING;
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX +
+ "Target reported cancel for a cancel which is not supported by the server."); "Target reported cancel for a cancel which is not supported by the server.");
return status; return status;
} }
@@ -596,8 +595,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
final String message; final String message;
if (range != null) { if (range != null) {
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads range " + range + " of: " message = RepositoryConstants.SERVER_MESSAGE_PREFIX +
+ request.getRequestURI(); "Target downloads range " + range + " of: " + request.getRequestURI();
} else { } else {
message = RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target downloads " + request.getRequestURI(); 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)); entityFactory.actionStatus().create(action.getId()).status(Status.DOWNLOAD).message(message));
} }
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId, private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId, final Long actionId) {
final Long actionId) {
final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId); final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
final List<String> messages = new ArrayList<>(); final List<String> messages = new ArrayList<>();
if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) { if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) {
@@ -625,43 +621,49 @@ public class DdiRootController implements DdiRootControllerRestApi {
final Status status; final Status status;
switch (feedback.getStatus().getExecution()) { switch (feedback.getStatus().getExecution()) {
case CANCELED: case CANCELED: {
log.debug("Controller confirmed cancel (actionId: {}, controllerId: {}) as we got {} report.", actionId, log.debug("Controller confirmed cancel (actionId: {}, controllerId: {}) as we got {} report.", actionId,
controllerId, feedback.getStatus().getExecution()); controllerId, feedback.getStatus().getExecution());
status = Status.CANCELED; status = Status.CANCELED;
addMessageIfEmpty("Target confirmed cancellation.", messages); addMessageIfEmpty("Target confirmed cancellation.", messages);
break; break;
case REJECTED: }
case REJECTED: {
log.info("Controller reported internal error (actionId: {}, controllerId: {}) as we got {} report.", log.info("Controller reported internal error (actionId: {}, controllerId: {}) as we got {} report.",
actionId, controllerId, feedback.getStatus().getExecution()); actionId, controllerId, feedback.getStatus().getExecution());
status = Status.WARNING; status = Status.WARNING;
addMessageIfEmpty("Target REJECTED update", messages); addMessageIfEmpty("Target REJECTED update", messages);
break; break;
case CLOSED: }
case CLOSED: {
status = handleClosedCase(feedback, controllerId, actionId, messages); status = handleClosedCase(feedback, controllerId, actionId, messages);
break; break;
case DOWNLOAD: }
case DOWNLOAD: {
log.debug("Controller confirmed status of download (actionId: {}, controllerId: {}) as we got {} report.", log.debug("Controller confirmed status of download (actionId: {}, controllerId: {}) as we got {} report.",
actionId, controllerId, feedback.getStatus().getExecution()); actionId, controllerId, feedback.getStatus().getExecution());
status = Status.DOWNLOAD; status = Status.DOWNLOAD;
addMessageIfEmpty("Target confirmed download start", messages); addMessageIfEmpty("Target confirmed download start", messages);
break; break;
case DOWNLOADED: }
case DOWNLOADED: {
log.debug("Controller confirmed download (actionId: {}, controllerId: {}) as we got {} report.", actionId, log.debug("Controller confirmed download (actionId: {}, controllerId: {}) as we got {} report.", actionId,
controllerId, feedback.getStatus().getExecution()); controllerId, feedback.getStatus().getExecution());
status = Status.DOWNLOADED; status = Status.DOWNLOADED;
addMessageIfEmpty("Target confirmed download finished", messages); addMessageIfEmpty("Target confirmed download finished", messages);
break; break;
default: }
default: {
status = handleDefaultCase(feedback, controllerId, actionId, messages); status = handleDefaultCase(feedback, controllerId, actionId, messages);
break; break;
}
} }
return actionStatusCreate.status(status).messages(messages); return actionStatusCreate.status(status).messages(messages);
} }
private Status handleDefaultCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId, private Status handleDefaultCase(
final List<String> messages) { final DdiActionFeedback feedback, final String controllerId, final Long actionId, final List<String> messages) {
final Status status; final Status status;
log.debug("Controller reported intermediate status (actionId: {}, controllerId: {}) as we got {} report.", log.debug("Controller reported intermediate status (actionId: {}, controllerId: {}) as we got {} report.",
actionId, controllerId, feedback.getStatus().getExecution()); actionId, controllerId, feedback.getStatus().getExecution());
@@ -670,8 +672,8 @@ public class DdiRootController implements DdiRootControllerRestApi {
return status; return status;
} }
private Status handleClosedCase(final DdiActionFeedback feedback, final String controllerId, final Long actionId, private Status handleClosedCase(
final List<String> messages) { final DdiActionFeedback feedback, final String controllerId, final Long actionId, final List<String> messages) {
final Status status; final Status status;
log.debug("Controller reported closed (actionId: {}, controllerId: {}) as we got {} report.", actionId, log.debug("Controller reported closed (actionId: {}, controllerId: {}) as we got {} report.", actionId,
controllerId, feedback.getStatus().getExecution()); 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, * If the action has a maintenance schedule defined but is no longer valid, cancel the action.
* cancel the action.
* *
* @param action is the {@link Action} to check. * @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, private DdiDeploymentBase generateDdiDeploymentBase(final Target target, final Action action, final Integer actionHistoryMessageCount) {
final Integer actionHistoryMessageCount) {
final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null); final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null);
final DdiDeployment ddiDeployment = generateDdiDeployment(target, action); final DdiDeployment ddiDeployment = generateDdiDeployment(target, action);
return new DdiDeploymentBase(Long.toString(action.getId()), ddiDeployment, actionHistory); return new DdiDeploymentBase(Long.toString(action.getId()), ddiDeployment, actionHistory);
} }
private DdiConfirmationBaseAction generateDdiConfirmationBase(final Target target, final Action action, private DdiConfirmationBaseAction generateDdiConfirmationBase(final Target target, final Action action, final Integer actionHistoryMessageCount) {
final Integer actionHistoryMessageCount) {
final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null); final DdiActionHistory actionHistory = generateDdiActionHistory(action, actionHistoryMessageCount).orElse(null);
final DdiDeployment ddiDeployment = generateDdiDeployment(target, action); final DdiDeployment ddiDeployment = generateDdiDeployment(target, action);
return new DdiConfirmationBaseAction(Long.toString(action.getId()), ddiDeployment, actionHistory); return new DdiConfirmationBaseAction(Long.toString(action.getId()), ddiDeployment, actionHistory);
} }
private DdiDeployment generateDdiDeployment(final Target target, final Action action) { 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()), systemManagement, new ServletServerHttpRequest(RequestResponseContextHolder.getHttpServletRequest()),
controllerManagement); controllerManagement);
final HandlingType downloadType = calculateDownloadType(action); final HandlingType downloadType = calculateDownloadType(action);
@@ -745,12 +745,13 @@ public class DdiRootController implements DdiRootControllerRestApi {
return new DdiDeployment(downloadType, updateType, chunks, maintenanceWindow); return new DdiDeployment(downloadType, updateType, chunks, maintenanceWindow);
} }
private Optional<DdiActionHistory> generateDdiActionHistory(final Action action, private Optional<DdiActionHistory> generateDdiActionHistory(final Action action, final Integer actionHistoryMessageCount) {
final Integer actionHistoryMessageCount) {
final List<String> actionHistoryMsgs = controllerManagement.getActionHistoryMessages(action.getId(), 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); : actionHistoryMessageCount);
return actionHistoryMsgs.isEmpty() ? Optional.empty() return actionHistoryMsgs.isEmpty()
? Optional.empty()
: Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs)); : Optional.of(new DdiActionHistory(action.getStatus().name(), actionHistoryMsgs));
} }
@@ -779,11 +780,9 @@ public class DdiRootController implements DdiRootControllerRestApi {
* @param response the response * @param response the response
* @param md5Hash of the artifact * @param md5Hash of the artifact
* @param filename as provided by the client * @param filename as provided by the client
* @return the response
* @throws IOException cannot write output stream * @throws IOException cannot write output stream
*/ */
private static void writeMD5FileResponse( private static void writeMD5FileResponse(final HttpServletResponse response, final String md5Hash, final String filename) throws IOException {
final HttpServletResponse response, final String md5Hash, final String filename) throws IOException {
if (md5Hash == null) { if (md5Hash == null) {
throw new IllegalArgumentException("MD5 hash must not be null"); throw new IllegalArgumentException("MD5 hash must not be null");
} }

View File

@@ -23,6 +23,7 @@ import java.io.StringWriter;
import java.time.Instant; import java.time.Instant;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Random;
import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator; 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.ResultMatcher;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ContextConfiguration(classes = { DdiApiConfiguration.class, RestConfiguration.class, @ContextConfiguration(
RepositoryApplicationConfiguration.class, TestConfiguration.class }) classes = { DdiApiConfiguration.class, RestConfiguration.class, RepositoryApplicationConfiguration.class, TestConfiguration.class })
@Import(TestChannelBinderConfiguration.class) @Import(TestChannelBinderConfiguration.class)
@TestPropertySource(locations = "classpath:/ddi-test.properties") @TestPropertySource(locations = "classpath:/ddi-test.properties")
public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrationTest { 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 HTTP_LOCALHOST = String.format("http://localhost:%s/", HTTP_PORT);
protected static final String CONTROLLER_BASE = "/{tenant}/controller/v1/{controllerId}"; protected static final String CONTROLLER_BASE = "/{tenant}/controller/v1/{controllerId}";
protected static final String SOFTWARE_MODULE_ARTIFACTS = CONTROLLER_BASE protected static final String SOFTWARE_MODULE_ARTIFACTS = CONTROLLER_BASE + "/softwaremodules/{softwareModuleId}/artifacts";
+ "/softwaremodules/{softwareModuleId}/artifacts";
protected static final String DEPLOYMENT_BASE = CONTROLLER_BASE + "/deploymentBase/{actionId}"; protected static final String DEPLOYMENT_BASE = CONTROLLER_BASE + "/deploymentBase/{actionId}";
protected static final String DEPLOYMENT_FEEDBACK = DEPLOYMENT_BASE + "/feedback"; protected static final String DEPLOYMENT_FEEDBACK = DEPLOYMENT_BASE + "/feedback";
protected static final String CANCEL_ACTION = CONTROLLER_BASE + "/cancelAction/{actionId}"; protected static final String CANCEL_ACTION = CONTROLLER_BASE + "/cancelAction/{actionId}";
@@ -83,7 +83,8 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
protected static final String CONFIRMATION_FEEDBACK = CONFIRMATION_BASE_ACTION + "/feedback"; protected static final String CONFIRMATION_FEEDBACK = CONFIRMATION_BASE_ACTION + "/feedback";
protected static final int ARTIFACT_SIZE = 5 * 1024; 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. * Convert JSON to a CBOR equivalent.
@@ -126,62 +127,69 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
} }
protected static ObjectMapper getMapper() { protected static ObjectMapper getMapper() {
return objectMapper; return OBJECT_MAPPER;
} }
protected ResultActions postDeploymentFeedback(final String controllerId, final Long actionId, final String content, protected ResultActions postDeploymentFeedback(final String controllerId, final Long actionId, final String content,
final ResultMatcher statusMatcher) throws Exception { final ResultMatcher statusMatcher) throws Exception {
return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(), return postDeploymentFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(), statusMatcher);
statusMatcher);
} }
protected ResultActions putInstalledBase(final String controllerId, final String content, protected ResultActions putInstalledBase(final String controllerId, final String content, final ResultMatcher statusMatcher)
final ResultMatcher statusMatcher) throws Exception { throws Exception {
return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId) return mvc.perform(put(INSTALLED_BASE_ROOT, tenantAware.getCurrentTenant(), controllerId)
.content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8)) .content(content.getBytes()).contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher); .andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher);
} }
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 { final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception {
return mvc return mvc
.perform(post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId) .perform(post(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId)
.content(content).contentType(mediaType).accept(mediaType)) .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 { final ResultMatcher statusMatcher) throws Exception {
return postCancelFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(), return postCancelFeedback(MediaType.APPLICATION_JSON_UTF8, controllerId, actionId, content.getBytes(), statusMatcher);
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 { final Long actionId, final byte[] content, final ResultMatcher statusMatcher) throws Exception {
return mvc return mvc
.perform(post(CANCEL_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId).content(content) .perform(post(CANCEL_FEEDBACK, tenantAware.getCurrentTenant(), controllerId, actionId).content(content)
.contentType(mediaType).accept(mediaType)) .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, protected ResultActions performGet(final String url, final MediaType mediaType, final ResultMatcher statusMatcher, final String... values)
final String... values) throws Exception { throws Exception {
return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType) return mvc.perform(MockMvcRequestBuilders.get(url, values).accept(mediaType)
.with(new RequestOnHawkbitDefaultPortPostProcessor())) .with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()).andExpect(statusMatcher) .andDo(MockMvcResultPrinter.print())
.andExpect(statusMatcher)
.andExpect(content().contentTypeCompatibleWith(mediaType)); .andExpect(content().contentTypeCompatibleWith(mediaType));
} }
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 DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
final Long osModuleId, final String downloadType, final String updateType) throws Exception { final Long osModuleId, final String downloadType, final String updateType) throws Exception {
final ResultActions resultActions = performGet(DEPLOYMENT_BASE, mediaType, status().isOk(), final ResultActions resultActions = performGet(DEPLOYMENT_BASE, mediaType, status().isOk(),
tenantAware.getCurrentTenant(), controllerId, actionId.toString()); tenantAware.getCurrentTenant(), controllerId, actionId.toString());
return verifyBasePayload("$.deployment", resultActions, controllerId, ds, artifact, artifactSignature, actionId, osModuleId, return verifyBasePayload(
downloadType, updateType); "$.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 DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
final Long osModuleId, final Action.ActionType actionType) throws Exception { final Long osModuleId, final Action.ActionType actionType) throws Exception {
return getAndVerifyDeploymentBasePayload(controllerId, mediaType, ds, artifact, artifactSignature, actionId, 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) { protected String installedBaseLink(final String controllerId, final String actionId) {
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" +
+ "/installedBase/" + actionId; controllerId + "/installedBase/" + actionId;
} }
protected String deploymentBaseLink(final String controllerId, final String actionId) { protected String deploymentBaseLink(final String controllerId, final String actionId) {
return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId return HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" +
+ "/deploymentBase/" + actionId; controllerId + "/deploymentBase/" + actionId;
} }
protected String getJsonRejectedCancelActionFeedback() throws JsonProcessingException { protected String getJsonRejectedCancelActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS, return getJsonActionFeedback(
Collections.singletonList("rejected")); DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("rejected"));
} }
protected String getJsonRejectedDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonRejectedDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("rejected")); DdiStatus.ExecutionStatus.REJECTED, DdiResult.FinalResult.NONE, Collections.singletonList("rejected"));
} }
protected String getJsonDownloadDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonDownloadDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.DOWNLOAD, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("download")); DdiStatus.ExecutionStatus.DOWNLOAD, DdiResult.FinalResult.NONE, Collections.singletonList("download"));
} }
protected String getJsonDownloadedDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonDownloadedDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.DOWNLOADED, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("download")); DdiStatus.ExecutionStatus.DOWNLOADED, DdiResult.FinalResult.NONE, Collections.singletonList("download"));
} }
protected String getJsonCanceledCancelActionFeedback() throws JsonProcessingException { protected String getJsonCanceledCancelActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.SUCCESS, return getJsonActionFeedback(
Collections.singletonList("canceled")); DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("canceled"));
} }
protected String getJsonCanceledDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonCanceledDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("canceled")); DdiStatus.ExecutionStatus.CANCELED, DdiResult.FinalResult.NONE, Collections.singletonList("canceled"));
} }
protected String getJsonScheduledCancelActionFeedback() throws JsonProcessingException { protected String getJsonScheduledCancelActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.SUCCESS, return getJsonActionFeedback(
Collections.singletonList("scheduled")); DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("scheduled"));
} }
protected String getJsonScheduledDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonScheduledDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("scheduled")); DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE, Collections.singletonList("scheduled"));
} }
protected String getJsonResumedCancelActionFeedback() throws JsonProcessingException { protected String getJsonResumedCancelActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.SUCCESS, return getJsonActionFeedback(
Collections.singletonList("resumed")); DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("resumed"));
} }
protected String getJsonResumedDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonResumedDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("resumed")); DdiStatus.ExecutionStatus.RESUMED, DdiResult.FinalResult.NONE, Collections.singletonList("resumed"));
} }
protected String getJsonProceedingCancelActionFeedback() throws JsonProcessingException { protected String getJsonProceedingCancelActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.SUCCESS, return getJsonActionFeedback(
Collections.singletonList("proceeding")); DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.SUCCESS, Collections.singletonList("proceeding"));
} }
protected String getJsonProceedingDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonProceedingDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("proceeding")); DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE, Collections.singletonList("proceeding"));
} }
protected String getJsonClosedCancelActionFeedback() throws JsonProcessingException { protected String getJsonClosedCancelActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, return getJsonActionFeedback(
Collections.singletonList("closed")); DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("closed"));
} }
protected String getJsonClosedDeploymentActionFeedback() throws JsonProcessingException { protected String getJsonClosedDeploymentActionFeedback() throws JsonProcessingException {
return getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, return getJsonActionFeedback(
Collections.singletonList("closed")); DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, Collections.singletonList("closed"));
} }
protected String getJsonActionFeedback(final DdiStatus.ExecutionStatus executionStatus, protected String getJsonActionFeedback(
final DdiResult.FinalResult finalResult) throws JsonProcessingException { final DdiStatus.ExecutionStatus executionStatus, final DdiResult.FinalResult finalResult) throws JsonProcessingException {
return getJsonActionFeedback(executionStatus, finalResult, return getJsonActionFeedback(
Collections.singletonList(RandomStringUtils.randomAlphanumeric(1000))); 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 List<String> messages) throws JsonProcessingException {
final DdiStatus ddiStatus = new DdiStatus(executionStatus, ddiResult, null, messages); 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 { final DdiResult.FinalResult finalResult, final List<String> messages) throws JsonProcessingException {
return getJsonActionFeedback(executionStatus, finalResult, null, messages); 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 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, final DdiStatus ddiStatus = new DdiStatus(executionStatus, new DdiResult(finalResult, new DdiProgress(2, 5)), code, messages);
messages); return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
return objectMapper.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 { 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 { 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 DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
final Long osModuleId, final String downloadType, final String updateType) throws Exception { final Long osModuleId, final String downloadType, final String updateType) throws Exception {
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()); 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); 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) { static void implicitLock(final DistributionSet set) {
((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1); ((JpaDistributionSet) set).setOptLockRevision(set.getOptLockRevision() + 1);
} }
@@ -330,7 +350,8 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
return "attempt"; 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 DistributionSet ds, final Artifact artifact, final Artifact artifactSignature, final Long actionId,
final Long osModuleId, final String downloadType, final String updateType) throws Exception { final Long osModuleId, final String downloadType, final String updateType) throws Exception {
return resultActions.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId)))) 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", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].hashes.sha256",
contains(artifact.getSha256Hash()))) contains(artifact.getSha256Hash())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + "/download")))
+ "/download")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0]._links.md5sum-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() "/softwaremodules/" + osModuleId + "/artifacts/" + artifact.getFilename() + "/download.MD5SUM")))
+ "/download.MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE))) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].size", contains(ARTIFACT_SIZE)))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].filename",
contains(artifactSignature.getFilename()))) contains(artifactSignature.getFilename())))
@@ -371,13 +390,11 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha256", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1].hashes.sha256",
contains(artifactSignature.getSha256Hash()))) contains(artifactSignature.getSha256Hash())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.download-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download")))
+ "/download")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[1]._links.md5sum-http.href",
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
+ "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() "/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download.MD5SUM")))
+ "/download.MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version", .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version",
contains(ds.findFirstModuleByType(appType).get().getVersion()))) contains(ds.findFirstModuleByType(appType).get().getVersion())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist()) .andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist())

View File

@@ -10,7 +10,7 @@
package org.eclipse.hawkbit.ddi.rest.resource; package org.eclipse.hawkbit.ddi.rest.resource;
import static org.assertj.core.api.Assertions.assertThat; import static org.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.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
@@ -24,6 +24,7 @@ import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
@@ -32,7 +33,6 @@ import java.util.TimeZone;
import io.qameta.allure.Description; import io.qameta.allure.Description;
import io.qameta.allure.Feature; import io.qameta.allure.Feature;
import io.qameta.allure.Story; import io.qameta.allure.Story;
import org.apache.commons.lang3.RandomUtils;
import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration; import org.eclipse.hawkbit.ddi.rest.resource.DdiArtifactDownloadTest.DownloadTestConfiguration;
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent; import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.model.Artifact; import org.eclipse.hawkbit.repository.model.Artifact;
@@ -74,30 +74,34 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
public void invalidRequestsOnArtifactResource() throws Exception { public void invalidRequestsOnArtifactResource() throws Exception {
// create target // create target
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
final List<Target> targets = Arrays.asList(target); final List<Target> targets = Collections.singletonList(target);
// create ds // create ds
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final int artifactSize = 5 * 1024; 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), final Artifact artifact = artifactManagement.create(new ArtifactUpload(
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize)); new ByteArrayInputStream(random), ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
assignDistributionSet(ds, targets); assignDistributionSet(ds, targets);
// no artifact available // no artifact available
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/123455", 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", 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 // SM does not exist
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/1234567890/artifacts/{filename}", 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", 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 // test now consistent data to test allowed methods
mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}", mvc.perform(get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{smId}/artifacts/{filename}",
@@ -163,34 +167,35 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// create target // create target
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
final List<Target> targets = Arrays.asList(target); final List<Target> targets = Collections.singletonList(target);
// create ds // create ds
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// create artifact // create artifact
final int artifactSize = (int) quotaManagement.getMaxArtifactSize(); 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), final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize)); ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
// download fails as artifact is not yet assigned // download fails as artifact is not yet assigned
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", 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 // now assign and download successful
assignDistributionSet(ds, targets); assignDistributionSet(ds, targets);
final MvcResult result = mvc.perform(get( final MvcResult result = mvc.perform(get(
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt())))) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename())) .andExpect(header().string("Content-Disposition", "attachment;filename=" + artifact.getFilename()))
.andReturn(); .andReturn();
assertTrue( assertArrayEquals(result.getResponse().getContentAsByteArray(), random,
Arrays.equals(result.getResponse().getContentAsByteArray(), random),
"The same file that was uploaded is expected when downloaded"); "The same file that was uploaded is expected when downloaded");
// download complete // download complete
@@ -209,7 +214,7 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
// create artifact // create artifact
final int artifactSize = 5 * 1024; final int artifactSize = 5 * 1024;
final byte random[] = RandomUtils.nextBytes(artifactSize); final byte[] random = nextBytes(artifactSize);
final Artifact artifact = artifactManagement.create( final Artifact artifact = artifactManagement.create(
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, artifactSize)); 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( final MvcResult result = mvc.perform(get(
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}.MD5SUM",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename())) tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), artifact.getFilename()))
.andExpect(status().isOk()).andExpect(header().string("Content-Disposition", .andExpect(status().isOk())
.andExpect(header().string("Content-Disposition",
"attachment;filename=" + artifact.getFilename() + ".MD5SUM")) "attachment;filename=" + artifact.getFilename() + ".MD5SUM"))
.andReturn(); .andReturn();
@@ -233,7 +239,7 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
public void rangeDownloadArtifact() throws Exception { public void rangeDownloadArtifact() throws Exception {
// create target // create target
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
final List<Target> targets = Arrays.asList(target); final List<Target> targets = Collections.singletonList(target);
// create ds // create ds
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
@@ -241,7 +247,7 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
final int resultLength = (int) quotaManagement.getMaxArtifactSize(); final int resultLength = (int) quotaManagement.getMaxArtifactSize();
// create artifact // create artifact
final byte random[] = RandomUtils.nextBytes(resultLength); final byte[] random = nextBytes(resultLength);
final Artifact artifact = artifactManagement.create( final Artifact artifact = artifactManagement.create(
new ArtifactUpload(new ByteArrayInputStream(random), getOsModule(ds), "file1", false, resultLength)); 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 // full file download with standard range request
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
for (int i = 0; i < resultLength / range; i++) { 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( final MvcResult result = mvc.perform(get(
"/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", "/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range", tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1").header("Range",
"bytes=" + rangeString)) "bytes=" + rangeString))
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt())))) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().longValue("Content-Length", range)) .andExpect(header().longValue("Content-Length", range))
.andExpect(header().string("Content-Range", "bytes " + rangeString + "/" + resultLength)) .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()); outputStream.write(result.getResponse().getContentAsByteArray());
} }
@@ -279,14 +287,16 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=-1000")) .header("Range", "bytes=-1000"))
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt())))) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().longValue("Content-Length", 1000)) .andExpect(header().longValue("Content-Length", 1000))
.andExpect(header().string("Content-Range", .andExpect(header().string("Content-Range",
"bytes " + (resultLength - 1000) + "-" + (resultLength - 1) + "/" + resultLength)) "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()) assertThat(result.getResponse().getContentAsByteArray())
.isEqualTo(Arrays.copyOfRange(random, resultLength - 1000, resultLength)); .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}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=1000-")) .header("Range", "bytes=1000-"))
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM)) .andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt())))) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().longValue("Content-Length", resultLength - 1000)) .andExpect(header().longValue("Content-Length", resultLength - 1000))
.andExpect(header().string("Content-Range", .andExpect(header().string("Content-Range",
"bytes " + 1000 + "-" + (resultLength - 1) + "/" + resultLength)) "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()) assertThat(result.getResponse().getContentAsByteArray())
.isEqualTo(Arrays.copyOfRange(random, 1000, resultLength)); .isEqualTo(Arrays.copyOfRange(random, 1000, resultLength));
@@ -325,11 +337,13 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}", get("/{tenant}/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",
tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1") tenantAware.getCurrentTenant(), target.getControllerId(), getOsModule(ds), "file1")
.header("Range", "bytes=0-9,10-19")) .header("Range", "bytes=0-9,10-19"))
.andExpect(status().isPartialContent()).andExpect(header().string("ETag", artifact.getSha1Hash())) .andExpect(status().isPartialContent())
.andExpect(header().string("ETag", artifact.getSha1Hash()))
.andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART")) .andExpect(content().contentType("multipart/byteranges; boundary=THIS_STRING_SEPARATES_MULTIPART"))
.andExpect(header().string("Accept-Ranges", "bytes")) .andExpect(header().string("Accept-Ranges", "bytes"))
.andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt())))) .andExpect(header().string("Last-Modified", dateFormat.format(new Date(artifact.getCreatedAt()))))
.andExpect(header().string("Content-Disposition", "attachment;filename=file1")).andReturn(); .andExpect(header().string("Content-Disposition", "attachment;filename=file1"))
.andReturn();
outputStream.reset(); outputStream.reset();
@@ -365,5 +379,4 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
} }
} }
}
}

View File

@@ -68,8 +68,10 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" .perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId(), tenantAware.getCurrentTenant()) + cancelAction.getId(), tenantAware.getCurrentTenant())
.accept(DdiRestConstants.MEDIA_TYPE_CBOR)) .accept(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andReturn().getResponse() .andExpect(status().isOk())
.andExpect(content().contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
.andReturn().getResponse()
.getContentAsByteArray(); .getContentAsByteArray();
assertThat(JsonPathUtils.<String> evaluate(cborToJson(result), "$.id")) assertThat(JsonPathUtils.<String> evaluate(cborToJson(result), "$.id"))
.isEqualTo(String.valueOf(cancelAction.getId())); .isEqualTo(String.valueOf(cancelAction.getId()));
@@ -81,7 +83,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(jsonToCbor(getJsonProceedingCancelActionFeedback())) .content(jsonToCbor(getJsonProceedingCancelActionFeedback()))
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR)) .contentType(DdiRestConstants.MEDIA_TYPE_CBOR).accept(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
} }
@Test @Test
@@ -102,7 +105,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
@@ -110,7 +114,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
mvc.perform( mvc.perform(
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId, get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId,
tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId)))) .andExpect(jsonPath("$.id", equalTo(String.valueOf(actionId))))
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
@@ -128,7 +133,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.NONE,
Collections.singletonList("message"))) Collections.singletonList("message")))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
// check database after test // check database after test
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get()) assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
@@ -152,8 +158,10 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
final long timeBeforeFirstPoll = System.currentTimeMillis(); final long timeBeforeFirstPoll = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON)).andDo(MockMvcResultPrinter.print()) TestdataFactory.DEFAULT_CONTROLLER_ID).accept(MediaTypes.HAL_JSON))
.andExpect(status().isOk()).andExpect(content().contentType(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("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/" startsWith("http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/"
@@ -181,7 +189,9 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
final long timeBefore2ndPoll = System.currentTimeMillis(); final long timeBefore2ndPoll = System.currentTimeMillis();
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) TestdataFactory.DEFAULT_CONTROLLER_ID))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
@@ -193,7 +203,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId())))) .andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId)))); .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) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) activeActionsByTarget = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
.getContent(); .getContent();
@@ -222,27 +234,32 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
// not allowed methods // not allowed methods
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1", mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print()) tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1", mvc.perform(put("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print()) tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1", mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/1",
tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print()) tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
// non existing target // non existing target
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
createCancelAction("34534543"); createCancelAction("34534543");
// wrong media type // wrong media type
mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant()) mvc.perform(get("/{tenant}/controller/v1/34534543/cancelAction/1", tenantAware.getCurrentTenant())
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_ATOM_XML))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotAcceptable()); .andExpect(status().isNotAcceptable());
} }
@@ -267,7 +284,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonProceedingCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
assertThat(countActionStatusAll()).isEqualTo(3); assertThat(countActionStatusAll()).isEqualTo(3);
@@ -276,7 +294,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonResumedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
assertThat(countActionStatusAll()).isEqualTo(4); assertThat(countActionStatusAll()).isEqualTo(4);
@@ -284,7 +303,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonScheduledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(5); assertThat(countActionStatusAll()).isEqualTo(5);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -294,7 +314,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonCanceledCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(6); assertThat(countActionStatusAll()).isEqualTo(6);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -307,7 +328,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonRejectedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(7); assertThat(countActionStatusAll()).isEqualTo(7);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
@@ -316,7 +338,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(8); assertThat(countActionStatusAll()).isEqualTo(8);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty(); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
} }
@@ -352,14 +375,17 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3); assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + cancelAction.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId())))) .andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId)))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId))));
assertThat(countActionStatusAll()).isEqualTo(6); assertThat(countActionStatusAll()).isEqualTo(6);
mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controllerId}", tenantAware.getCurrentTenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) TestdataFactory.DEFAULT_CONTROLLER_ID))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
@@ -371,7 +397,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(7); assertThat(countActionStatusAll()).isEqualTo(7);
// 1 update actions, 1 cancel actions // 1 update actions, 1 cancel actions
@@ -379,14 +406,17 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3); assertThat(deploymentManagement.countActionsByTarget(savedTarget.getControllerId())).isEqualTo(3);
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + cancelAction2.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId())))) .andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction2.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId2)))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId2))));
assertThat(countActionStatusAll()).isEqualTo(8); assertThat(countActionStatusAll()).isEqualTo(8);
mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(), mvc.perform(get("/{tenant}/controller/v1/{controller}", tenantAware.getCurrentTenant(),
TestdataFactory.DEFAULT_CONTROLLER_ID)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) TestdataFactory.DEFAULT_CONTROLLER_ID))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.cancelAction.href", .andExpect(jsonPath("$._links.cancelAction.href",
@@ -398,7 +428,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction2.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(9); assertThat(countActionStatusAll()).isEqualTo(9);
assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get()) assertThat(deploymentManagement.getAssignedDistributionSet(TestdataFactory.DEFAULT_CONTROLLER_ID).get())
@@ -406,7 +437,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
mvc.perform( mvc.perform(
get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3, get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/" + actionId3,
tenantAware.getCurrentTenant())) tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(10); assertThat(countActionStatusAll()).isEqualTo(10);
// 1 update actions, 0 cancel actions // 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/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON)) + cancelAction3.getId(), tenantAware.getCurrentTenant()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId())))) .andExpect(jsonPath("$.id", equalTo(String.valueOf(cancelAction3.getId()))))
.andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId3)))); .andExpect(jsonPath("$.cancelAction.stopId", equalTo(String.valueOf(actionId3))));
@@ -433,7 +466,8 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction3.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(countActionStatusAll()).isEqualTo(13); assertThat(countActionStatusAll()).isEqualTo(13);
// final status // final status
@@ -480,49 +514,57 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(delete("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(get("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
// bad content type // bad content type
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_ATOM_XML)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType());
// bad body // bad body
String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}"; String invalidFeedback = "{\"status\":{\"execution\":\"546456456\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"none\"]}}";
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
// non existing target // non existing target
mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback", mvc.perform(post("/{tenant}/controller/v1/12345/cancelAction/" + cancelAction.getId() + "/feedback",
tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback()) tenantAware.getCurrentTenant()).content(getJsonClosedCancelActionFeedback())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
// invalid action // invalid action
invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}"; invalidFeedback = "{\"id\":\"sdfsdfsdfs\",\"status\":{\"execution\":\"closed\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}";
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()).content(invalidFeedback)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
// finaly, get it right :) // finaly, get it right :)
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/" mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant()) + cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON) .content(getJsonClosedCancelActionFeedback()).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
} }
private Action createCancelAction(final String targetid) { private Action createCancelAction(final String targetid) {

View File

@@ -52,10 +52,10 @@ import org.springframework.test.context.ActiveProfiles;
@Story("Config Data Resource") @Story("Config Data Resource")
class DdiConfigDataTest extends AbstractDDiApiIntegrationTest { class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
public static final String TARGET1_ID = "4717"; private static final String TARGET1_ID = "4717";
public static final String TARGET1_CONFIGDATA_PATH = "/{tenant}/controller/v1/" + TARGET1_ID + "/configData"; private static final String TARGET1_CONFIG_DATA_PATH = "/{tenant}/controller/v1/" + TARGET1_ID + "/configData";
public static final String TARGET2_ID = "4718"; private static final String TARGET2_ID = "4718";
public static final String TARGET2_CONFIGDATA_PATH = "/{tenant}/controller/v1/" + TARGET2_ID + "/configData"; private static final String TARGET2_CONFIG_DATA_PATH = "/{tenant}/controller/v1/" + TARGET2_ID + "/configData";
@Test @Test
@Description("Verify that config data can be uploaded as CBOR") @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<>(); final Map<String, String> attributes = new HashMap<>();
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID); attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
.content(jsonToCbor(JsonBuilder.configData(attributes).toString())) .content(jsonToCbor(JsonBuilder.configData(attributes).toString()))
.contentType(DdiRestConstants.MEDIA_TYPE_CBOR)).andDo(MockMvcResultPrinter.print()) .contentType(DdiRestConstants.MEDIA_TYPE_CBOR))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes); assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
} }
@Test @Test
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " @Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " +
+ "are requested only once from the device.") "are requested only once from the device.")
@SuppressWarnings("squid:S2925") @SuppressWarnings("squid:S2925")
void requestConfigDataIfEmpty() throws Exception { void requestConfigDataIfEmpty() throws Exception {
final Target savedTarget = testdataFactory.createTarget("4712"); final Target savedTarget = testdataFactory.createTarget("4712");
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform( mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.configData.href", equalTo( .andExpect(jsonPath("$._links.configData.href", equalTo(
"http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData"))); "http://localhost/" + tenantAware.getCurrentTenant() + "/controller/v1/4712/configData")));
Thread.sleep(1); // is required: otherwise processing the next line is Thread.sleep(1); // is required: otherwise processing the next line is
// often too fast and // often too fast and // the following assert will fail
// the following assert will fail
assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new) assertThat(targetManagement.getByControllerID("4712").orElseThrow(NoSuchElementException::new)
.getLastTargetQuery()) .getLastTargetQuery())
.isLessThanOrEqualTo(System.currentTimeMillis()); .isLessThanOrEqualTo(System.currentTimeMillis());
@@ -97,26 +97,23 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
.getLastTargetQuery()) .getLastTargetQuery())
.isGreaterThanOrEqualTo(current); .isGreaterThanOrEqualTo(current);
final Map<String, String> attributes = new HashMap<>(1);
attributes.put("dsafsdf", "sdsds");
final Target updateControllerAttributes = controllerManagement 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 // request controller attributes need to be false because we don't want
// to request the controller attributes again // to request the controller attributes again
assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse(); assertThat(updateControllerAttributes.isRequestControllerAttributes()).isFalse();
mvc.perform( mvc.perform(get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON))
get("/{tenant}/controller/v1/4712", tenantAware.getCurrentTenant()).accept(MediaTypes.HAL_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.configData.href").doesNotExist()); .andExpect(jsonPath("$._links.configData.href").doesNotExist());
} }
@Test @Test
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " @Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " +
+ "can be uploaded correctly by the controller.") "can be uploaded correctly by the controller.")
void putConfigData() throws Exception { void putConfigData() throws Exception {
testdataFactory.createTarget(TARGET1_ID); testdataFactory.createTarget(TARGET1_ID);
@@ -124,38 +121,38 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
final Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = new HashMap<>();
attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID); attributes.put(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_VALID);
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes); assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
// update // update
attributes.put("sdsds", "123412"); attributes.put("sdsds", "123412");
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes); assertThat(targetManagement.getControllerAttributes(TARGET1_ID)).isEqualTo(attributes);
} }
@Test @Test
@Description("We verify that the config data (i.e. device attributes like serial number, hardware revision etc.) " @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.") "upload quota is enforced to protect the server from malicious attempts.")
void putTooMuchConfigData() throws Exception { void putTooMuchConfigData() throws Exception {
testdataFactory.createTarget(TARGET1_ID); testdataFactory.createTarget(TARGET1_ID);
// initial // initial
Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = new HashMap<>();
for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) { for (int i = 0; i < quotaManagement.getMaxAttributeEntriesPerTarget(); i++) {
attributes.put("dsafsdf" + i, "sdsds" + 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)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk()); .andExpect(status().isOk());
attributes = new HashMap<>(); mvc.perform(put(TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
attributes.put("on too many", "sdsds"); .content(JsonBuilder.configData(Map.of("on too many", "sdsds")).toString()).contentType(MediaType.APPLICATION_JSON))
mvc.perform(put(TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isForbidden()) .andExpect(status().isForbidden())
.andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName()))) .andExpect(jsonPath("$.exceptionClass", equalTo(AssignmentQuotaExceededException.class.getName())))
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey()))); .andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
@@ -174,27 +171,31 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
andExpect(status().isMethodNotAllowed()); andExpect(status().isMethodNotAllowed());
mvc.perform(get("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())) 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())) 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 // bad content type
final Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = Map.of("dsafsdf", "sdsds");
attributes.put("dsafsdf", "sdsds");
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()) mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isUnsupportedMediaType()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType());
// non existing target // non existing target
mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant()) mvc.perform(put("/{tenant}/controller/v1/456456/configData", tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
// bad body // bad body
mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant()) mvc.perform(put("/{tenant}/controller/v1/4712/configData", tenantAware.getCurrentTenant())
.content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON)) .content("{\"id\": \"51659181\"}").contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
} }
@Test @Test
@@ -209,7 +210,6 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).") @Description("Verify that config data (device attributes) can be updated by the controller using different update modes (merge, replace, remove).")
void putConfigDataWithDifferentUpdateModes() throws Exception { void putConfigDataWithDifferentUpdateModes() throws Exception {
// create a target // create a target
testdataFactory.createTarget(TARGET1_ID); testdataFactory.createTarget(TARGET1_ID);
@@ -232,7 +232,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
@Step @Step
private void putAndVerifyConfigDataWithKeyTooLong() throws Exception { private void putAndVerifyConfigDataWithKeyTooLong() throws Exception {
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_TOO_LONG, ATTRIBUTE_VALUE_VALID); 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)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName()))) .andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
@@ -242,7 +242,7 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
@Step @Step
private void putAndVerifyConfigDataWithValueTooLong() throws Exception { private void putAndVerifyConfigDataWithValueTooLong() throws Exception {
final Map<String, String> attributes = Collections.singletonMap(ATTRIBUTE_KEY_VALID, ATTRIBUTE_VALUE_TOO_LONG); 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)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isBadRequest()) .andExpect(status().isBadRequest())
.andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName()))) .andExpect(jsonPath("$.exceptionClass", equalTo(InvalidTargetAttributeException.class.getName())))
@@ -252,14 +252,15 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
@Step @Step
private void putConfigDataWithInvalidUpdateMode() throws Exception { private void putConfigDataWithInvalidUpdateMode() throws Exception {
// create some attriutes // create some attriutes
final Map<String, String> attributes = new HashMap<>(); final Map<String, String> attributes = Map.of(
attributes.put("k0", "v0"); "k0", "v0",
attributes.put("k1", "v1"); "k1", "v1");
// use an invalid update mode // 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()) .content(JsonBuilder.configData(attributes, "KJHGKJHGKJHG").toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest()); .andExpect(status().isBadRequest());
} }
@@ -269,13 +270,14 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
final int previousSize = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID).size(); final int previousSize = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID).size();
// update the attributes using update mode REMOVE // update the attributes using update mode REMOVE
final Map<String, String> removeAttributes = new HashMap<>(); final Map<String, String> removeAttributes = Map.of(
removeAttributes.put("k1", "foo"); "k1", "foo",
removeAttributes.put("k3", "bar"); "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()) .content(JsonBuilder.configData(removeAttributes, "remove").toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
// verify attribute removal // verify attribute removal
@@ -287,74 +289,68 @@ class DdiConfigDataTest extends AbstractDDiApiIntegrationTest {
} }
@Step @Step
private void putConfigDataWithUpdateModeMerge() private void putConfigDataWithUpdateModeMerge() throws Exception {
throws Exception {
// get the current attributes // get the current attributes
final Map<String, String> attributes = new HashMap<>( final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
// update the attributes using update mode MERGE // update the attributes using update mode MERGE
final Map<String, String> mergeAttributes = new HashMap<>(); final Map<String, String> mergeAttributes = Map.of(
mergeAttributes.put("k1", "v1_modified_again"); "k1", "v1_modified_again",
mergeAttributes.put("k4", "v4"); "k4", "v4");
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(mergeAttributes, "merge").toString()) .content(JsonBuilder.configData(mergeAttributes, "merge").toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
// verify attribute merge // verify attribute merge
final Map<String, String> updatedAttributes = targetManagement final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
assertThat(updatedAttributes).hasSize(4); assertThat(updatedAttributes).hasSize(4);
assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes); assertThat(updatedAttributes).containsAllEntriesOf(mergeAttributes);
assertThat(updatedAttributes).containsEntry("k1", "v1_modified_again"); assertThat(updatedAttributes).containsEntry("k1", "v1_modified_again");
attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey); attributes.keySet().forEach(assertThat(updatedAttributes)::containsKey);
} }
@Step @Step
private void putConfigDataWithUpdateModeReplace() private void putConfigDataWithUpdateModeReplace() throws Exception {
throws Exception {
// get the current attributes // get the current attributes
final Map<String, String> attributes = new HashMap<>( final Map<String, String> attributes = new HashMap<>(targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID));
// update the attributes using update mode REPLACE // update the attributes using update mode REPLACE
final Map<String, String> replacementAttributes = new HashMap<>(); final Map<String, String> replacementAttributes = Map.of(
replacementAttributes.put("k1", "v1_modified"); "k1", "v1_modified",
replacementAttributes.put("k2", "v2"); "k2", "v2",
replacementAttributes.put("k3", "v3"); "k3", "v3");
mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIGDATA_PATH, tenantAware.getCurrentTenant()) mvc.perform(put(DdiConfigDataTest.TARGET1_CONFIG_DATA_PATH, tenantAware.getCurrentTenant())
.content(JsonBuilder.configData(replacementAttributes, "replace").toString()) .content(JsonBuilder.configData(replacementAttributes, "replace").toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
// verify attribute replacement // verify attribute replacement
final Map<String, String> updatedAttributes = targetManagement final Map<String, String> updatedAttributes = targetManagement.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
assertThat(updatedAttributes).hasSize(replacementAttributes.size()); assertThat(updatedAttributes).hasSize(replacementAttributes.size());
assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes); assertThat(updatedAttributes).containsAllEntriesOf(replacementAttributes);
assertThat(updatedAttributes).containsEntry("k1", "v1_modified"); assertThat(updatedAttributes).containsEntry("k1", "v1_modified");
attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain); attributes.entrySet().forEach(assertThat(updatedAttributes)::doesNotContain);
} }
@Step @Step
private void putConfigDataWithoutUpdateMode() private void putConfigDataWithoutUpdateMode() throws Exception {
throws Exception { // create some attributes
// create some attriutes final Map<String, String> attributes = Map.of(
final Map<String, String> attributes = new HashMap<>(); "k0", "v0",
attributes.put("k0", "v0"); "k1", "v1");
attributes.put("k1", "v1");
// set the initial attributes // 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)) .content(JsonBuilder.configData(attributes).toString()).contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
// verify the initial parameters // verify the initial parameters
final Map<String, String> updatedAttributes = targetManagement final Map<String, String> updatedAttributes = targetManagement
.getControllerAttributes(DdiConfigDataTest.TARGET1_ID); .getControllerAttributes(DdiConfigDataTest.TARGET1_ID);
assertThat(updatedAttributes).containsExactlyEntriesOf(attributes); assertThat(updatedAttributes).containsExactlyEntriesOf(attributes);
} }
} }

View File

@@ -29,7 +29,6 @@ import io.qameta.allure.Feature;
import io.qameta.allure.Step; import io.qameta.allure.Step;
import io.qameta.allure.Story; import io.qameta.allure.Story;
import org.apache.commons.lang3.RandomStringUtils; 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.DdiActivateAutoConfirmation;
import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback; import org.eclipse.hawkbit.ddi.json.model.DdiConfirmationFeedback;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
@@ -80,44 +79,41 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
// Prepare test data // Prepare test data
final DistributionSet ds = testdataFactory.createDistributionSet("", true); final DistributionSet ds = testdataFactory.createDistributionSet("", true);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", 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);
"test1", ARTIFACT_SIZE); final Artifact artifactSignature = testdataFactory.createArtifact(
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
final Target savedTarget = testdataFactory.createTarget(DdiConfirmationBaseTest.DEFAULT_CONTROLLER_ID); final Target savedTarget = testdataFactory.createTarget(DdiConfirmationBaseTest.DEFAULT_CONTROLLER_ID);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty(); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).isEmpty();
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), final List<Target> targetsAssignedToDs = assignDistributionSet(
Action.ActionType.FORCED).getAssignedEntity().stream().map(Action::getTarget) ds.getId(), savedTarget.getControllerId(), Action.ActionType.FORCED).getAssignedEntity().stream()
.map(Action::getTarget)
.collect(Collectors.toList()); .collect(Collectors.toList());
implicitLock(ds); implicitLock(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1); assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
assignDistributionSet(ds2, targetsAssignedToDs).getAssignedEntity(); assignDistributionSet(ds2, targetsAssignedToDs).getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2); assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(uaction.getDistributionSet()).isEqualTo(ds); assertThat(uaction.getDistributionSet()).isEqualTo(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
// Run test // Run test
final long current = System.currentTimeMillis(); 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()); tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, uaction.getId());
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID)
DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.confirmationBase.href", .andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)))
containsString(expectedConfirmationBaseLink)))
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
@@ -128,7 +124,8 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get(); 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(), artifactSignature, action.getId(),
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced"); findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
@@ -151,8 +148,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(distributionSet.getId(), target.getName()); assignDistributionSet(distributionSet.getId(), target.getName());
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
.getContent().get(0);
// get confirmation base // get confirmation base
performGet(CONFIRMATION_BASE_ACTION, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), 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())); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
final String controllerId = 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() mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.get(0); .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()); .andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
} }
@@ -197,20 +192,21 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String controllerId = savedTarget.getControllerId(); final String controllerId = savedTarget.getControllerId();
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent() final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
.get(0); mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
mvc.perform( .andExpect(status().isOk())
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.confirmationBase.href").exists())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
} }
@@ -225,8 +221,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String controllerId = savedTarget.getControllerId(); final String controllerId = savedTarget.getControllerId();
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent() final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
.get(0);
// disable confirmation flow // disable confirmation flow
disableConfirmationFlow(); disableConfirmationFlow();
@@ -235,15 +230,17 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId()); verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId());
// verify confirmation endpoint is still accessible // verify confirmation endpoint is still accessible
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 20, sendConfirmationFeedback(
"Action denied message.").andExpect(status().isOk()); savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 20, "Action denied message.")
.andExpect(status().isOk());
// confirmation base should still be exposed // confirmation base should still be exposed
verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId()); verifyActionInConfirmationBaseState(savedTarget.getControllerId(), savedAction.getId());
// verify confirmation endpoint is still accessible // verify confirmation endpoint is still accessible
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10, sendConfirmationFeedback(
"Action confirmed message.").andExpect(status().isOk()); savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10, "Action confirmed message.")
.andExpect(status().isOk());
// assert deployment link is exposed to the target // assert deployment link is exposed to the target
verifyActionInDeploymentBaseState(controllerId, savedAction.getId()); verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
@@ -251,7 +248,8 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Controller sends a confirmed action state.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@@ -273,8 +271,9 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent() final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent()
.get(0); .get(0);
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10, sendConfirmationFeedback(
"Action confirmed message.").andExpect(status().isOk()); savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, 10, "Action confirmed message.")
.andExpect(status().isOk());
// assert deployment link is exposed to the target // assert deployment link is exposed to the target
verifyActionInDeploymentBaseState(controllerId, savedAction.getId()); verifyActionInDeploymentBaseState(controllerId, savedAction.getId());
@@ -287,18 +286,19 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
final String controllerId = testdataFactory.createTarget("989").getControllerId(); final String controllerId = testdataFactory.createTarget("989").getControllerId();
assignDistributionSet(testdataFactory.createDistributionSet("").getId(), controllerId); assignDistributionSet(testdataFactory.createDistributionSet("").getId(), controllerId);
final long actionId = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0) final long actionId = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0).getId();
.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); 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); tenantAware.getCurrentTenant(), controllerId);
mvc.perform( mvc.perform(get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE))) .andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.FALSE)))
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(confirmationBaseActionLink))) .andExpect(jsonPath("$._links.confirmationBase.href", containsString(confirmationBaseActionLink)))
.andExpect(jsonPath("$._links.activateAutoConfirm.href", containsString(activateAutoConfLink))) .andExpect(jsonPath("$._links.activateAutoConfirm.href", containsString(activateAutoConfLink)))
@@ -308,23 +308,24 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
@ParameterizedTest @ParameterizedTest
@MethodSource("possibleActiveStates") @MethodSource("possibleActiveStates")
@Description("Confirmation base provides right values if auto-confirm is active.") @Description("Confirmation base provides right values if auto-confirm is active.")
void getConfirmationBaseProvidesAutoConfirmStatusActive(final String initiator, final String remark) void getConfirmationBaseProvidesAutoConfirmStatusActive(final String initiator, final String remark) throws Exception {
throws Exception {
final String controllerId = testdataFactory.createTarget("988").getControllerId(); final String controllerId = testdataFactory.createTarget("988").getControllerId();
confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark); confirmationManagement.activateAutoConfirmation(controllerId, initiator, remark);
final String deactivateAutoConfLink = String.format( final String deactivateAutoConfLink = String.format(
"/%s/controller/v1/%s/confirmationBase/deactivateAutoConfirm", tenantAware.getCurrentTenant(), "/%s/controller/v1/%s/confirmationBase/deactivateAutoConfirm",
controllerId); tenantAware.getCurrentTenant(), controllerId);
mvc.perform( mvc.perform(get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
get(CONFIRMATION_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE))) .andExpect(jsonPath("autoConfirm.active", equalTo(Boolean.TRUE)))
.andExpect(initiator == null ? jsonPath("autoConfirm.initiator").doesNotExist() .andExpect(initiator == null
? jsonPath("autoConfirm.initiator").doesNotExist()
: jsonPath("autoConfirm.initiator", equalTo(initiator))) : jsonPath("autoConfirm.initiator", equalTo(initiator)))
.andExpect(remark == null ? jsonPath("autoConfirm.remark").doesNotExist() .andExpect(remark == null
? jsonPath("autoConfirm.remark").doesNotExist()
: jsonPath("autoConfirm.remark", equalTo(remark))) : jsonPath("autoConfirm.remark", equalTo(remark)))
.andExpect(jsonPath("$._links.deactivateAutoConfirm.href", containsString(deactivateAutoConfLink))) .andExpect(jsonPath("$._links.deactivateAutoConfirm.href", containsString(deactivateAutoConfLink)))
.andExpect(jsonPath("$._links.activateAutoConfirm").doesNotExist()); .andExpect(jsonPath("$._links.activateAutoConfirm").doesNotExist());
@@ -340,7 +341,8 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
mvc.perform(post(ACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId) mvc.perform(post(ACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId)
.content(getMapper().writeValueAsString(body)).contentType(MediaType.APPLICATION_JSON_UTF8)) .content(getMapper().writeValueAsString(body)).contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
assertThat(confirmationManagement.getStatus(controllerId)).hasValueSatisfying(status -> { assertThat(confirmationManagement.getStatus(controllerId)).hasValueSatisfying(status -> {
assertThat(status.getInitiator()).isEqualTo(initiator); assertThat(status.getInitiator()).isEqualTo(initiator);
@@ -357,14 +359,16 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
confirmationManagement.activateAutoConfirmation(controllerId, null, null); confirmationManagement.activateAutoConfirmation(controllerId, null, null);
mvc.perform(post(DEACTIVATE_AUTO_CONFIRM, tenantAware.getCurrentTenant(), controllerId)) 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(); assertThat(confirmationManagement.getStatus(controllerId)).isEmpty();
} }
@Test @Test
@Description("Controller sends a denied action state.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@@ -383,30 +387,33 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
Target savedTarget = testdataFactory.createTarget("989"); Target savedTarget = testdataFactory.createTarget("989");
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId())); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
String controllerId = savedTarget.getControllerId(); String controllerId = savedTarget.getControllerId();
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent() final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
.get(0);
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 10, sendConfirmationFeedback(
"Action denied message.").andExpect(status().isOk()); savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.DENIED, 10, "Action denied message.")
.andExpect(status().isOk());
// asserts that deployment link is not available // 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()); tenantAware.getCurrentTenant(), controllerId, savedAction.getId());
mvc.perform( mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
.andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink))); .andExpect(jsonPath("$._links.confirmationBase.href", containsString(expectedConfirmationBaseLink)));
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), controllerId, savedAction.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
} }
@Test @Test
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.") @Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@@ -422,71 +429,80 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
Target savedTarget = testdataFactory.createTarget("990"); Target savedTarget = testdataFactory.createTarget("990");
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId())); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
String controllerId = savedTarget.getControllerId(); final String controllerId = savedTarget.getControllerId();
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent() final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, controllerId).getContent().get(0);
.get(0); final String confirmedMessage = "Action confirmed message.";
final String CONFIRMED_MESSAGE = "Action confirmed message."; final Integer confirmedCode = 10;
final Integer CONFIRMED_CODE = 10; sendConfirmationFeedback(
sendConfirmationFeedback(savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, savedTarget, savedAction, DdiConfirmationFeedback.Confirmation.CONFIRMED, confirmedCode, confirmedMessage)
CONFIRMED_CODE, CONFIRMED_MESSAGE).andExpect(status().isOk()); .andExpect(status().isOk());
// confirmationBase not available in RUNNING state anymore // confirmationBase not available in RUNNING state anymore
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), savedTarget.getControllerId(), mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound());
// assert confirmed message against deploymentBase endpoint // assert confirmed message against deploymentBase endpoint
// this call will update the action due to retrieved action status update // this call will update the action due to retrieved action status update
mvc.perform( mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(),
get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), savedTarget.getControllerId(), savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
savedAction.getId()).contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString(CONFIRMED_MESSAGE)))) .andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString(confirmedMessage))))
.andExpect(jsonPath("$.actionHistory.messages", .andExpect(jsonPath("$.actionHistory.messages",
hasItem(containsString(String.format(CONFIRMATION_CODE_MSG_PREFIX, CONFIRMED_CODE))))); hasItem(containsString(String.format(CONFIRMATION_CODE_MSG_PREFIX, confirmedCode)))));
} }
private static Stream<Arguments> possibleActiveStates() { private static Stream<Arguments> possibleActiveStates() {
return Stream.of(Arguments.of("someInitiator", "someRemark"), Arguments.of(null, "someRemark"), return Stream.of(
Arguments.of("someInitiator", null), Arguments.of(null, null)); Arguments.of("someInitiator", "someRemark"),
Arguments.of(null, "someRemark"),
Arguments.of("someInitiator", null),
Arguments.of(null, null));
} }
@Step @Step
private void verifyActionInDeploymentBaseState(final String controllerId, final long actionId) throws Exception { 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); tenantAware.getCurrentTenant(), controllerId, actionId);
mvc.perform( mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink))) .andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)))
.andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist()); .andExpect(jsonPath("$._links.confirmationBase.href").doesNotExist());
// assert that deployment endpoint is working // assert that deployment endpoint is working
mvc.perform(get(expectedDeploymentBaseLink).accept(MediaType.APPLICATION_JSON)) mvc.perform(get(expectedDeploymentBaseLink).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
} }
@Step @Step
private void verifyActionInConfirmationBaseState(final String controllerId, final long actionId) throws Exception { private void verifyActionInConfirmationBaseState(final String controllerId, final long actionId) throws Exception {
mvc.perform( mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andExpect(status().isOk())
.andExpect(jsonPath("$._links.confirmationBase.href").exists()) .andExpect(jsonPath("$._links.confirmationBase.href").exists())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
mvc.perform(get(CONFIRMATION_BASE_ACTION, tenantAware.getCurrentTenant(), controllerId, actionId) 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) 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()); .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 { final DdiConfirmationFeedback.Confirmation confirmation, Integer code, String message) throws Exception {
if (message == null) { if (message == null) {
message = RandomStringUtils.randomAlphanumeric(1000); message = RandomStringUtils.randomAlphanumeric(1000);
} }

View File

@@ -30,7 +30,6 @@ import com.jayway.jsonpath.JsonPath;
import io.qameta.allure.Description; import io.qameta.allure.Description;
import io.qameta.allure.Feature; import io.qameta.allure.Feature;
import io.qameta.allure.Story; import io.qameta.allure.Story;
import org.apache.commons.lang3.RandomUtils;
import org.assertj.core.api.Condition; import org.assertj.core.api.Condition;
import org.eclipse.hawkbit.ddi.json.model.DdiResult; import org.eclipse.hawkbit.ddi.json.model.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
@@ -94,8 +93,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
testdataFactory.createArtifacts(softwareModuleId); testdataFactory.createArtifacts(softwareModuleId);
assignDistributionSet(distributionSet.getId(), target.getName()); assignDistributionSet(distributionSet.getId(), target.getName());
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
.getContent().get(0);
// get deployment base // get deployment base
performGet(DEPLOYMENT_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(), performGet(DEPLOYMENT_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(),
@@ -107,17 +105,17 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
String.valueOf(softwareModuleId)); String.valueOf(softwareModuleId));
final byte[] feedback = jsonToCbor(getJsonProceedingDeploymentActionFeedback()); final byte[] feedback = jsonToCbor(getJsonProceedingDeploymentActionFeedback());
postDeploymentFeedback(
postDeploymentFeedback(MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), target.getControllerId(), MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), target.getControllerId(), action.getId(), feedback,
action.getId(), feedback, status().isOk()); status().isOk());
} }
@Test @Test
@Description("Ensures that artifacts are not found, when software module does not exists.") @Description("Ensures that artifacts are not found, when software module does not exists.")
void artifactsNotFound() throws Exception { void artifactsNotFound() throws Exception {
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isNotFound(), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isNotFound(), tenantAware.getCurrentTenant(),
tenantAware.getCurrentTenant(), target.getControllerId(), "1"); target.getControllerId(), "1");
} }
@Test @Test
@@ -131,8 +129,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(distributionSet.getId(), target.getName()); assignDistributionSet(distributionSet.getId(), target.getName());
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString()) target.getControllerId(), softwareModuleId.toString())
.andExpect(jsonPath("$", hasSize(3))) .andExpect(jsonPath("$", hasSize(3)))
.andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1))) .andExpect(jsonPath("$.[?(@.filename=='filename0')]", hasSize(1)))
.andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1))) .andExpect(jsonPath("$.[?(@.filename=='filename1')]", hasSize(1)))
@@ -145,36 +143,37 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Prepare test data // Prepare test data
final DistributionSet ds = testdataFactory.createDistributionSet("", true); final DistributionSet ds = testdataFactory.createDistributionSet("", true);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", 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);
"test1", ARTIFACT_SIZE); final Artifact artifactSignature = testdataFactory.createArtifact(
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
final Target savedTarget = createTargetAndAssertNoActiveActions(); final Target savedTarget = createTargetAndAssertNoActiveActions();
final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), final List<Target> targetsAssignedToDs = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), ActionType.FORCED)
ActionType.FORCED).getAssignedEntity().stream().map(Action::getTarget).collect(Collectors.toList()); .getAssignedEntity().stream()
.map(Action::getTarget)
.collect(Collectors.toList());
implicitLock(ds); implicitLock(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1); assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
assignDistributionSet(ds2, targetsAssignedToDs).getAssignedEntity(); assignDistributionSet(ds2, targetsAssignedToDs).getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2); assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(uaction.getDistributionSet()).isEqualTo(ds); assertThat(uaction.getDistributionSet()).isEqualTo(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath(
"$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current); .isGreaterThanOrEqualTo(current);
@@ -183,7 +182,6 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(), artifactSignature, action.getId(),
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced"); findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
@@ -207,14 +205,16 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
ActionType.TIMEFORCED, System.currentTimeMillis() + 2_000)); ActionType.TIMEFORCED, System.currentTimeMillis() + 2_000));
MvcResult mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), 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") final String urlBeforeSwitch = JsonPath.compile("_links.deploymentBase.href")
.read(mvcResult.getResponse().getContentAsString()).toString(); .read(mvcResult.getResponse().getContentAsString()).toString();
// Time is not yet over, so we should see the same URL // Time is not yet over, so we should see the same URL
mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), 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()) assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
.toString()).isEqualTo(urlBeforeSwitch) .toString()).isEqualTo(urlBeforeSwitch)
.startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, actionId.toString())); .startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, actionId.toString()));
@@ -223,7 +223,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
TimeUnit.MILLISECONDS.sleep(2_000); TimeUnit.MILLISECONDS.sleep(2_000);
mvcResult = performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), 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()) assertThat(JsonPath.compile("_links.deploymentBase.href").read(mvcResult.getResponse().getContentAsString())
.toString()).isNotEqualTo(urlBeforeSwitch); .toString()).isNotEqualTo(urlBeforeSwitch);
@@ -238,9 +239,9 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final String visibleMetadataOsKey = "metaDataVisible"; final String visibleMetadataOsKey = "metaDataVisible";
final String visibleMetadataOsValue = "withValue"; 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); "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); getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
@@ -255,23 +256,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
implicitLock(ds); implicitLock(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1); assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
assignDistributionSet(ds2, saved).getAssignedEntity(); assignDistributionSet(ds2, saved).getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2); assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(uaction.getDistributionSet()).isEqualTo(ds); assertThat(uaction.getDistributionSet()).isEqualTo(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
@@ -301,9 +300,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet("", true); final DistributionSet ds = testdataFactory.createDistributionSet("", true);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", 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);
"test1", ARTIFACT_SIZE); final Artifact artifactSignature = testdataFactory.createArtifact(nextBytes(ARTIFACT_SIZE),
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE),
getOsModule(ds), "test1.signature", ARTIFACT_SIZE); getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
final Target savedTarget = createTargetAndAssertNoActiveActions(); final Target savedTarget = createTargetAndAssertNoActiveActions();
@@ -313,23 +311,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
implicitLock(ds); implicitLock(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1); assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
assignDistributionSet(ds2, saved).getAssignedEntity(); assignDistributionSet(ds2, saved).getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(uaction.getDistributionSet()).isEqualTo(ds); assertThat(uaction.getDistributionSet()).isEqualTo(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
// Run test // Run test
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
@@ -339,7 +335,6 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(), artifactSignature, action.getId(),
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced"); findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
@@ -362,10 +357,9 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// Prepare test data // Prepare test data
final DistributionSet ds = testdataFactory.createDistributionSet("", true); final DistributionSet ds = testdataFactory.createDistributionSet("", true);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", 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);
"test1", ARTIFACT_SIZE); final Artifact artifactSignature = testdataFactory.createArtifact(
final Artifact artifactSignature = testdataFactory.createArtifact(RandomUtils.nextBytes(ARTIFACT_SIZE), nextBytes(ARTIFACT_SIZE), getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds)) softwareModuleManagement.createMetaData(entityFactory.softwareModuleMetadata().create(getOsModule(ds))
.key("metaDataVisible").value("withValue").targetVisible(true)); .key("metaDataVisible").value("withValue").targetVisible(true));
@@ -374,21 +368,20 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Target savedTarget = createTargetAndAssertNoActiveActions(); final Target savedTarget = createTargetAndAssertNoActiveActions();
final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), final List<Target> saved = assignDistributionSet(ds.getId(), savedTarget.getControllerId(), ActionType.DOWNLOAD_ONLY)
ActionType.DOWNLOAD_ONLY).getAssignedEntity().stream().map(Action::getTarget) .getAssignedEntity().stream()
.map(Action::getTarget)
.collect(Collectors.toList()); .collect(Collectors.toList());
implicitLock(ds); implicitLock(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(1);
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(1); assertThat(deploymentManagement.countActionsAll()).isEqualTo(1);
assignDistributionSet(ds2, saved).getAssignedEntity(); assignDistributionSet(ds2, saved).getAssignedEntity();
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
assertThat(deploymentManagement.countActionsAll()).isEqualTo(2); assertThat(deploymentManagement.countActionsAll()).isEqualTo(2);
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
assertThat(uaction.getDistributionSet()).isEqualTo(ds); assertThat(uaction.getDistributionSet()).isEqualTo(ds);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())).hasSize(2);
@@ -396,7 +389,8 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID).andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) DEFAULT_CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href", .andExpect(jsonPath("$._links.deploymentBase.href",
startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString())))); startsWith(deploymentBaseLink(DEFAULT_CONTROLLER_ID, uaction.getId().toString()))));
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery()) assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getLastTargetQuery())
@@ -406,7 +400,6 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
assertThat(countActionStatusAll()).isEqualTo(2); assertThat(countActionStatusAll()).isEqualTo(2);
final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get(); final DistributionSet findDistributionSetByAction = distributionSetManagement.getByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, "metaDataVisible", getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, "metaDataVisible",
"withValue", artifact, artifactSignature, action.getId(), "forced", "skip", "withValue", artifact, artifactSignature, action.getId(), "forced", "skip",
getOsModule(findDistributionSetByAction)); getOsModule(findDistributionSetByAction));
@@ -426,22 +419,26 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// not allowed methods // not allowed methods
mvc.perform(post(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1")) 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")) 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")) 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 // non existing target
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "not-existing", "1")) 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 // no deployment
mvc.perform( mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1"))
MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "1")) .andDo(MockMvcResultPrinter.print())
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound()); .andExpect(status().isNotFound());
// wrong media type // wrong media type
final List<Target> toAssign = Collections.singletonList(target); final List<Target> toAssign = Collections.singletonList(target);
@@ -449,23 +446,25 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID,
actionId)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); actionId))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
mvc.perform(MockMvcRequestBuilders mvc.perform(MockMvcRequestBuilders
.get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, actionId) .get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, actionId)
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_ATOM_XML))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotAcceptable()); .andExpect(status().isNotAcceptable());
} }
@Test @Test
@Description("The server protects itself against to many feedback upload attempts. The test verifies that " @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.") "it is not possible to exceed the configured maximum number of feedback uploads.")
void tooMuchDeploymentActionFeedback() throws Exception { void tooMuchDeploymentActionFeedback() throws Exception {
final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID); final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds.getId(), DEFAULT_CONTROLLER_ID); assignDistributionSet(ds.getId(), DEFAULT_CONTROLLER_ID);
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent() final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
.get(0);
final String feedback = getJsonProceedingDeploymentActionFeedback(); final String feedback = getJsonProceedingDeploymentActionFeedback();
// assign distribution set creates an action status, so only 99 left // assign distribution set creates an action status, so only 99 left
@@ -477,23 +476,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
} }
@Test @Test
@Description("The server protects itself against too large feedback bodies. The test verifies that " @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.") "it is not possible to exceed the configured maximum number of feedback details.")
void tooMuchDeploymentActionMessagesInFeedback() throws Exception { void tooMuchDeploymentActionMessagesInFeedback() throws Exception {
final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID); final Target target = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds.getId(), DEFAULT_CONTROLLER_ID); assignDistributionSet(ds.getId(), DEFAULT_CONTROLLER_ID);
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent() final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
.get(0);
final List<String> messages = new ArrayList<>(); final List<String> messages = new ArrayList<>();
for (int i = 0; i < quotaManagement.getMaxMessagesPerActionStatus() + 1; i++) { for (int i = 0; i < quotaManagement.getMaxMessagesPerActionStatus() + 1; i++) {
messages.add(String.valueOf(i)); messages.add(String.valueOf(i));
} }
final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE, final String feedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, DdiResult.FinalResult.NONE, null, messages);
null, messages);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(), feedback, status().isForbidden()); 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); assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.UNKNOWN)).hasSize(2);
// action1 done // action1 done
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId1, getJsonClosedDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId1, getJsonClosedDeploymentActionFeedback(), status().isOk());
status().isOk());
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 2, findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 2, Optional.of(ds1));
Optional.of(ds1));
assertStatusMessagesCount(4); assertStatusMessagesCount(4);
// action2 done // action2 done
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId2, getJsonClosedDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId2, getJsonClosedDeploymentActionFeedback(), status().isOk());
status().isOk());
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 1, findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.PENDING, 1, Optional.of(ds2));
Optional.of(ds2));
assertStatusMessagesCount(5); assertStatusMessagesCount(5);
// action3 done // action3 done
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId3, getJsonClosedDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId3, getJsonClosedDeploymentActionFeedback(), status().isOk());
status().isOk());
findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.IN_SYNC, 0, findTargetAndAssertUpdateStatus(Optional.of(ds3), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds3));
Optional.of(ds3));
assertStatusMessagesCount(6); assertStatusMessagesCount(6);
} }
@@ -549,16 +540,15 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
DistributionSet ds = testdataFactory.createDistributionSet(""); DistributionSet ds = testdataFactory.createDistributionSet("");
final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID); final Target savedTarget = testdataFactory.createTarget(DEFAULT_CONTROLLER_ID);
assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()) assertThat(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
.isEqualTo(TargetUpdateStatus.UNKNOWN);
assignDistributionSet(ds, Collections.singletonList(savedTarget)); assignDistributionSet(ds, Collections.singletonList(savedTarget));
final Action action = actionRepository final Action action = actionRepository
.findAll(ActionSpecifications.byDistributionSetId(ds.getId()), PAGE) .findAll(ActionSpecifications.byDistributionSetId(ds.getId()), PAGE)
.map(Action.class::cast).getContent().get(0); .map(Action.class::cast).getContent().get(0);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action.getId(),
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.FAILURE, getJsonActionFeedback(
Collections.singletonList("Error message")), DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.FAILURE, Collections.singletonList("Error message")),
status().isOk()); status().isOk());
findTargetAndAssertUpdateStatus(Optional.empty(), TargetUpdateStatus.ERROR, 0, Optional.empty()); findTargetAndAssertUpdateStatus(Optional.empty(), TargetUpdateStatus.ERROR, 0, Optional.empty());
@@ -567,60 +557,51 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// redo // redo
ds = distributionSetManagement.getWithDetails(ds.getId()).get(); ds = distributionSetManagement.getWithDetails(ds.getId()).get();
assignDistributionSet(ds, assignDistributionSet(ds, Collections.singletonList(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get()));
Collections.singletonList(targetManagement.getByControllerID(DEFAULT_CONTROLLER_ID).get())); final Action action2 = deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent().get(0);
final Action action2 = deploymentManagement.findActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID).getContent() postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(), status().isOk());
.get(0);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, action2.getId(), getJsonClosedCancelActionFeedback(),
status().isOk());
findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds)); findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.IN_SYNC, 0, Optional.of(ds));
assertTargetCountByStatus(0, 0, 1); assertTargetCountByStatus(0, 0, 1);
assertThat(deploymentManagement.findInActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID)).hasSize(2); assertThat(deploymentManagement.findInActiveActionsByTarget(PAGE, DEFAULT_CONTROLLER_ID)).hasSize(2);
assertThat(countActionStatusAll()).isEqualTo(4); assertThat(countActionStatusAll()).isEqualTo(4);
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action.getId()).getContent()).haveAtLeast(1, assertThat(deploymentManagement.findActionStatusByAction(PAGE, action.getId()).getContent())
new ActionStatusCondition(Status.ERROR)); .haveAtLeast(1, new ActionStatusCondition(Status.ERROR));
assertThat(deploymentManagement.findActionStatusByAction(PAGE, action2.getId()).getContent()).haveAtLeast(1, assertThat(deploymentManagement.findActionStatusByAction(PAGE, action2.getId()).getContent())
new ActionStatusCondition(Status.FINISHED)); .haveAtLeast(1, new ActionStatusCondition(Status.FINISHED));
} }
@Test @Test
@Description("Verifies that the controller can provided as much feedback entries as necessary as long as it is in the configured limits.") @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 { void rootRsSingleDeploymentActionFeedback() throws Exception {
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, final Long actionId = getFirstAssignedActionId(
Collections.singletonList(testdataFactory.createTarget(DEFAULT_CONTROLLER_ID)))); assignDistributionSet(ds,
Collections.singletonList(testdataFactory.createTarget(DEFAULT_CONTROLLER_ID))));
implicitLock(ds); implicitLock(ds);
findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.PENDING, 1, Optional.empty()); findTargetAndAssertUpdateStatus(Optional.of(ds), TargetUpdateStatus.PENDING, 1, Optional.empty());
// Now valid Feedback // Now valid Feedback
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonProceedingDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonProceedingDeploymentActionFeedback(), status().isOk());
status().isOk());
assertActionStatusCount(i + 2, i); assertActionStatusCount(i + 2, i);
} }
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonScheduledDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonScheduledDeploymentActionFeedback(), status().isOk());
status().isOk());
assertActionStatusCount(6, 5); assertActionStatusCount(6, 5);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonResumedDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonResumedDeploymentActionFeedback(), status().isOk());
status().isOk());
assertActionStatusCount(7, 6); assertActionStatusCount(7, 6);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonCanceledDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonCanceledDeploymentActionFeedback(), status().isOk());
status().isOk());
assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1); assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1);
assertActionStatusCount(8, 7, 0, 0, 1); assertActionStatusCount(8, 7, 0, 0, 1);
assertTargetCountByStatus(1, 0, 0); assertTargetCountByStatus(1, 0, 0);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonRejectedDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonRejectedDeploymentActionFeedback(), status().isOk());
status().isOk());
assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1); assertStatusAndActiveActionsCount(TargetUpdateStatus.PENDING, 1);
assertActionStatusCount(9, 6, 1, 0, 1); assertActionStatusCount(9, 6, 1, 0, 1);
postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonClosedDeploymentActionFeedback(), postDeploymentFeedback(DEFAULT_CONTROLLER_ID, actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
status().isOk());
assertStatusAndActiveActionsCount(TargetUpdateStatus.IN_SYNC, 0); assertStatusAndActiveActionsCount(TargetUpdateStatus.IN_SYNC, 0);
assertActionStatusCount(10, 7, 1, 1, 1); assertActionStatusCount(10, 7, 1, 1, 1);
assertTargetCountByStatus(0, 0, 1); assertTargetCountByStatus(0, 0, 1);
@@ -636,9 +617,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet savedSet2 = testdataFactory.createDistributionSet("1"); final DistributionSet savedSet2 = testdataFactory.createDistributionSet("1");
// target does not exist // 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); 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(savedSet, Collections.singletonList(savedTarget)).getAssignedEntity().iterator().next();
assignDistributionSet(savedSet2, Collections.singletonList(testdataFactory.createTarget("4713"))); assignDistributionSet(savedSet2, Collections.singletonList(testdataFactory.createTarget("4713")));
final Action updateAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action updateAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
// action exists but is not assigned to this target // action exists but is not assigned to this target
postDeploymentFeedback("4713", updateAction.getId(), getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING, postDeploymentFeedback("4713", updateAction.getId(), getJsonActionFeedback(DdiStatus.ExecutionStatus.PROCEEDING,
@@ -657,53 +635,57 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
// not allowed methods // not allowed methods
mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), mvc.perform(MockMvcRequestBuilders.get(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(),
DEFAULT_CONTROLLER_ID, "2")).andDo(MockMvcResultPrinter.print()) DEFAULT_CONTROLLER_ID, "2"))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed()); .andExpect(status().isMethodNotAllowed());
mvc.perform(put(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2")) mvc.perform(put(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
mvc.perform(delete(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2")) mvc.perform(delete(DEPLOYMENT_FEEDBACK, tenantAware.getCurrentTenant(), DEFAULT_CONTROLLER_ID, "2"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isMethodNotAllowed()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
} }
@Test @Test
@Description("Ensures that an invalid id in feedback body returns a bad request.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 { void invalidIdInFeedbackReturnsBadRequest() throws Exception {
final Target target = testdataFactory.createTarget("1080"); final Target target = testdataFactory.createTarget("1080");
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds.getId(), "1080"); assignDistributionSet(ds.getId(), "1080");
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent() final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
.get(0);
final String invalidFeedback = "{\"id\":\"AAAA\",\"status\":{\"execution\":\"proceeding\",\"result\":{\"finished\":\"none\",\"progress\":{\"cnt\":2,\"of\":5}},\"details\":\"details\"]}}"; 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()); postDeploymentFeedback("1080", action.getId(), invalidFeedback, status().isBadRequest());
} }
@Test @Test
@Description("Ensures that a missing feedback result in feedback body returns a bad request.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 { void missingResultAttributeInFeedbackReturnsBadRequest() throws Exception {
final Target target = testdataFactory.createTarget("1080"); final Target target = testdataFactory.createTarget("1080");
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds.getId(), "1080"); assignDistributionSet(ds.getId(), "1080");
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent() final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
.get(0);
final String missingResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, (DdiResult) null, final String missingResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, (DdiResult) null,
Collections.singletonList("test")); Collections.singletonList("test"));
@@ -714,20 +696,21 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Ensures that a missing finished result in feedback body returns a bad request.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 { void missingFinishedAttributeInFeedbackReturnsBadRequest() throws Exception {
final Target target = testdataFactory.createTarget("1080"); final Target target = testdataFactory.createTarget("1080");
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
assignDistributionSet(ds.getId(), "1080"); assignDistributionSet(ds.getId(), "1080");
final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent() final Action action = deploymentManagement.findActionsByTarget(target.getControllerId(), PAGE).getContent().get(0);
.get(0);
final String missingFinishedResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, final String missingFinishedResultInFeedback = getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED,
new DdiResult(null, null), new DdiResult(null, null),
Collections.singletonList("test")); Collections.singletonList("test"));
@@ -741,15 +724,15 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
return actionStatusRepository.count(); 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 DistributionSet ds, final String visibleMetadataOsKey, final String visibleMetadataOsValue,
final Artifact artifact, final Artifact artifactSignature, final Long actionId, final String downloadType, final Artifact artifact, final Artifact artifactSignature, final Long actionId, final String downloadType,
final String updateType, final Long osModuleId) throws Exception { final String updateType, final Long osModuleId) throws Exception {
getAndVerifyDeploymentBasePayload(controllerId, mediaType, ds, artifact, artifactSignature, actionId, getAndVerifyDeploymentBasePayload(controllerId, mediaType, ds, artifact, artifactSignature, actionId,
osModuleId, downloadType, updateType).andExpect( osModuleId, downloadType, updateType)
jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].key").value(visibleMetadataOsKey)) .andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].key").value(visibleMetadataOsKey))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].value") .andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].metadata[0].value").value(visibleMetadataOsValue));
.value(visibleMetadataOsValue));
} }
private void assertActionStatusCount(final int actionStatusCount, final int minActionStatusCountInPage) { 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(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(1);
assertThat(countActionStatusAll()).isEqualTo(actionStatusCount); assertThat(countActionStatusAll()).isEqualTo(actionStatusCount);
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(minActionStatusCountInPage, assertThat(findActionStatusAll(PAGE).getContent())
new ActionStatusCondition(Status.RUNNING)); .haveAtLeast(minActionStatusCountInPage, new ActionStatusCondition(Status.RUNNING));
} }
private Target createTargetAndAssertNoActiveActions() { private Target createTargetAndAssertNoActiveActions() {
@@ -774,13 +757,13 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
private void assertStatusMessagesCount(final int actionStatusMessagesCount) { private void assertStatusMessagesCount(final int actionStatusMessagesCount) {
final Iterable<ActionStatus> actionStatusMessages; final Iterable<ActionStatus> actionStatusMessages;
actionStatusMessages = findActionStatusAll(PageRequest.of(0, 100, Direction.DESC, "id")) actionStatusMessages = findActionStatusAll(PageRequest.of(0, 100, Direction.DESC, "id")).getContent();
.getContent();
assertThat(actionStatusMessages).hasSize(actionStatusMessagesCount); assertThat(actionStatusMessages).hasSize(actionStatusMessagesCount);
assertThat(actionStatusMessages).haveAtLeast(1, new ActionStatusCondition(Status.FINISHED)); 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 TargetUpdateStatus updateStatus, final int activeActions,
final Optional<DistributionSet> installedDs) { final Optional<DistributionSet> installedDs) {
final Target myT = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get(); 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) { private void assertTargetCountByStatus(final int pending, final int error, final int inSync) {
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.PENDING)) assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.PENDING)).hasSize(pending);
.hasSize(pending);
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.ERROR)).hasSize(error); assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.ERROR)).hasSize(error);
assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.IN_SYNC)) assertThat(targetManagement.findByUpdateStatus(PageRequest.of(0, 10), TargetUpdateStatus.IN_SYNC)).hasSize(inSync);
.hasSize(inSync);
} }
private void assertActionStatusCount(final int total, final int running, final int warning, final int finished, private void assertActionStatusCount(final int total, final int running, final int warning, final int finished, final int canceled) {
final int canceled) {
assertThat(countActionStatusAll()).isEqualTo(total); assertThat(countActionStatusAll()).isEqualTo(total);
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(running, assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(running, new ActionStatusCondition(Status.RUNNING));
new ActionStatusCondition(Status.RUNNING)); assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(warning, new ActionStatusCondition(Status.WARNING));
assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(warning, assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(canceled, new ActionStatusCondition(Status.CANCELED));
new ActionStatusCondition(Status.WARNING)); assertThat(findActionStatusAll(PAGE).getContent()).haveAtLeast(finished, new ActionStatusCondition(Status.FINISHED));
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) { private void assertStatusAndActiveActionsCount(final TargetUpdateStatus status, final int activeActions) {
final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get(); final Target target = targetManagement.getByControllerID(DdiDeploymentBaseTest.DEFAULT_CONTROLLER_ID).get();
assertThat(target.getUpdateStatus()).isEqualTo(status); assertThat(target.getUpdateStatus()).isEqualTo(status);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())) assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(activeActions);
.hasSize(activeActions);
} }
private Page<ActionStatus> findActionStatusAll(final Pageable pageable) { private Page<ActionStatus> findActionStatusAll(final Pageable pageable) {
@@ -835,4 +810,4 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
return value.getStatus() == status; return value.getStatus() == status;
} }
} }
} }

View File

@@ -30,7 +30,6 @@ import java.util.stream.Stream;
import io.qameta.allure.Description; import io.qameta.allure.Description;
import io.qameta.allure.Feature; import io.qameta.allure.Feature;
import io.qameta.allure.Story; 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.DdiResult;
import org.eclipse.hawkbit.ddi.json.model.DdiStatus; import org.eclipse.hawkbit.ddi.json.model.DdiStatus;
import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants; import org.eclipse.hawkbit.ddi.rest.api.DdiRestConstants;
@@ -87,8 +86,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
testdataFactory.createArtifacts(softwareModuleId); testdataFactory.createArtifacts(softwareModuleId);
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
status().isOk());
// get installed base // get installed base
performGet(INSTALLED_BASE, MediaType.parseMediaType(DdiRestConstants.MEDIA_TYPE_CBOR), status().isOk(), 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(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
// update assigned version // update assigned version
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status() putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isCreated());
.isCreated());
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()) assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get().getId()).isEqualTo(ds.getId());
.isEqualTo(ds.getId());
// update assigned version while version already assigned // update assigned version while version already assigned
putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isOk()); putInstalledBase(target.getControllerId(), getJsonInstalledBase(ds.getName(), ds.getVersion()), status().isOk());
@@ -137,15 +133,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = createTargetAndAssertNoActiveActions(); final Target target = createTargetAndAssertNoActiveActions();
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true); 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); 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); getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); 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); 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); getOsModule(ds2), "test2.signature", ARTIFACT_SIZE);
// Run test with 1st action // Run test with 1st action
@@ -161,8 +157,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
postDeploymentFeedback(target.getControllerId(), actionId1, postDeploymentFeedback(target.getControllerId(), actionId1,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
Collections.singletonList("Closed")),
status().isOk()); status().isOk());
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, 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); actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED);
postDeploymentFeedback(target.getControllerId(), actionId2, postDeploymentFeedback(target.getControllerId(), actionId2,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
Collections.singletonList("Closed")),
status().isOk()); status().isOk());
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2, getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2,
@@ -195,8 +189,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
startsWith(installedBaseLink(CONTROLLER_ID, actionId2.toString())))) startsWith(installedBaseLink(CONTROLLER_ID, actionId2.toString()))))
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()); .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
// older installed action is still accessible, although not part of controller // older installed action is still accessible, although not part of controller base
// base
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1, getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT); actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
} }
@@ -208,9 +201,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = createTargetAndAssertNoActiveActions(); final Target target = createTargetAndAssertNoActiveActions();
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true); 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); 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); getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
// assign ds1, action1 - and provide cancel feedback // assign ds1, action1 - and provide cancel feedback
@@ -218,8 +211,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
deploymentManagement.cancelAction(actionId1); deploymentManagement.cancelAction(actionId1);
postCancelFeedback(target.getControllerId(), actionId1, postCancelFeedback(target.getControllerId(), actionId1,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
Collections.singletonList("Canceled")),
status().isOk()); status().isOk());
// assign ds1, action2 - and provide cancel feedback // assign ds1, action2 - and provide cancel feedback
@@ -227,16 +219,14 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.FORCED)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.FORCED));
deploymentManagement.cancelAction(actionId2); deploymentManagement.cancelAction(actionId2);
postCancelFeedback(target.getControllerId(), actionId2, postCancelFeedback(target.getControllerId(), actionId2,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
Collections.singletonList("Canceled")),
status().isOk()); status().isOk());
// assign ds1, action 3 - and provide success feedback // assign ds1, action 3 - and provide success feedback
final Long actionId3 = getFirstAssignedActionId( final Long actionId3 = getFirstAssignedActionId(
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
postDeploymentFeedback(target.getControllerId(), actionId3, postDeploymentFeedback(target.getControllerId(), actionId3,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
Collections.singletonList("Canceled")),
status().isOk()); status().isOk());
// Test: latest succeeded action is returned in installedBase // Test: latest succeeded action is returned in installedBase
@@ -251,9 +241,13 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// cancelled action are not accessible // cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), 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(), 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 @Test
@@ -263,9 +257,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = createTargetAndAssertNoActiveActions(); final Target target = createTargetAndAssertNoActiveActions();
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true); 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); 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); getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
@@ -274,8 +268,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId1 = getFirstAssignedActionId( final Long actionId1 = getFirstAssignedActionId(
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
postDeploymentFeedback(target.getControllerId(), actionId1, postDeploymentFeedback(target.getControllerId(), actionId1,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Success")),
Collections.singletonList("Success")),
status().isOk()); status().isOk());
// assign ds2, action2 - assign ds1, action 3 - and cancel both // 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)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
deploymentManagement.cancelAction(actionId2); deploymentManagement.cancelAction(actionId2);
postCancelFeedback(target.getControllerId(), actionId2, postCancelFeedback(target.getControllerId(), actionId2,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
Collections.singletonList("Canceled")),
status().isOk()); status().isOk());
deploymentManagement.cancelAction(actionId3); deploymentManagement.cancelAction(actionId3);
postCancelFeedback(target.getControllerId(), actionId3, postCancelFeedback(target.getControllerId(), actionId3,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
Collections.singletonList("Canceled")),
status().isOk()); status().isOk());
// Test: the succeeded action is returned in installedBase instead of the latest // 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 // cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), 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(), 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 @Test
@@ -319,9 +314,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Target target = createTargetAndAssertNoActiveActions(); final Target target = createTargetAndAssertNoActiveActions();
final DistributionSet ds1 = testdataFactory.createDistributionSet("1", true); 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); 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); getOsModule(ds1), "test1.signature", ARTIFACT_SIZE);
final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true); final DistributionSet ds2 = testdataFactory.createDistributionSet("2", true);
@@ -330,8 +325,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId1 = getFirstAssignedActionId( final Long actionId1 = getFirstAssignedActionId(
assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
postDeploymentFeedback(target.getControllerId(), actionId1, postDeploymentFeedback(target.getControllerId(), actionId1,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Success")),
Collections.singletonList("Success")),
status().isOk()); status().isOk());
// assign ds2, action2 - assign ds1, action 3 - and cancel action 2 // 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)); assignDistributionSet(ds1.getId(), target.getControllerId(), Action.ActionType.SOFT));
deploymentManagement.cancelAction(actionId2); deploymentManagement.cancelAction(actionId2);
postCancelFeedback(target.getControllerId(), actionId2, postCancelFeedback(target.getControllerId(), actionId2,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Canceled")),
Collections.singletonList("Canceled")),
status().isOk()); status().isOk());
// Test: the succeeded action is returned in installedBase instead of the latest // Test: the succeeded action is returned in installedBase instead of the latest cancelled action
// cancelled action
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID) performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
@@ -359,9 +351,13 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// cancelled action are not accessible // cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), 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(), 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 @Test
@@ -382,7 +378,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
target.getControllerId(), actionId.toString()); target.getControllerId(), actionId.toString());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(), 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 @Test
@@ -396,8 +394,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(ds, target));
postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), postDeploymentFeedback(target.getControllerId(), actionId, getJsonClosedDeploymentActionFeedback(), status().isOk());
status().isOk());
performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(), performGet(SOFTWARE_MODULE_ARTIFACTS, MediaType.APPLICATION_JSON, status().isOk(),
tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString()) tenantAware.getCurrentTenant(), target.getControllerId(), softwareModuleId.toString())
@@ -410,13 +407,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
@ParameterizedTest @ParameterizedTest
@MethodSource("org.eclipse.hawkbit.ddi.rest.resource.DdiInstalledBaseTest#actionTypeForDeployment") @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.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 5), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 5), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAttributesRequestedEvent.class, count = 1), @Expect(type = TargetAttributesRequestedEvent.class, count = 1),
@Expect(type = TargetPollEvent.class, count = 1) }) @Expect(type = TargetPollEvent.class, count = 1) })
@@ -424,26 +423,26 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Prepare test data // Prepare test data
final Target target = createTargetAndAssertNoActiveActions(); final Target target = createTargetAndAssertNoActiveActions();
final DistributionSet ds = testdataFactory.createDistributionSet("", true); 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); "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); getOsModule(ds), "test1.signature", ARTIFACT_SIZE);
final Long actionId = getFirstAssignedActionId( final Long actionId = getFirstAssignedActionId(
assignDistributionSet(ds.getId(), target.getControllerId(), actionType)); assignDistributionSet(ds.getId(), target.getControllerId(), actionType));
postDeploymentFeedback(target.getControllerId(), actionId, postDeploymentFeedback(target.getControllerId(), actionId,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
Collections.singletonList("Closed")),
status().isOk()); status().isOk());
// Run test // Run test
final ResultActions resultActions = performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), final ResultActions resultActions = performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(),
tenantAware.getCurrentTenant(), target.getControllerId()); 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.deploymentBase.href").doesNotExist())
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href", containsString(String.format(
containsString(String.format("/%s/controller/v1/%s/installedBase/%d", "/%s/controller/v1/%s/installedBase/%d",
tenantAware.getCurrentTenant(), target.getControllerId(), actionId)))); tenantAware.getCurrentTenant(), target.getControllerId(), actionId))));
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature, getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature,
actionId, ds.findFirstModuleByType(osType).get().getId(), actionType); actionId, ds.findFirstModuleByType(osType).get().getId(), actionType);
@@ -461,13 +460,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Test download-only deployment to a controller. Checks that download-only is not represented as installedBase.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAttributesRequestedEvent.class, count = 1), @Expect(type = TargetAttributesRequestedEvent.class, count = 1),
@Expect(type = TargetPollEvent.class, count = 2) }) @Expect(type = TargetPollEvent.class, count = 2) })
@@ -479,18 +480,20 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds.getId(), target.getControllerId(), Action.ActionType.DOWNLOAD_ONLY)); assignDistributionSet(ds.getId(), target.getControllerId(), Action.ActionType.DOWNLOAD_ONLY));
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) target.getControllerId())
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").exists()) .andExpect(jsonPath("$._links.deploymentBase.href").exists())
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()); .andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(), postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadDeploymentActionFeedback(), status().isOk());
status().isOk()); postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(), status().isOk());
postDeploymentFeedback(target.getControllerId(), actionId, getJsonDownloadedDeploymentActionFeedback(),
status().isOk());
// Test // Test
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) target.getControllerId())
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()); .andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
} }
@@ -506,7 +509,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds.getId(), target.getControllerId(), actionType)); assignDistributionSet(ds.getId(), target.getControllerId(), actionType));
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) target.getControllerId())
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").exists()) .andExpect(jsonPath("$._links.deploymentBase.href").exists())
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()); .andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
@@ -520,7 +525,9 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// Test // Test
performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(), performGet(CONTROLLER_BASE, MediaType.APPLICATION_JSON, status().isOk(), tenantAware.getCurrentTenant(),
target.getControllerId()).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) target.getControllerId())
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()); .andExpect(jsonPath("$._links.installedBase.href").doesNotExist());
} }
@@ -531,8 +538,7 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
Target savedTarget = testdataFactory.createTarget("911"); Target savedTarget = testdataFactory.createTarget("911");
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId())); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(), postDeploymentFeedback(savedTarget.getControllerId(), savedAction.getId(),
getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE, getJsonActionFeedback(DdiStatus.ExecutionStatus.SCHEDULED, DdiResult.FinalResult.NONE,
@@ -553,14 +559,15 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// for zero input no action history is returned // for zero input no action history is returned
mvc.perform(get(INSTALLED_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(INSTALLED_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist()); .andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
// depending on given query parameter value, only the latest messages are // depending on given query parameter value, only the latest messages are returned
// returned
mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(INSTALLED_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed")))) .andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed"))))
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding")))) .andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
.andExpect( .andExpect(
@@ -569,7 +576,8 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// for negative input the entire action history is returned // for negative input the entire action history is returned
mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(INSTALLED_BASE + "?actionHistory=-3", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed")))) .andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation completed"))))
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding")))) .andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation proceeding"))))
.andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation scheduled")))); .andExpect(jsonPath("$.actionHistory.messages", hasItem(containsString("Installation scheduled"))));
@@ -582,21 +590,26 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// not allowed methods // not allowed methods
mvc.perform(post(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1")) 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")) 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")) 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 // non existing target
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), "not-existing", "1")) 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 // no deployment
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, "1")) 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 // wrong media type
final List<Target> toAssign = Collections.singletonList(target); final List<Target> toAssign = Collections.singletonList(target);
@@ -605,9 +618,11 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign)); final Long actionId = getFirstAssignedActionId(assignDistributionSet(savedSet, toAssign));
postDeploymentFeedback(CONTROLLER_ID, actionId, getJsonClosedCancelActionFeedback(), status().isOk()); postDeploymentFeedback(CONTROLLER_ID, actionId, getJsonClosedCancelActionFeedback(), status().isOk());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId)) mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId) mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), CONTROLLER_ID, actionId)
.accept(MediaType.APPLICATION_ATOM_XML)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_ATOM_XML))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotAcceptable()); .andExpect(status().isNotAcceptable());
} }
@@ -622,4 +637,4 @@ public class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
assertThat(actionStatusRepository.count()).isZero(); assertThat(actionStatusRepository.count()).isZero();
return savedTarget; return savedTarget;
} }
} }

View File

@@ -86,6 +86,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
private static final String TARGET_COMPLETED_INSTALLATION_MSG = "Target completed installation."; 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_PROCEEDING_INSTALLATION_MSG = "Target proceeding installation.";
private static final String TARGET_SCHEDULED_INSTALLATION_MSG = "Target scheduled installation."; private static final String TARGET_SCHEDULED_INSTALLATION_MSG = "Target scheduled installation.";
@Autowired @Autowired
private HawkbitSecurityProperties securityProperties; private HawkbitSecurityProperties securityProperties;
@@ -93,7 +94,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Description("Ensure that the root poll resource is available as CBOR") @Description("Ensure that the root poll resource is available as CBOR")
void rootPollResourceCbor() throws Exception { void rootPollResourceCbor() throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711).accept(DdiRestConstants.MEDIA_TYPE_CBOR)) 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()); .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.") @Description("Ensures that the API returns JSON when no Accept header is specified by the client.")
void apiReturnsJSONByDefault() throws Exception { void apiReturnsJSONByDefault() throws Exception {
final MvcResult result = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)) final MvcResult result = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(content().contentType(MediaTypes.HAL_JSON)).andReturn(); .andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON))
.andReturn();
// verify that we did not specify a content-type in the request, in case // verify that we did not specify a content-type in the request, in case there are any default values
// there are any default values
assertThat(result.getRequest().getHeader("Accept")).isNull(); assertThat(result.getRequest().getHeader("Accept")).isNull();
} }
@Test @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.") @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, @WithUser(tenantId = "tenantDoesNotExists", allSpPermissions = true,
SYSTEM_ROLE }, autoCreateTenant = false) authorities = { CONTROLLER_ROLE, SYSTEM_ROLE }, autoCreateTenant = false)
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetPollEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1),
@Expect(type = DistributionSetTypeCreatedEvent.class, count = 3), @Expect(type = DistributionSetTypeCreatedEvent.class, count = 3),
@Expect(type = SoftwareModuleTypeCreatedEvent.class, count = 2) }) @Expect(type = SoftwareModuleTypeCreatedEvent.class, count = 2) })
void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception { void targetCannotBeRegisteredIfTenantDoesNotExistsButWhenExists() throws Exception {
mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant()))
mvc.perform(get("/default-tenant/", tenantAware.getCurrentTenant())).andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotFound()); .andExpect(status().isNotFound());
// create tenant -- creates softwaremoduletypes and distributionsettypes // create tenant -- creates software module types and distribution set types
systemManagement.createTenantMetadata("tenantDoesNotExists"); systemManagement.createTenantMetadata("tenantDoesNotExists");
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), "aControllerId")) 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 // delete tenant again, will also deleted target aControllerId
systemManagement.deleteTenant("tenantDoesNotExists"); systemManagement.deleteTenant("tenantDoesNotExists");
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), "aControllerId")) mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), "aControllerId"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isBadRequest()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
} }
@Test @Test
@Description("Ensures that target poll request does not change audit data on the entity.") @Description("Ensures that target poll request does not change audit data on the entity.")
@WithUser(principal = "knownPrincipal", authorities = { SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET, @WithUser(principal = "knownPrincipal", authorities = { SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET, SpPermission.CREATE_TARGET })
SpPermission.CREATE_TARGET }, allSpPermissions = false) @ExpectEvents({
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.class, count = 1) }) @Expect(type = TargetUpdatedEvent.class, count = 1),
@Expect(type = TargetPollEvent.class, count = 1) })
void targetPollDoesNotModifyAuditData() throws Exception { void targetPollDoesNotModifyAuditData() throws Exception {
// create target first with "knownPrincipal" user and audit data // create target first with "knownPrincipal" user and audit data
final String knownTargetControllerId = "target1"; final String knownTargetControllerId = "target1";
@@ -149,12 +156,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId).get(); final Target findTargetByControllerID = targetManagement.getByControllerID(knownTargetControllerId).get();
assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy); assertThat(findTargetByControllerID.getCreatedBy()).isEqualTo(knownCreatedBy);
// make a poll, audit information should not be changed, run as // make a poll, audit information should not be changed, run as controller principal!
// controller principal!
SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS),
() -> { () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownTargetControllerId)) mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownTargetControllerId))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
return null; 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.") @Description("Ensures that server returns a not found response in case of empty controller ID.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) }) @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
void rootRsWithoutId() throws Exception { 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 @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.") @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) }) @Expect(type = TargetPollEvent.class, count = 1) })
void rootRsPlugAndPlay() throws Exception { void rootRsPlugAndPlay() throws Exception {
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
final String controllerId = "4711"; final String controllerId = "4711";
mvc.perform(get(CONTROLLER_BASE, "default-tenant", controllerId)).andDo(MockMvcResultPrinter.print()) mvc.perform(get(CONTROLLER_BASE, "default-tenant", controllerId))
.andExpect(status().isOk()).andExpect(content().contentType(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("$.config.polling.sleep", equalTo("00:01:00")));
assertThat(targetManagement.getByControllerID(controllerId).get().getLastTargetQuery()) assertThat(targetManagement.getByControllerID(controllerId).get().getLastTargetQuery())
.isGreaterThanOrEqualTo(current); .isGreaterThanOrEqualTo(current);
@@ -192,33 +204,38 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.isEqualTo(TargetUpdateStatus.REGISTERED); .isEqualTo(TargetUpdateStatus.REGISTERED);
// not allowed methods // 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()); .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()); .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()); .andExpect(status().isMethodNotAllowed());
} }
@Test @Test
@Description("Ensures that tenant specific polling time, which is saved in the db, is delivered to the controller.") @Description("Ensures that tenant specific polling time, which is saved in the db, is delivered to the controller.")
@WithUser(principal = "knownpricipal", allSpPermissions = false) @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 = TargetPollEvent.class, count = 1),
@Expect(type = TenantConfigurationCreatedEvent.class, count = 1) }) @Expect(type = TenantConfigurationCreatedEvent.class, count = 1) })
void pollWithModifiedGlobalPollingTime() throws Exception { void pollWithModifiedGlobalPollingTime() throws Exception {
SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", TENANT_CONFIGURATION), SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("tenantadmin", TENANT_CONFIGURATION),
() -> { () -> {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, "00:02:00");
"00:02:00");
return null; return null;
}); });
SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> { SecurityContextSwitch.runAs(SecurityContextSwitch.withUser("controller", CONTROLLER_ROLE_ANONYMOUS), () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711)).andDo(MockMvcResultPrinter.print()) mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), 4711))
.andExpect(status().isOk()).andExpect(content().contentType(MediaTypes.HAL_JSON)) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00"))); .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:02:00")));
return null; return null;
}); });
@@ -226,10 +243,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Ensures that etag check results in not modified response if provided etag by client is identical to entity in repository.") @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 = TargetPollEvent.class, count = 6),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2), @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 = DistributionSetCreatedEvent.class, count = 2),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 6), @Expect(type = SoftwareModuleCreatedEvent.class, count = 6),
@Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 2), // implicit lock
@@ -239,14 +258,17 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
void rootRsNotModified() throws Exception { void rootRsNotModified() throws Exception {
final String controllerId = "4711"; final String controllerId = "4711";
final String etag = mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)) 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(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .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"); .getHeader("ETag");
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match", 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 Target target = targetManagement.getByControllerID(controllerId).get();
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
@@ -258,7 +280,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final String etagWithFirstUpdate = mvc final String etagWithFirstUpdate = mvc
.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId) .perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON).with(new RequestOnHawkbitDefaultPortPostProcessor())) .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(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href").doesNotExist()) .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", mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).header("If-None-Match",
etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor())) etagWithFirstUpdate).with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotModified()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isNotModified());
// now lets finish the update // now lets finish the update
sendDeploymentActionFeedback(target, updateAction, "closed", null).andDo(MockMvcResultPrinter.print()) sendDeploymentActionFeedback(target, updateAction, "closed", null)
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
// as the update was installed, and we always receive the installed action, the // 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) .perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
.header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON) .header("If-None-Match", etag).accept(MediaType.APPLICATION_JSON)
.with(new RequestOnHawkbitDefaultPortPostProcessor())) .with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist()) .andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist())
@@ -295,13 +321,13 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds2.getId(), controllerId); assignDistributionSet(ds2.getId(), controllerId);
final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()) final Action updateAction2 = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
.getContent().get(0);
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId) mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)
.header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON) .header("If-None-Match", etagAfterInstallation).accept(MediaType.APPLICATION_JSON)
.with(new RequestOnHawkbitDefaultPortPostProcessor())) .with(new RequestOnHawkbitDefaultPortPostProcessor()))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))) .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
.andExpect(jsonPath("$._links.installedBase.href", .andExpect(jsonPath("$._links.installedBase.href",
@@ -317,16 +343,16 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
+ "UNKNOWN to REGISTERED when the target polls for the first time.") + "UNKNOWN to REGISTERED when the target polls for the first time.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 1), @Expect(type = TargetPollEvent.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"; final String controllerId = "4711";
testdataFactory.createTarget(controllerId); testdataFactory.createTarget(controllerId);
assertThat(targetManagement.getByControllerID(controllerId).get().getUpdateStatus()) assertThat(targetManagement.getByControllerID(controllerId).get().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
.isEqualTo(TargetUpdateStatus.UNKNOWN);
final long current = System.currentTimeMillis(); final long current = System.currentTimeMillis();
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId)) 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(content().contentType(MediaTypes.HAL_JSON))
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00"))); .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")));
@@ -341,7 +367,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Ensures that the source IP address of the polling target is correctly stored in repository") @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) }) @Expect(type = TargetPollEvent.class, count = 1) })
void rootRsPlugAndPlayIpAddress() throws Exception { void rootRsPlugAndPlayIpAddress() throws Exception {
// test // test
@@ -352,7 +379,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS), SecurityContextSwitch.runAs(SecurityContextSwitch.withController("controller", CONTROLLER_ROLE_ANONYMOUS),
() -> { () -> {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1)) mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
return null; return null;
}); });
@@ -363,12 +391,12 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create); assertThat(target.getCreatedAt()).isGreaterThanOrEqualTo(create);
assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY"); assertThat(target.getLastModifiedBy()).isEqualTo("CONTROLLER_PLUG_AND_PLAY");
assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create); assertThat(target.getLastModifiedAt()).isGreaterThanOrEqualTo(create);
} }
@Test @Test
@Description("Ensures that the source IP address of the polling target is not stored in repository if disabled") @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) }) @Expect(type = TargetPollEvent.class, count = 1) })
void rootRsIpAddressNotStoredIfDisabled() throws Exception { void rootRsIpAddressNotStoredIfDisabled() throws Exception {
securityProperties.getClients().setTrackRemoteIp(false); securityProperties.getClients().setTrackRemoteIp(false);
@@ -376,7 +404,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
// test // test
final String knownControllerId1 = "0815"; final String knownControllerId1 = "0815";
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1)) mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), knownControllerId1))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()); .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
// verify // verify
final Target target = targetManagement.getByControllerID(knownControllerId1).get(); final Target target = targetManagement.getByControllerID(knownControllerId1).get();
@@ -387,13 +416,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Controller trys to finish an update process after it has been finished by an error action status.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 = TargetUpdatedEvent.class, count = 2) })
void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception { void tryToFinishAnUpdateProcessAfterItHasBeenFinished() throws Exception {
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
@@ -401,26 +432,32 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId())); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId())
.getContent().get(0); .getContent().get(0);
sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null).andDo(MockMvcResultPrinter.print()) sendDeploymentActionFeedback(savedTarget, savedAction, "proceeding", null)
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "failure").andDo(MockMvcResultPrinter.print()) sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "failure")
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()); .andExpect(status().isOk());
sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success").andDo(MockMvcResultPrinter.print()) sendDeploymentActionFeedback(savedTarget, savedAction, "closed", "success")
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isGone()); .andExpect(status().isGone());
} }
@Test @Test
@Description("Controller sends attribute update request after device successfully closed software update.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 2), @Expect(type = TargetAssignDistributionSetEvent.class, count = 2),
@Expect(type = ActionCreatedEvent.class, count = 2), @Expect(type = ActionUpdatedEvent.class, count = 2), @Expect(type = ActionCreatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 6), @Expect(type = TargetPollEvent.class, count = 4), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 6),
@Expect(type = TargetPollEvent.class, count = 4),
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) }) @Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
void attributeUpdateRequestSendingAfterSuccessfulDeployment() throws Exception { void attributeUpdateRequestSendingAfterSuccessfulDeployment() throws Exception {
final DistributionSet ds = testdataFactory.createDistributionSet("1"); final DistributionSet ds = testdataFactory.createDistributionSet("1");
@@ -440,13 +477,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.") @Description("Test to verify that only a specific count of messages are returned based on the input actionHistory for getControllerDeploymentActionFeedback endpoint.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1), @ExpectEvents({
@Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1), @Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) }) @Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
void testActionHistoryCount() throws Exception { void testActionHistoryCount() throws Exception {
@@ -457,17 +496,21 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.getContent().get(0); .getContent().get(0);
sendDeploymentActionFeedback(savedTarget, savedAction, "scheduled", null, TARGET_SCHEDULED_INSTALLATION_MSG) 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) 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) 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()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=2", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages", .andExpect(jsonPath("$.actionHistory.messages",
hasItem(containsString(TARGET_COMPLETED_INSTALLATION_MSG)))) hasItem(containsString(TARGET_COMPLETED_INSTALLATION_MSG))))
.andExpect(jsonPath("$.actionHistory.messages", .andExpect(jsonPath("$.actionHistory.messages",
@@ -478,45 +521,52 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Test to verify that a zero input value of actionHistory results in no action history appended for getControllerDeploymentActionFeedback endpoint.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock @Expect(type = SoftwareModuleUpdatedEvent.class, count = 3), // implicit lock
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1), @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 = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAttributesRequestedEvent.class, count = 1) }) @Expect(type = TargetAttributesRequestedEvent.class, count = 1) })
void testActionHistoryZeroInput() throws Exception { void testActionHistoryZeroInput() throws Exception {
final DistributionSet ds = testdataFactory.createDistributionSet(""); final DistributionSet ds = testdataFactory.createDistributionSet("");
Target savedTarget = testdataFactory.createTarget("911"); Target savedTarget = testdataFactory.createTarget("911");
savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId())); savedTarget = getFirstAssignedTarget(assignDistributionSet(ds.getId(), savedTarget.getControllerId()));
final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()) final Action savedAction = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
sendDeploymentActionFeedback(savedTarget, savedAction, "scheduled", null, TARGET_SCHEDULED_INSTALLATION_MSG) 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) 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) 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()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=0", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist()); .andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages").doesNotExist()); .andExpect(jsonPath("$.actionHistory.messages").doesNotExist());
} }
@Test @Test
@Description("Test to verify that entire action history is returned if the input value for actionHistory is -1, for getControllerDeploymentActionFeedback endpoint.") @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 = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3), @Expect(type = SoftwareModuleCreatedEvent.class, count = 3),
@Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock @Expect(type = DistributionSetUpdatedEvent.class, count = 1), // implicit lock
@@ -533,17 +583,21 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.getContent().get(0); .getContent().get(0);
sendDeploymentActionFeedback(savedTarget, savedAction, "scheduled", null, TARGET_SCHEDULED_INSTALLATION_MSG) 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) 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) 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()) mvc.perform(get(DEPLOYMENT_BASE + "?actionHistory=-1", tenantAware.getCurrentTenant(), 911, savedAction.getId())
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.actionHistory.messages", .andExpect(jsonPath("$.actionHistory.messages",
hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG)))) hasItem(containsString(TARGET_SCHEDULED_INSTALLATION_MSG))))
.andExpect(jsonPath("$.actionHistory.messages", .andExpect(jsonPath("$.actionHistory.messages",
@@ -561,8 +615,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
() -> { () -> {
tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL, tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.POLLING_TIME_INTERVAL,
"00:05:00"); "00:05:00");
tenantConfigurationManagement tenantConfigurationManagement.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL, "00:01:00");
.addOrUpdateConfiguration(TenantConfigurationKey.MIN_POLLING_TIME_INTERVAL, "00:01:00");
return null; return null;
}); });
@@ -570,7 +623,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(), getTestSchedule(16), assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget.getControllerId(), getTestSchedule(16),
getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next(); 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"))); .andExpect(jsonPath("$.config.polling.sleep", greaterThanOrEqualTo("00:05:00")));
final Target savedTarget1 = testdataFactory.createTarget("2911"); final Target savedTarget1 = testdataFactory.createTarget("2911");
@@ -578,7 +632,8 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
assignDistributionSetWithMaintenanceWindow(ds1.getId(), savedTarget1.getControllerId(), getTestSchedule(10), assignDistributionSetWithMaintenanceWindow(ds1.getId(), savedTarget1.getControllerId(), getTestSchedule(10),
getTestDuration(10), getTestTimeZone()).getAssignedEntity().iterator().next(); 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", lessThan("00:05:00")))
.andExpect(jsonPath("$.config.polling.sleep", greaterThanOrEqualTo("00:03: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), assignDistributionSetWithMaintenanceWindow(ds2.getId(), savedTarget2.getControllerId(), getTestSchedule(5),
getTestDuration(5), getTestTimeZone()).getAssignedEntity().iterator().next(); 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"))); .andExpect(jsonPath("$.config.polling.sleep", lessThan("00:02:00")));
final Target savedTarget3 = testdataFactory.createTarget("4911"); final Target savedTarget3 = testdataFactory.createTarget("4911");
@@ -595,9 +651,9 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
assignDistributionSetWithMaintenanceWindow(ds3.getId(), savedTarget3.getControllerId(), getTestSchedule(-5), assignDistributionSetWithMaintenanceWindow(ds3.getId(), savedTarget3.getControllerId(), getTestSchedule(-5),
getTestDuration(15), getTestTimeZone()).getAssignedEntity().iterator().next(); 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"))); .andExpect(jsonPath("$.config.polling.sleep", equalTo("00:05:00")));
} }
@Test @Test
@@ -608,13 +664,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(),
savedTarget.getControllerId(), getTestSchedule(2), getTestDuration(1), getTestTimeZone())); 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()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId()) mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
.andExpect(jsonPath("$.deployment.update", equalTo("skip"))) .andExpect(jsonPath("$.deployment.update", equalTo("skip")))
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable"))); .andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("unavailable")));
@@ -628,13 +686,15 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(), savedTarget = getFirstAssignedTarget(assignDistributionSetWithMaintenanceWindow(ds.getId(),
savedTarget.getControllerId(), getTestSchedule(-5), getTestDuration(10), getTestTimeZone())); 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()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, savedTarget.getControllerId()).getContent().get(0);
.getContent().get(0);
mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId()) mvc.perform(get(DEPLOYMENT_BASE, tenantAware.getCurrentTenant(), "1911", action.getId())
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.deployment.download", equalTo("forced"))) .andExpect(jsonPath("$.deployment.download", equalTo("forced")))
.andExpect(jsonPath("$.deployment.update", equalTo("forced"))) .andExpect(jsonPath("$.deployment.update", equalTo("forced")))
.andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available"))); .andExpect(jsonPath("$.deployment.maintenanceWindow", equalTo("available")));
@@ -648,13 +708,11 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
final DistributionSet ds1 = testdataFactory.createDistributionSet(UUID.randomUUID().toString()); final DistributionSet ds1 = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
final DistributionSet ds2 = testdataFactory.createDistributionSet(UUID.randomUUID().toString()); final DistributionSet ds2 = testdataFactory.createDistributionSet(UUID.randomUUID().toString());
final Action action1 = getFirstAssignedAction(assignDistributionSet(ds1.getId(), target.getControllerId(), 56)); final Action action1 = getFirstAssignedAction(assignDistributionSet(ds1.getId(), target.getControllerId(), 56));
final Long action2Id = getFirstAssignedActionId( final Long action2Id = getFirstAssignedActionId(assignDistributionSet(ds2.getId(), target.getControllerId(), 34));
assignDistributionSet(ds2.getId(), target.getControllerId(), 34));
assertDeploymentActionIsExposedToTarget(target.getControllerId(), action1.getId()); assertDeploymentActionIsExposedToTarget(target.getControllerId(), action1.getId());
sendDeploymentActionFeedback(target, action1, "closed", "success"); sendDeploymentActionFeedback(target, action1, "closed", "success");
assertDeploymentActionIsExposedToTarget(target.getControllerId(), action2Id); assertDeploymentActionIsExposedToTarget(target.getControllerId(), action2Id);
} }
@Test @Test
@@ -666,39 +724,39 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
} }
@Step @Step
private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds) private void assertAttributesUpdateNotRequestedAfterFailedDeployment(Target target, final DistributionSet ds) throws Exception {
throws Exception {
target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId())); target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId()));
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
.getContent().get(0); sendDeploymentActionFeedback(target, action, "closed", "failure")
sendDeploymentActionFeedback(target, action, "closed", "failure").andExpect(status().isOk()); .andExpect(status().isOk());
assertThatAttributesUpdateIsNotRequested(target.getControllerId()); assertThatAttributesUpdateIsNotRequested(target.getControllerId());
} }
@Step @Step
private void assertAttributesUpdateRequestedAfterSuccessfulDeployment(Target target, final DistributionSet ds) private void assertAttributesUpdateRequestedAfterSuccessfulDeployment(Target target, final DistributionSet ds) throws Exception {
throws Exception {
target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId())); target = getFirstAssignedTarget(assignDistributionSet(ds.getId(), target.getControllerId()));
final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()) final Action action = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
.getContent().get(0); sendDeploymentActionFeedback(target, action, "closed", null)
sendDeploymentActionFeedback(target, action, "closed", null).andExpect(status().isOk()); .andExpect(status().isOk());
assertThatAttributesUpdateIsRequested(target.getControllerId()); assertThatAttributesUpdateIsRequested(target.getControllerId());
} }
private void assertThatAttributesUpdateIsRequested(final String targetControllerId) throws Exception { private void assertThatAttributesUpdateIsRequested(final String targetControllerId) throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId) 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()); .andExpect(jsonPath("$._links.configData.href").isNotEmpty());
} }
private void assertThatAttributesUpdateIsNotRequested(final String targetControllerId) throws Exception { private void assertThatAttributesUpdateIsNotRequested(final String targetControllerId) throws Exception {
mvc.perform(get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), targetControllerId) 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()); .andExpect(jsonPath("$._links.configData").doesNotExist());
} }
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution, private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution, String finished,
String finished, String message) throws Exception { String message) throws Exception {
if (finished == null) { if (finished == null) {
finished = "none"; finished = "none";
} }
@@ -713,19 +771,18 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
.content(feedback).contentType(MediaType.APPLICATION_JSON)); .content(feedback).contentType(MediaType.APPLICATION_JSON));
} }
private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution, private ResultActions sendDeploymentActionFeedback(final Target target, final Action action, final String execution, final String finished)
final String finished) throws Exception { throws Exception {
return sendDeploymentActionFeedback(target, action, execution, finished, null); return sendDeploymentActionFeedback(target, action, execution, finished, null);
} }
private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId) private void assertDeploymentActionIsExposedToTarget(final String controllerId, final long expectedActionId) throws Exception {
throws Exception {
final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d", final String expectedDeploymentBaseLink = String.format("/%s/controller/v1/%s/deploymentBase/%d",
tenantAware.getCurrentTenant(), controllerId, expectedActionId); tenantAware.getCurrentTenant(), controllerId, expectedActionId);
mvc.perform( mvc.perform(
get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON)) get(CONTROLLER_BASE, tenantAware.getCurrentTenant(), controllerId).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink))); .andExpect(jsonPath("$._links.deploymentBase.href", containsString(expectedDeploymentBaseLink)));
} }
} }

View File

@@ -46,28 +46,26 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
@Override @Override
protected DefaultMockMvcBuilder createMvcWebAppContext(final WebApplicationContext context) { protected DefaultMockMvcBuilder createMvcWebAppContext(final WebApplicationContext context) {
return super.createMvcWebAppContext(context).addFilter( return super.createMvcWebAppContext(context).addFilter(
new DosFilter(null, 10, 10, new DosFilter(null, 10, 10, "127\\.0\\.0\\.1|\\[0:0:0:0:0:0:0:1\\]", "(^192\\.168\\.)", "X-Forwarded-For"));
"127\\.0\\.0\\.1|\\[0:0:0:0:0:0:0:1\\]", "(^192\\.168\\.)",
"X-Forwarded-For"));
} }
@Test @Test
@Description("Ensures that clients that are on the blacklist are forbidden") @Description("Ensures that clients that are on the blacklist are forbidden")
void blackListedClientIsForbidden() throws Exception { void blackListedClientIsForbidden() throws Exception {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) 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 @Test
@Description("Ensures that a READ DoS attempt is blocked ") @Description("Ensures that a READ DoS attempt is blocked ")
void getFloodingAttackThatIsPrevented() throws Exception { void getFloodingAttackThatIsPrevented() throws Exception {
MvcResult result = null;
int requests = 0; int requests = 0;
MvcResult result;
do { do {
result = mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) 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++; requests++;
// we give up after 1.000 requests // we give up after 1.000 requests
@@ -83,7 +81,8 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
void unacceptableGetLoadButOnWhitelistIPv4() throws Exception { void unacceptableGetLoadButOnWhitelistIPv4() throws Exception {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) 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 { void unacceptableGetLoadButOnWhitelistIPv6() throws Exception {
for (int i = 0; i < 100; i++) { for (int i = 0; i < 100; i++) {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) 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 @Test
@Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold") @Description("Ensures that a relatively high number of READ requests is allowed if it is below the DoS detection threshold")
// No idea how to get rid of the Thread.sleep here
@SuppressWarnings("squid:S2925") @SuppressWarnings("squid:S2925")
// No idea how to get rid of the Thread.sleep here
void acceptableGetLoad() throws Exception { void acceptableGetLoad() throws Exception {
for (int x = 0; x < 3; x++) { for (int x = 0; x < 3; x++) {
// sleep for one second // sleep for one second
Thread.sleep(1100); Thread.sleep(1100);
for (int i = 0; i < 9; i++) { for (int i = 0; i < 9; i++) {
mvc.perform(get("/{tenant}/controller/v1/4711", tenantAware.getCurrentTenant()) 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 Long actionId = prepareDeploymentBase();
final String feedback = getJsonProceedingDeploymentActionFeedback(); final String feedback = getJsonProceedingDeploymentActionFeedback();
MvcResult result = null;
int requests = 0; int requests = 0;
MvcResult result;
do { do {
result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback", result = mvc.perform(post("/{tenant}/controller/v1/4711/deploymentBase/" + actionId + "/feedback",
tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback) tenantAware.getCurrentTenant()).header(X_FORWARDED_FOR, "10.0.0.1").content(feedback)
@@ -133,13 +133,12 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
// the filter shuts down after 10 POST requests // the filter shuts down after 10 POST requests
assertThat(requests).isGreaterThanOrEqualTo(10); assertThat(requests).isGreaterThanOrEqualTo(10);
} }
@Test @Test
@Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold") @Description("Ensures that a relatively high number of WRITE requests is allowed if it is below the DoS detection threshold")
// No idea how to get rid of the Thread.sleep here
@SuppressWarnings("squid:S2925") @SuppressWarnings("squid:S2925")
// No idea how to get rid of the Thread.sleep here
void acceptablePutPostLoad() throws Exception { void acceptablePutPostLoad() throws Exception {
final Long actionId = prepareDeploymentBase(); final Long actionId = prepareDeploymentBase();
final String feedback = getJsonProceedingDeploymentActionFeedback(); final String feedback = getJsonProceedingDeploymentActionFeedback();
@@ -166,8 +165,7 @@ class DosFilterTest extends AbstractDDiApiIntegrationTest {
assignDistributionSet(ds, toAssign); assignDistributionSet(ds, toAssign);
assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(1); assertThat(deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId())).hasSize(1);
final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()) final Action uaction = deploymentManagement.findActiveActionsByTarget(PAGE, target.getControllerId()).getContent().get(0);
.getContent().get(0);
return uaction.getId(); return uaction.getId();
} }