diff --git a/.gitattributes b/.gitattributes
index 0825468a3..fd20d7edb 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -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
diff --git a/docs/src/main/resources/Binterfaces.md b/docs/src/main/resources/Binterfaces.md
index 3dd6d0ab4..8f8209e8f 100644
--- a/docs/src/main/resources/Binterfaces.md
+++ b/docs/src/main/resources/Binterfaces.md
@@ -4,11 +4,11 @@ title : "Interfaces"
series : "homepagetop"
sequence: "2"
order : 2
-imagename : "hawkBit_overview.png"
+imagename : "hawkBit_overview.jpeg"
style: "thumb1"
animatestyle: "fadeIn"
fadestyle: "fadeIn"
fadeduration: "4"
---
-hawkBit offers a direct device integration via HTTP or an device management federation API which allows you to connect devices with different protocol adapter. Users can make use of the graphical user interface and other service can interact with hawkBit through the RESTful management API.
\ No newline at end of file
+hawkBit offers a direct device integration via HTTP or an device management federation API which allows you to connect devices with different protocol adapter. Users can make use of the graphical user interface and other service can interact with hawkBit through the RESTful management API.
diff --git a/docs/src/main/resources/img/hawkBit_overview.jpeg b/docs/src/main/resources/img/hawkBit_overview.jpeg
new file mode 100644
index 000000000..c16b20d88
Binary files /dev/null and b/docs/src/main/resources/img/hawkBit_overview.jpeg differ
diff --git a/docs/src/main/resources/img/hawkBit_overview.png b/docs/src/main/resources/img/hawkBit_overview.png
deleted file mode 100644
index 3ad9813aa..000000000
Binary files a/docs/src/main/resources/img/hawkBit_overview.png and /dev/null differ
diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
index 5f2875e42..73610168e 100644
--- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
+++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
@@ -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:
diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java
index 8760f839b..8cda78fea 100644
--- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java
+++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiCancelActionTest.java
@@ -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))
diff --git a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
index 66a56378c..a56be2088 100644
--- a/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
+++ b/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageHandlerService.java
@@ -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());
diff --git a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java
index 26120d2d5..b629ee180 100644
--- a/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java
+++ b/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java
@@ -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;
diff --git a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java
index 5ef0e726c..716241ce1 100644
--- a/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java
+++ b/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java
@@ -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;
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java
index dd1ca4553..454c79919 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/exception/CancelActionNotAllowedException.java
@@ -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 {
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java
index 66659f2b1..5200510e4 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/Action.java
@@ -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;
}
/**
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java
index 68080312a..2a3dc126b 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaControllerManagement.java
@@ -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);
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java
index f9a469c8a..f1389606e 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/ControllerManagementTest.java
@@ -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 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 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 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 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);
+ }
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java
index 1c410ab35..24c9df37a 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/TargetManagementTest.java
@@ -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 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 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 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 testData = new HashMap<>();
testData.put("test1", "testdata1");
diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java
index 356e12e65..556be5fcc 100644
--- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java
+++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/AbstractIntegrationTest.java
@@ -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
diff --git a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java
index 645b749f1..fd9892a0b 100644
--- a/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java
+++ b/hawkbit-repository/hawkbit-repository-test/src/main/java/org/eclipse/hawkbit/repository/test/util/TestdataFactory.java
@@ -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;
}
/**
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java
index 3d9b39f15..0ef2635fb 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionHistoryTable.java
@@ -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 {
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionStatusIconMapper.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionStatusIconMapper.java
new file mode 100644
index 000000000..e8f75e52c
--- /dev/null
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/management/actionhistory/ActionStatusIconMapper.java
@@ -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 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;
+ }
+
+}
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java
index d7fd5216b..57791cfdd 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/SPUIStyleDefinitions.java
@@ -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.
*/