Fix cancel action status (#429)

* Fixed handling of action cancellation status updates.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix broken DDI test.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Code readibility.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Reduce access to default.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Added test for finished on action that is in cancelling.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Update MariaDb driver

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Wrong branch

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove duplicate status definition.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Use updated picture in docs.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Leverage existing statics.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix picture upload.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Revert change

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2017-02-07 09:57:57 +01:00
committed by GitHub
parent 21181bc6f8
commit 1ad9b915c4
19 changed files with 513 additions and 273 deletions

1
.gitattributes vendored
View File

@@ -2,6 +2,7 @@
# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.jpeg binary
*.pdf binary
*.PNG binary
*.pptx binary

View File

@@ -4,7 +4,7 @@ title : "Interfaces"
series : "homepagetop"
sequence: "2"
order : 2
imagename : "hawkBit_overview.png"
imagename : "hawkBit_overview.jpeg"
style: "thumb1"
animatestyle: "fadeIn"
fadestyle: "fadeIn"

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -439,7 +439,7 @@ public class DdiRootController implements DdiRootControllerRestApi {
case REJECTED:
LOG.info("Target rejected the cancelation request (actionid: {}, controllerId: {}).", actionid,
target.getControllerId());
status = Status.WARNING;
status = Status.CANCEL_REJECTED;
messages.add(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Target rejected the cancelation request.");
break;
case CLOSED:

View File

@@ -276,7 +276,7 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(5);
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId())).hasSize(1);
// cancelation canceled -> should remove the action from active
// cancellation canceled -> should remove the action from active
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId())).hasSize(1);
current = System.currentTimeMillis();
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
@@ -289,7 +289,8 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(6);
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId())).hasSize(1);
// cancelation rejected -> action still active until controller close it
// cancellation rejected -> action still active until controller close
// it
// with finished or
// error
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId())).hasSize(1);
@@ -304,9 +305,9 @@ public class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
assertThat(deploymentManagement.countActionStatusAll()).isEqualTo(7);
assertThat(deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId())).hasSize(1);
// cancelaction closed -> should remove the action from active
// update closed -> should remove the action from active
current = System.currentTimeMillis();
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/cancelAction/"
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"
+ cancelAction.getId() + "/feedback", tenantAware.getCurrentTenant())
.content(JsonBuilder.cancelActionFeedback(cancelAction.getId().toString(), "closed"))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))

View File

@@ -294,7 +294,7 @@ public class AmqpMessageHandlerService extends BaseAmqpService {
private Status hanldeCancelRejectedState(final Message message, final Action action) {
if (action.isCancelingOrCanceled()) {
return Status.WARNING;
return Status.CANCEL_REJECTED;
} else {
logAndThrowMessageError(message,
"Cancel recjected message is not allowed, if action is on state: " + action.getStatus());

View File

@@ -23,40 +23,6 @@ import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown = true)
public class MgmtActionStatus {
/**
* Action is finished successfully for this target.
*/
public static final String AS_FINISHED = "finished";
/**
* Action has failed for this target.
*/
public static final String AS_ERROR = "error";
/**
* Action is still running but with warnings.
*/
public static final String AS_WARNING = "warning";
/**
* Action is still running for this target.
*/
public static final String AS_RUNNING = "running";
/**
* Action has been canceled for this target.
*/
public static final String AS_CANCELED = "canceled";
/**
* Action has been presented to the target.
*/
public static final String AS_RETRIEVED = "retrieved";
/**
* Action has been canceled for this target.
*/
public static final String AS_CANCELING = "canceling";
@JsonProperty("id")
private Long statusId;

View File

@@ -34,7 +34,6 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.rest.data.ResponseList;
import org.eclipse.hawkbit.rest.data.SortDirection;
import org.eclipse.hawkbit.util.IpUtil;
@@ -112,7 +111,7 @@ public final class MgmtTargetMapper {
targetRest.setControllerId(target.getControllerId());
targetRest.setDescription(target.getDescription());
targetRest.setName(target.getName());
targetRest.setUpdateStatus(getUpdateStatusName(target.getTargetInfo().getUpdateStatus()));
targetRest.setUpdateStatus(target.getTargetInfo().getUpdateStatus().name().toLowerCase());
final URI address = target.getTargetInfo().getAddress();
if (address != null) {
@@ -198,37 +197,6 @@ public final class MgmtTargetMapper {
.collect(Collectors.toList());
}
private static String getNameOfActionStatusType(final Action.Status type) {
String result;
switch (type) {
case CANCELED:
result = MgmtActionStatus.AS_CANCELED;
break;
case ERROR:
result = MgmtActionStatus.AS_ERROR;
break;
case FINISHED:
result = MgmtActionStatus.AS_FINISHED;
break;
case RETRIEVED:
result = MgmtActionStatus.AS_RETRIEVED;
break;
case RUNNING:
result = MgmtActionStatus.AS_RUNNING;
break;
case WARNING:
result = MgmtActionStatus.AS_WARNING;
break;
default:
return type.name().toLowerCase();
}
return result;
}
private static String getType(final Action action) {
if (!action.isCancelingOrCanceled()) {
return MgmtAction.ACTION_UPDATE;
@@ -239,39 +207,13 @@ public final class MgmtTargetMapper {
return null;
}
private static String getUpdateStatusName(final TargetUpdateStatus updatestatus) {
String result;
switch (updatestatus) {
case ERROR:
result = "error";
break;
case IN_SYNC:
result = "in_sync";
break;
case PENDING:
result = "pending";
break;
case REGISTERED:
result = "registered";
break;
case UNKNOWN:
result = "unknown";
break;
default:
return updatestatus.name().toLowerCase();
}
return result;
}
private static MgmtActionStatus toResponse(final ActionStatus actionStatus) {
final MgmtActionStatus result = new MgmtActionStatus();
result.setMessages(actionStatus.getMessages());
result.setReportedAt(actionStatus.getCreatedAt());
result.setStatusId(actionStatus.getId());
result.setType(getNameOfActionStatusType(actionStatus.getStatus()));
result.setType(actionStatus.getStatus().name().toLowerCase());
return result;
}

View File

@@ -12,11 +12,10 @@ import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if cancelation of actions is performened where the action is not
* cancelable, e.g. the action is not active or is already a cancel action.
*
*
*
* Thrown if cancellation of action is requested where the action cannot be
* cancelled (e.g. the action is not active or is already a canceled action) or
* controller provides cancellation feedback on an action that is actually not
* in caneling state.
*
*/
public final class CancelActionNotAllowedException extends AbstractServerRtException {

View File

@@ -172,7 +172,12 @@ public interface Action extends TenantAwareBaseEntity {
* Action is in waiting state, e.g. the action is scheduled in a rollout
* but not yet activated.
*/
SCHEDULED;
SCHEDULED,
/**
* Cancellation has been rejected by the controller.
*/
CANCEL_REJECTED;
}
/**

View File

@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.repository.builder.ActionStatusCreate;
import org.eclipse.hawkbit.repository.event.remote.DownloadProgressEvent;
import org.eclipse.hawkbit.repository.event.remote.TargetPollEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.ToManyAttributeEntriesException;
import org.eclipse.hawkbit.repository.exception.TooManyStatusEntriesException;
@@ -101,9 +102,6 @@ public class JpaControllerManagement implements ControllerManagement {
@Autowired
private RepositoryProperties repositoryProperties;
@Autowired
private TenantConfigurationRepository tenantConfigurationRepository;
@Autowired
private TenantConfigurationManagement tenantConfigurationManagement;
@@ -242,26 +240,29 @@ public class JpaControllerManagement implements ControllerManagement {
final JpaActionStatusCreate create = (JpaActionStatusCreate) c;
final JpaAction action = getActionAndThrowExceptionIfNotFound(create.getActionId());
if (!action.isCancelingOrCanceled()) {
throw new CancelActionNotAllowedException("The action is not in canceling state.");
}
final JpaActionStatus actionStatus = create.build();
checkForToManyStatusEntries(action);
action.setStatus(actionStatus.getStatus());
switch (actionStatus.getStatus()) {
case WARNING:
case ERROR:
case RUNNING:
break;
case CANCELED:
case FINISHED:
handleFinishedCancelation(actionStatus, action);
break;
case RETRIEVED:
actionStatus.addMessage(RepositoryConstants.SERVER_MESSAGE_PREFIX + "Cancellation request retrieved.");
case ERROR:
case CANCEL_REJECTED:
// Cancellation rejected. Back to running.
action.setStatus(Status.RUNNING);
break;
default:
// do nothing
// information status entry - check for a potential DOS attack
checkForToManyStatusEntries(action);
break;
}
actionStatus.setAction(actionRepository.save(action));
actionStatusRepository.save(actionStatus);
@@ -306,17 +307,11 @@ public class JpaControllerManagement implements ControllerManagement {
/**
* Sets {@link TargetUpdateStatus} based on given {@link ActionStatus}.
*
* @param actionStatus
* @param action
* @return
*/
private Action handleAddUpdateActionStatus(final JpaActionStatus actionStatus, final JpaAction action) {
LOG.debug("addUpdateActionStatus for action {}", action.getId());
JpaTarget target = (JpaTarget) action.getTarget();
// check for a potential DOS attack
checkForToManyStatusEntries(action);
switch (actionStatus.getStatus()) {
case ERROR:
@@ -327,10 +322,9 @@ public class JpaControllerManagement implements ControllerManagement {
case FINISHED:
handleFinishedAndStoreInTargetStatus(target, action);
break;
case CANCELED:
case WARNING:
case RUNNING:
default:
// information status entry - check for a potential DOS attack
checkForToManyStatusEntries(action);
break;
}
@@ -339,8 +333,6 @@ public class JpaControllerManagement implements ControllerManagement {
LOG.debug("addUpdateActionStatus {} for target {} is finished.", action, target.getId());
action.setStatus(actionStatus.getStatus());
return actionRepository.save(action);
}

View File

@@ -12,6 +12,8 @@ import static org.fest.assertions.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import java.io.ByteArrayInputStream;
import java.util.List;
import java.util.Map;
import javax.validation.ConstraintViolationException;
@@ -20,13 +22,15 @@ import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.ActionUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.CancelTargetAssignmentEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.DistributionSetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.SoftwareModuleUpdatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetCreatedEvent;
import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.Target;
@@ -37,8 +41,11 @@ import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import com.google.common.collect.Maps;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Step;
import ru.yandex.qatools.allure.annotations.Stories;
@Features("Component Tests - Repository")
@@ -49,40 +56,256 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
private RepositoryProperties repositoryProperties;
@Test
@Description("Controller adds a new action status.")
@Description("Controller confirms successfull update with FINISHED status.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void controllerAddsActionStatus() {
final DistributionSet ds = testdataFactory.createDistributionSet("");
Target savedTarget = testdataFactory.createTarget();
public void controllerConfirmsUpdateWithFinished() {
final Long actionId = createTargetAndAssignDs();
assertThat(savedTarget.getTargetInfo().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
simulateIntermediateStatusOnUpdate(actionId);
savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator()
.next();
final JpaAction savedAction = (JpaAction) deploymentManagement
.findActiveActionsByTarget(savedTarget.getControllerId()).get(0);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
Action.Status.FINISHED, Action.Status.FINISHED, false);
assertThat(targetManagement.findTargetByControllerID(savedTarget.getControllerId()).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
assertThat(actionStatusRepository.count()).isEqualTo(6);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(6);
}
controllerManagament.addUpdateActionStatus(
entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.RUNNING));
@Test
@Description("Controller confirms successfull update with FINISHED status on a action that is on canceling. "
+ "Reason: The decission to ignore the cancellation is in fact up to the controller.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void controllerConfirmsUpdateWithFinishedAndIgnorsCancellationWithThat() {
final Long actionId = createTargetAndAssignDs();
deploymentManagement.cancelAction(actionId);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
Action.Status.FINISHED, Action.Status.FINISHED, false);
assertThat(actionStatusRepository.count()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(3);
}
@Test
@Description("Update server rejects cancelation feedback if action is not in CANCELING state.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = TargetUpdatedEvent.class, count = 1),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void cancellationFeedbackRejectedIfActionIsNotInCanceling() {
final Long actionId = createTargetAndAssignDs();
try {
controllerManagament.addCancelActionStatus(
entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
fail("Expected " + CancelActionNotAllowedException.class.getName());
} catch (final CancelActionNotAllowedException e) {
// expected
}
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.RUNNING, true);
assertThat(actionStatusRepository.count()).isEqualTo(1);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(1);
}
@Test
@Description("Controller confirms action cancelation with FINISHED status.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void controllerConfirmsActionCancelationWithFinished() {
final Long actionId = createTargetAndAssignDs();
deploymentManagement.cancelAction(actionId);
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.CANCELING, true);
simulateIntermediateStatusOnCancellation(actionId);
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
Action.Status.CANCELED, Action.Status.FINISHED, false);
assertThat(actionStatusRepository.count()).isEqualTo(7);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(7);
}
@Test
@Description("Controller confirms action cancelation with FINISHED status.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void controllerConfirmsActionCancelationWithCanceled() {
final Long actionId = createTargetAndAssignDs();
deploymentManagement.cancelAction(actionId);
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.CANCELING, true);
simulateIntermediateStatusOnCancellation(actionId);
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.CANCELED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
Action.Status.CANCELED, Action.Status.CANCELED, false);
assertThat(actionStatusRepository.count()).isEqualTo(7);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(7);
}
@Test
@Description("Controller rejects action cancelation with CANCEL_REJECTED status. Action goes back to RUNNING status as it expects "
+ "that the controller will continue the original update.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 1),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void controllerRejectsActionCancelationWithReject() {
final Long actionId = createTargetAndAssignDs();
deploymentManagement.cancelAction(actionId);
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.CANCELING, true);
simulateIntermediateStatusOnCancellation(actionId);
controllerManagament.addCancelActionStatus(
entityFactory.actionStatus().create(actionId).status(Action.Status.CANCEL_REJECTED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.CANCEL_REJECTED, true);
assertThat(actionStatusRepository.count()).isEqualTo(7);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(7);
}
@Test
@Description("Controller rejects action cancelation with ERROR status. Action goes back to RUNNING status as it expects "
+ "that the controller will continue the original update.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 2),
@Expect(type = TargetUpdatedEvent.class, count = 1),
@Expect(type = CancelTargetAssignmentEvent.class, count = 1),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void controllerRejectsActionCancelationWithError() {
final Long actionId = createTargetAndAssignDs();
deploymentManagement.cancelAction(actionId);
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.CANCELING, true);
simulateIntermediateStatusOnCancellation(actionId);
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.ERROR));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.ERROR, true);
assertThat(actionStatusRepository.count()).isEqualTo(7);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(7);
}
@Step
private Long createTargetAndAssignDs() {
final Long dsId = testdataFactory.createDistributionSet().getId();
testdataFactory.createTarget();
assignDistributionSet(dsId, TestdataFactory.DEFAULT_CONTROLLER_ID);
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
controllerManagament.addUpdateActionStatus(
entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.FINISHED));
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC);
return deploymentManagement.findActiveActionsByTarget(TestdataFactory.DEFAULT_CONTROLLER_ID).get(0).getId();
}
@Step
private void simulateIntermediateStatusOnCancellation(final Long actionId) {
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.RUNNING, true);
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.DOWNLOAD, true);
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.RETRIEVED, true);
controllerManagament
.addCancelActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.CANCELING, Action.Status.WARNING, true);
}
@Step
private void simulateIntermediateStatusOnUpdate(final Long actionId) {
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.RUNNING, true);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.DOWNLOAD));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.DOWNLOAD, true);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RETRIEVED));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.RETRIEVED, true);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.WARNING));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.WARNING, true);
}
private void assertActionStatus(final Long actionId, final String controllerId,
final TargetUpdateStatus expectedTargetUpdateStatus, final Action.Status expectedActionActionStatus,
final Action.Status expectedActionStatus, final boolean actionActive) {
final TargetUpdateStatus targetStatus = targetManagement.findTargetByControllerID(controllerId).getTargetInfo()
.getUpdateStatus();
assertThat(targetStatus).isEqualTo(expectedTargetUpdateStatus);
final Action action = deploymentManagement.findAction(actionId);
assertThat(action.getStatus()).isEqualTo(expectedActionActionStatus);
assertThat(action.isActive()).isEqualTo(actionActive);
final List<ActionStatus> actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, actionId)
.getContent();
assertThat(actionStatusList.get(actionStatusList.size() - 1).getStatus()).isEqualTo(expectedActionStatus);
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction.getId()).getNumberOfElements())
.isEqualTo(3);
}
@Test
@@ -123,7 +346,7 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
@Test
@Description("Register a controller which does not exist")
public void testfindOrRegisterTargetIfItDoesNotexist() {
public void findOrRegisterTargetIfItDoesNotexist() {
final Target target = controllerManagament.findOrRegisterTargetIfItDoesNotexist("AA", null);
assertThat(target).as("target should not be null").isNotNull();
@@ -142,47 +365,94 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
@Test
@Description("Controller trys to finish an update process after it has been finished by an error action status.")
public void tryToFinishUpdateProcessMoreThanOnce() {
final DistributionSet ds = testdataFactory.createDistributionSet("");
Target savedTarget = testdataFactory.createTarget();
savedTarget = assignDistributionSet(ds.getId(), savedTarget.getControllerId()).getAssignedEntity().iterator()
.next();
Action savedAction = deploymentManagement.findActiveActionsByTarget(savedTarget.getControllerId()).get(0);
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void tryToFinishWithErrorUpdateProcessMoreThanOnce() {
final Long actionId = createTargetAndAssignDs();
// test and verify
savedAction = controllerManagament.addUpdateActionStatus(
entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.RUNNING));
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.PENDING);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.RUNNING));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.PENDING,
Action.Status.RUNNING, Action.Status.RUNNING, true);
savedAction = controllerManagament.addUpdateActionStatus(
entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.ERROR));
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.ERROR);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.ERROR));
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
Action.Status.ERROR, Action.Status.ERROR, false);
// try with disabled late feedback
repositoryProperties.setRejectActionStatusForClosedAction(true);
savedAction = controllerManagament.addUpdateActionStatus(
entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.FINISHED));
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
// test
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.ERROR);
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
Action.Status.ERROR, Action.Status.ERROR, false);
// try with enabled late feedback
// try with enabled late feedback - should not make a difference as it
// only allows intermediate feedbacks and not multiple close
repositoryProperties.setRejectActionStatusForClosedAction(false);
controllerManagament.addUpdateActionStatus(
entityFactory.actionStatus().create(savedAction.getId()).status(Action.Status.FINISHED));
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
// test
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.ERROR);
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.ERROR,
Action.Status.ERROR, Action.Status.ERROR, false);
assertThat(actionStatusRepository.count()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(3);
}
@Test
@Description("Controller trys to finish an update process after it has been finished by an FINISHED action status.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void tryToFinishUpdateProcessMoreThanOnce() {
final Long actionId = prepareFinishedUpdate().getId();
// try with disabled late feedback
repositoryProperties.setRejectActionStatusForClosedAction(true);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
// test
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
Action.Status.FINISHED, Action.Status.FINISHED, false);
// try with enabled late feedback - should not make a difference as it
// only allows intermediate feedbacks and not multiple close
repositoryProperties.setRejectActionStatusForClosedAction(false);
controllerManagament
.addUpdateActionStatus(entityFactory.actionStatus().create(actionId).status(Action.Status.FINISHED));
// test
assertActionStatus(actionId, TestdataFactory.DEFAULT_CONTROLLER_ID, TargetUpdateStatus.IN_SYNC,
Action.Status.FINISHED, Action.Status.FINISHED, false);
assertThat(actionStatusRepository.count()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, actionId).getNumberOfElements()).isEqualTo(3);
}
@Test
@Description("Controller trys to send an update feedback after it has been finished which is reject as the repository is "
+ "configured to reject that.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void sendUpdatesForFinishUpdateProcessDropedIfDisabled() {
repositoryProperties.setRejectActionStatusForClosedAction(true);
@@ -194,14 +464,21 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
// nothing changed as "feedback after close" is disabled
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC);
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
assertThat(actionStatusRepository.count()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, action.getId()).getNumberOfElements())
.isEqualTo(3);
}
@Test
@Description("Controller trys to send an update feedback after it has been finished which is actepted as the repository is "
@Description("Controller trys to send an update feedback after it has been finished which is accepted as the repository is "
+ "configured to accept them.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = DistributionSetCreatedEvent.class, count = 1),
@Expect(type = ActionCreatedEvent.class, count = 1), @Expect(type = ActionUpdatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 2),
@Expect(type = TargetAssignDistributionSetEvent.class, count = 1),
@Expect(type = SoftwareModuleCreatedEvent.class, count = 3) })
public void sendUpdatesForFinishUpdateProcessAcceptedIfEnabled() {
repositoryProperties.setRejectActionStatusForClosedAction(false);
@@ -212,9 +489,58 @@ public class ControllerManagementTest extends AbstractJpaIntegrationTest {
// nothing changed as "feedback after close" is disabled
assertThat(targetManagement.findTargetByControllerID(TestdataFactory.DEFAULT_CONTROLLER_ID).getTargetInfo()
.getUpdateStatus()).isEqualTo(TargetUpdateStatus.IN_SYNC);
// however, additional action status has been stored
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(4);
assertThat(deploymentManagement.findActionStatusByAction(pageReq, action.getId()).getNumberOfElements())
.isEqualTo(4);
}
@Test
@Description("Ensures that target attribute update is reflected by the repository.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 3) })
public void updateTargetAttributes() {
final String controllerId = "test123";
testdataFactory.createTarget(controllerId);
addAttributeAndVerify(controllerId);
addSecondAttributeAndVerify(controllerId);
updateAttributeAndVerify(controllerId);
}
@Step
private void addAttributeAndVerify(final String controllerId) {
final Map<String, String> testData = Maps.newHashMapWithExpectedSize(1);
testData.put("test1", "testdata1");
controllerManagament.updateControllerAttributes(controllerId, testData);
final Target target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
.isEqualTo(testData);
}
@Step
private void addSecondAttributeAndVerify(final String controllerId) {
final Map<String, String> testData = Maps.newHashMapWithExpectedSize(2);
testData.put("test2", "testdata20");
controllerManagament.updateControllerAttributes(controllerId, testData);
final Target target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
testData.put("test1", "testdata1");
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
.isEqualTo(testData);
}
@Step
private void updateAttributeAndVerify(final String controllerId) {
final Map<String, String> testData = Maps.newHashMapWithExpectedSize(2);
testData.put("test1", "testdata12");
controllerManagament.updateControllerAttributes(controllerId, testData);
final Target target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
testData.put("test2", "testdata20");
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
.isEqualTo(testData);
}
}

View File

@@ -54,11 +54,9 @@ import org.springframework.data.domain.PageRequest;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import ru.yandex.qatools.allure.annotations.Description;
import ru.yandex.qatools.allure.annotations.Features;
import ru.yandex.qatools.allure.annotations.Step;
import ru.yandex.qatools.allure.annotations.Stories;
@Features("Component Tests - Repository")
@@ -245,54 +243,6 @@ public class TargetManagementTest extends AbstractJpaIntegrationTest {
assertThat(targetManagement.countTargetsAll()).as("target count is wrong").isEqualTo(0);
}
@Test
@Description("Ensures that target attribute update is reflected by the repository.")
@ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1),
@Expect(type = TargetUpdatedEvent.class, count = 3) })
public void updateTargetAttributes() {
final String controllerId = "test123";
testdataFactory.createTarget(controllerId);
addAttributeAndVerify(controllerId);
addSecondAttributeAndVerify(controllerId);
updateAttributeAndVerify(controllerId);
}
@Step
private void addAttributeAndVerify(final String controllerId) {
final Map<String, String> testData = Maps.newHashMapWithExpectedSize(1);
testData.put("test1", "testdata1");
controllerManagament.updateControllerAttributes(controllerId, testData);
final Target target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
.isEqualTo(testData);
}
@Step
private void addSecondAttributeAndVerify(final String controllerId) {
final Map<String, String> testData = Maps.newHashMapWithExpectedSize(2);
testData.put("test2", "testdata20");
controllerManagament.updateControllerAttributes(controllerId, testData);
final Target target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
testData.put("test1", "testdata1");
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
.isEqualTo(testData);
}
@Step
private void updateAttributeAndVerify(final String controllerId) {
final Map<String, String> testData = Maps.newHashMapWithExpectedSize(2);
testData.put("test1", "testdata12");
controllerManagament.updateControllerAttributes(controllerId, testData);
final Target target = targetManagement.findTargetByControllerIDWithDetails(controllerId);
testData.put("test2", "testdata20");
assertThat(target.getTargetInfo().getControllerAttributes()).as("Controller Attributes are wrong")
.isEqualTo(testData);
}
private Target createTargetWithAttributes(final String controllerId) {
final Map<String, String> testData = new HashMap<>();
testData.put("test1", "testdata1");

View File

@@ -78,6 +78,8 @@ import org.springframework.core.env.Environment;
import org.springframework.data.auditing.AuditingHandler;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.hateoas.MediaTypes;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
@@ -104,7 +106,7 @@ import com.google.common.collect.Lists;
public abstract class AbstractIntegrationTest implements EnvironmentAware {
private static final Logger LOG = LoggerFactory.getLogger(AbstractIntegrationTest.class);
protected static final Pageable pageReq = new PageRequest(0, 400);
protected static final Pageable pageReq = new PageRequest(0, 400, new Sort(Direction.ASC, "id"));
/**
* Constant for MediaType HAL with encoding UTF-8. Necessary since Spring

View File

@@ -8,6 +8,8 @@
*/
package org.eclipse.hawkbit.repository.test.util;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.security.SecureRandom;
@@ -44,6 +46,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
@@ -498,7 +501,9 @@ public class TestdataFactory {
* @return persisted {@link Target}
*/
public Target createTarget(final String controllerId) {
return targetManagement.createTarget(entityFactory.target().create().controllerId(controllerId));
final Target target = targetManagement.createTarget(entityFactory.target().create().controllerId(controllerId));
assertThat(target.getTargetInfo().getUpdateStatus()).isEqualTo(TargetUpdateStatus.UNKNOWN);
return target;
}
/**

View File

@@ -33,6 +33,7 @@ import org.eclipse.hawkbit.ui.management.state.ManagementUIState;
import org.eclipse.hawkbit.ui.utils.I18N;
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
import org.slf4j.Logger;
@@ -72,7 +73,6 @@ public class ActionHistoryTable extends TreeTable {
private static final Logger LOG = LoggerFactory.getLogger(ActionHistoryTable.class);
private static final String BUTTON_CANCEL = "button.cancel";
private static final String BUTTON_OK = "button.ok";
private static final String STATUS_ICON_GREEN = "statusIconGreen";
private final I18N i18n;
private final transient DeploymentManagement deploymentManagement;
@@ -504,50 +504,21 @@ public class ActionHistoryTable extends TreeTable {
*/
private Label getStatusIcon(final Action.Status status) {
final Label label = new LabelBuilder().name("").buildLabel();
final String statusIconPending = "statusIconPending";
label.setContentMode(ContentMode.HTML);
if (Action.Status.FINISHED == status) {
label.setDescription(i18n.get("label.finished"));
label.setStyleName(STATUS_ICON_GREEN);
label.setValue(FontAwesome.CHECK_CIRCLE.getHtml());
} else if (Action.Status.ERROR == status) {
label.setDescription(i18n.get("label.error"));
label.setStyleName("statusIconRed");
label.setValue(FontAwesome.EXCLAMATION_CIRCLE.getHtml());
} else if (Action.Status.WARNING == status) {
label.setStyleName("statusIconOrange");
label.setDescription(i18n.get("label.warning"));
label.setValue(FontAwesome.EXCLAMATION_CIRCLE.getHtml());
} else if (Action.Status.RUNNING == status) {
// dynamic spinner
label.setStyleName(statusIconPending);
label.setDescription(i18n.get("label.running"));
label.setValue(FontAwesome.ADJUST.getHtml());
} else if (Action.Status.CANCELING == status) {
label.setStyleName(statusIconPending);
label.setDescription(i18n.get("label.cancelling"));
label.setValue(FontAwesome.TIMES_CIRCLE.getHtml());
} else if (Action.Status.CANCELED == status) {
label.setStyleName(statusIconPending);
label.setDescription(i18n.get("label.cancelled"));
label.setStyleName(STATUS_ICON_GREEN);
label.setValue(FontAwesome.TIMES_CIRCLE.getHtml());
} else if (Action.Status.RETRIEVED == status) {
label.setStyleName(statusIconPending);
label.setDescription(i18n.get("label.retrieved"));
label.setValue(FontAwesome.CIRCLE_O.getHtml());
} else if (Action.Status.DOWNLOAD == status) {
label.setStyleName(statusIconPending);
label.setDescription(i18n.get("label.download"));
label.setValue(FontAwesome.CLOUD_DOWNLOAD.getHtml());
} else if (Action.Status.SCHEDULED == status) {
label.setStyleName(statusIconPending);
label.setDescription(i18n.get("label.scheduled"));
label.setValue(FontAwesome.HOURGLASS_1.getHtml());
} else {
final ActionStatusIconMapper mapping = ActionStatusIconMapper.MAPPINGS.get(status);
if (mapping == null) {
LOG.error("Unknown status icon mapping");
label.setDescription("");
label.setValue("");
return label;
}
label.setDescription(i18n.get(mapping.getDescriptionI18N()));
label.setStyleName(mapping.getStyleName());
label.setValue(mapping.getIcon().getHtml());
return label;
}
@@ -568,7 +539,7 @@ public class ActionHistoryTable extends TreeTable {
if (actionWithActiveStatus.isHitAutoForceTime(currentTimeMillis)) {
autoForceLabel.setDescription("autoforced");
autoForceLabel.setStyleName(STATUS_ICON_GREEN);
autoForceLabel.setStyleName(SPUIStyleDefinitions.STATUS_ICON_GREEN);
autoForceLabel.setDescription("auto forced since " + SPDateTimeUtil
.getDurationFormattedString(actionWithActiveStatus.getForcedTime(), currentTimeMillis, i18n));
} else {

View File

@@ -0,0 +1,75 @@
/**
* Copyright (c) 2015 Bosch Software Innovations GmbH and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.hawkbit.ui.management.actionhistory;
import java.util.Map;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
import com.google.common.collect.Maps;
import com.vaadin.server.FontAwesome;
/**
* Mapping utility for {@link ActionStatus} to icon in action history table.
*
*/
public final class ActionStatusIconMapper {
static final Map<Action.Status, ActionStatusIconMapper> MAPPINGS = Maps.newHashMapWithExpectedSize(10);
static {
MAPPINGS.put(Action.Status.FINISHED, new ActionStatusIconMapper("label.finished",
SPUIStyleDefinitions.STATUS_ICON_GREEN, FontAwesome.CHECK_CIRCLE));
MAPPINGS.put(Action.Status.CANCELED, new ActionStatusIconMapper("label.cancelled",
SPUIStyleDefinitions.STATUS_ICON_GREEN, FontAwesome.TIMES_CIRCLE));
MAPPINGS.put(Action.Status.ERROR, new ActionStatusIconMapper("label.error",
SPUIStyleDefinitions.STATUS_ICON_RED, FontAwesome.EXCLAMATION_CIRCLE));
MAPPINGS.put(Action.Status.WARNING, new ActionStatusIconMapper("label.warning",
SPUIStyleDefinitions.STATUS_ICON_ORANGE, FontAwesome.EXCLAMATION_CIRCLE));
MAPPINGS.put(Action.Status.CANCEL_REJECTED, new ActionStatusIconMapper("label.warning",
SPUIStyleDefinitions.STATUS_ICON_ORANGE, FontAwesome.EXCLAMATION_CIRCLE));
MAPPINGS.put(Action.Status.RUNNING, new ActionStatusIconMapper("label.running",
SPUIStyleDefinitions.STATUS_ICON_PENDING, FontAwesome.ADJUST));
MAPPINGS.put(Action.Status.CANCELING, new ActionStatusIconMapper("label.cancelling",
SPUIStyleDefinitions.STATUS_ICON_PENDING, FontAwesome.TIMES_CIRCLE));
MAPPINGS.put(Action.Status.RETRIEVED, new ActionStatusIconMapper("label.retrieved",
SPUIStyleDefinitions.STATUS_ICON_PENDING, FontAwesome.CIRCLE_O));
MAPPINGS.put(Action.Status.DOWNLOAD, new ActionStatusIconMapper("label.download",
SPUIStyleDefinitions.STATUS_ICON_PENDING, FontAwesome.CLOUD_DOWNLOAD));
MAPPINGS.put(Action.Status.SCHEDULED, new ActionStatusIconMapper("label.scheduled",
SPUIStyleDefinitions.STATUS_ICON_PENDING, FontAwesome.HOURGLASS_1));
}
private final String descriptionI18N;
private final String styleName;
private final FontAwesome icon;
private ActionStatusIconMapper(final String descriptionI18N, final String styleName, final FontAwesome icon) {
this.descriptionI18N = descriptionI18N;
this.styleName = styleName;
this.icon = icon;
}
String getDescriptionI18N() {
return descriptionI18N;
}
String getStyleName() {
return styleName;
}
FontAwesome getIcon() {
return icon;
}
}

View File

@@ -183,6 +183,11 @@ public final class SPUIStyleDefinitions {
*/
public static final String STATUS_ICON_RED = "statusIconRed";
/**
* Status icon style - orange color.
*/
public static final String STATUS_ICON_ORANGE = "statusIconOrange";
/**
* Status icon style - green color.
*/