Merge pull request #64 from bsinno/mgmtapi-shows-wrong-status-content

👍 ok merging
This commit is contained in:
Michael Hirsch
2016-03-04 09:23:46 +01:00
10 changed files with 179 additions and 111 deletions

View File

@@ -20,7 +20,12 @@ public enum ActionStatusFields implements FieldNameProvider {
/** /**
* The id field. * The id field.
*/ */
ID("id"); ID("id"),
/**
* The reportedAt field.
*/
REPORTEDAT("createdAt");
private final String fieldName; private final String fieldName;

View File

@@ -21,45 +21,47 @@ import org.springframework.transaction.annotation.Transactional;
/** /**
* {@link ActionStatus} repository. * {@link ActionStatus} repository.
* *
*
*
*
*/ */
@Transactional(readOnly = true) @Transactional(readOnly = true)
public interface ActionStatusRepository public interface ActionStatusRepository
extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> { extends BaseEntityRepository<ActionStatus, Long>, JpaSpecificationExecutor<ActionStatus> {
/** /**
* @param target * Counts {@link ActionStatus} entries of given {@link Action} in
* repository.
*
* @param action * @param action
* @return * to count status entries
* @return number of actions in repository
*/ */
Long countByAction(Action action); Long countByAction(Action action);
/** /**
* Counts {@link ActionStatus} entries of given {@link Action} with given
* {@link Status} in repository.
*
* @param action * @param action
* @param retrieved * to count status entries
* @return * @param status
* to filter for
* @return number of actions in repository
*/ */
Long countByActionAndStatus(Action action, Status retrieved); Long countByActionAndStatus(Action action, Status status);
/** /**
* Retrieves all {@link ActionStatus} entries from repository of given
* {@link Action}.
*
* @param pageReq * @param pageReq
* parameters
* @param action * @param action
* @return * of the status entries
* @return pages list of {@link ActionStatus} entries
*/ */
Page<ActionStatus> findByAction(Pageable pageReq, Action action); Page<ActionStatus> findByAction(Pageable pageReq, Action action);
/** /**
* @param pageReq * Finds all status updates for the defined action and target including
* @param action
* @return
*/
Page<ActionStatus> findByActionOrderByIdDesc(Pageable pageReq, Action action);
/**
* Finds all status updates for the defined action and target order by
* {@link ActionStatus#getId()} desc including
* {@link ActionStatus#getMessages()}. * {@link ActionStatus#getMessages()}.
* *
* @param pageReq * @param pageReq
@@ -71,6 +73,6 @@ public interface ActionStatusRepository
* @return Page with found targets * @return Page with found targets
*/ */
@EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD) @EntityGraph(value = "ActionStatus.withMessages", type = EntityGraphType.LOAD)
Page<ActionStatus> getByActionOrderByIdDesc(Pageable pageReq, Action action); Page<ActionStatus> getByAction(Pageable pageReq, Action action);
} }

View File

@@ -925,7 +925,7 @@ public class DeploymentManagement {
/** /**
* retrieves all the {@link ActionStatus} entries of the given * retrieves all the {@link ActionStatus} entries of the given
* {@link Action} and {@link Target} in the order latest first. * {@link Action} and {@link Target}.
* *
* @param pageReq * @param pageReq
* pagination parameter * pagination parameter
@@ -937,12 +937,12 @@ public class DeploymentManagement {
* @return the corresponding {@link Page} of {@link ActionStatus} * @return the corresponding {@link Page} of {@link ActionStatus}
*/ */
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
public Page<ActionStatus> findActionStatusMessagesByActionInDescOrder(final Pageable pageReq, final Action action, public Page<ActionStatus> findActionStatusByAction(final Pageable pageReq, final Action action,
final boolean withMessages) { final boolean withMessages) {
if (withMessages) { if (withMessages) {
return actionStatusRepository.getByActionOrderByIdDesc(pageReq, action); return actionStatusRepository.getByAction(pageReq, action);
} else { } else {
return actionStatusRepository.findByActionOrderByIdDesc(pageReq, action); return actionStatusRepository.findByAction(pageReq, action);
} }
} }

View File

@@ -70,8 +70,8 @@ public class ControllerManagementTest extends AbstractIntegrationTest {
.isEqualTo(TargetUpdateStatus.IN_SYNC); .isEqualTo(TargetUpdateStatus.IN_SYNC);
assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3); assertThat(actionStatusRepository.findAll(pageReq).getNumberOfElements()).isEqualTo(3);
assertThat(deploymentManagement.findActionStatusMessagesByActionInDescOrder(pageReq, savedAction, false) assertThat(deploymentManagement.findActionStatusByAction(pageReq, savedAction, false).getNumberOfElements())
.getNumberOfElements()).isEqualTo(3); .isEqualTo(3);
} }
@Test @Test

View File

@@ -23,11 +23,6 @@ import org.springframework.data.domain.Sort.Direction;
/** /**
* Utility class for for paged body generation. * Utility class for for paged body generation.
* *
*
*
*
*
*
*/ */
public final class PagingUtility { public final class PagingUtility {
/* /*
@@ -90,8 +85,9 @@ public final class PagingUtility {
if (sortParam != null) { if (sortParam != null) {
sorting = new Sort(SortUtility.parse(ActionFields.class, sortParam)); sorting = new Sort(SortUtility.parse(ActionFields.class, sortParam));
} else { } else {
// default sort // default sort is DESC in case of action to match behavior
sorting = new Sort(Direction.ASC, ActionFields.ID.getFieldName()); // of management UI (last entry on top)
sorting = new Sort(Direction.DESC, ActionFields.ID.getFieldName());
} }
return sorting; return sorting;
} }
@@ -101,8 +97,9 @@ public final class PagingUtility {
if (sortParam != null) { if (sortParam != null) {
sorting = new Sort(SortUtility.parse(ActionStatusFields.class, sortParam)); sorting = new Sort(SortUtility.parse(ActionStatusFields.class, sortParam));
} else { } else {
// default sort // default sort is DESC in case of action status to match behavior
sorting = new Sort(Direction.ASC, ActionStatusFields.ID.getFieldName()); // of management UI (last entry on top)
sorting = new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName());
} }
return sorting; return sorting;
} }

View File

@@ -297,8 +297,8 @@ final public class TargetMapper {
final ActionStatusRest result = new ActionStatusRest(); final ActionStatusRest result = new ActionStatusRest();
result.setMessages(actionStatus.getMessages()); result.setMessages(actionStatus.getMessages());
result.setReportedAt(action.getCreatedAt()); result.setReportedAt(actionStatus.getCreatedAt());
result.setStatusId(action.getId()); result.setStatusId(actionStatus.getId());
result.setType(getNameOfActionStatusType(actionStatus.getStatus())); result.setType(getNameOfActionStatusType(actionStatus.getStatus()));
return result; return result;

View File

@@ -235,7 +235,7 @@ public class TargetResource implements TargetRestApi {
final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam); final int sanitizedLimitParam = PagingUtility.sanitizePageLimitParam(pagingLimitParam);
final Sort sorting = PagingUtility.sanitizeActionStatusSortParam(sortParam); final Sort sorting = PagingUtility.sanitizeActionStatusSortParam(sortParam);
final Page<ActionStatus> statusList = this.deploymentManagement.findActionStatusMessagesByActionInDescOrder( final Page<ActionStatus> statusList = this.deploymentManagement.findActionStatusByAction(
new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting), action, true); new OffsetBasedPageRequest(sanitizedOffsetParam, sanitizedLimitParam, sorting), action, true);
return new ResponseEntity<>( return new ResponseEntity<>(

View File

@@ -11,6 +11,7 @@ package org.eclipse.hawkbit.rest.resource;
import static org.fest.assertions.api.Assertions.assertThat; import static org.fest.assertions.api.Assertions.assertThat;
import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasKey; import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
@@ -34,6 +35,7 @@ import org.eclipse.hawkbit.TestDataUtil;
import org.eclipse.hawkbit.WithUser; import org.eclipse.hawkbit.WithUser;
import org.eclipse.hawkbit.exception.SpServerError; import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.ActionFields;
import org.eclipse.hawkbit.repository.ActionStatusFields; import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException; import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
@@ -116,27 +118,24 @@ public class TargetResourceTest extends AbstractIntegrationTest {
new ActionStatus(actions.get(0), Status.FINISHED, System.currentTimeMillis(), "testmessage"), new ActionStatus(actions.get(0), Status.FINISHED, System.currentTimeMillis(), "testmessage"),
actions.get(0)); actions.get(0));
final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionStatusFields.ID.getFieldName()); final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionFields.ID.getFieldName());
final ActionStatus status = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(0).getActionStatus().stream().sorted((e1, e2) -> Long.compare(e2.getId(), e1.getId()))
.collect(Collectors.toList()).get(0);
// limit to 1 - first page -> standard cancel message
final Long reportAt = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(0).getCreatedAt();
final Long id = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(0).getId();
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status") + RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)) .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC")) .param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:DESC"))
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print()) .andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3))) .andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize))) .andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize))) .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
.andExpect(jsonPath("content.[0].id", equalTo(id.intValue()))) .andExpect(jsonPath("content.[0].id", equalTo(status.getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("finished"))) .andExpect(jsonPath("content.[0].type", equalTo("finished")))
.andExpect(jsonPath("content.[0].messages", hasSize(1))) .andExpect(jsonPath("content.[0].messages", hasSize(1)))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(reportAt))) .andExpect(jsonPath("content.[0].reportedAt", equalTo(status.getCreatedAt().longValue())))
.andExpect(jsonPath("content.[1].type", equalTo("canceling"))); .andExpect(jsonPath("content.[1].type", equalTo("canceling")));
} }
@@ -229,7 +228,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
@Test @Test
public void cancelActionOK() throws Exception { public void cancelActionOK() throws Exception {
// prepare test // prepare test
Target tA = createTargetAndStartAction(); final Target tA = createTargetAndStartAction();
// test - cancel the active action // test - cancel the active action
mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}", mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}",
@@ -252,7 +251,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
@Test @Test
public void cancelAnCancelActionIsNotAllowed() throws Exception { public void cancelAnCancelActionIsNotAllowed() throws Exception {
// prepare test // prepare test
Target tA = createTargetAndStartAction(); final Target tA = createTargetAndStartAction();
// cancel the active action // cancel the active action
deploymentManagement.cancelAction(tA.getActions().get(0), tA); deploymentManagement.cancelAction(tA.getActions().get(0), tA);
@@ -272,7 +271,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
@Description("Force Quit an Action, which is already canceled. Expected Result is an HTTP response code 204.") @Description("Force Quit an Action, which is already canceled. Expected Result is an HTTP response code 204.")
public void forceQuitAnCanceledActionReturnsOk() throws Exception { public void forceQuitAnCanceledActionReturnsOk() throws Exception {
Target tA = createTargetAndStartAction(); final Target tA = createTargetAndStartAction();
// cancel the active action // cancel the active action
deploymentManagement.cancelAction(tA.getActions().get(0), tA); deploymentManagement.cancelAction(tA.getActions().get(0), tA);
@@ -293,7 +292,7 @@ public class TargetResourceTest extends AbstractIntegrationTest {
@Description("Force Quit an Action, which is not canceled. Expected Result is an HTTP response code 405.") @Description("Force Quit an Action, which is not canceled. Expected Result is an HTTP response code 405.")
public void forceQuitAnNotCanceledActionReturnsMethodNotAllowed() throws Exception { public void forceQuitAnNotCanceledActionReturnsMethodNotAllowed() throws Exception {
Target tA = createTargetAndStartAction(); final Target tA = createTargetAndStartAction();
// test - cancel an cancel action returns forbidden // test - cancel an cancel action returns forbidden
mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}?force=true", mvc.perform(delete(RestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/actions/{actionId}?force=true",
@@ -834,7 +833,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId); final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
mvc.perform(get( mvc.perform(get(
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)) RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[1].id", equalTo(actions.get(1).getId().intValue()))) .andExpect(jsonPath("content.[1].id", equalTo(actions.get(1).getId().intValue())))
.andExpect(jsonPath("content.[1].type", equalTo("update"))) .andExpect(jsonPath("content.[1].type", equalTo("update")))
@@ -851,6 +851,108 @@ public class TargetResourceTest extends AbstractIntegrationTest {
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2))); .andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
} }
@Test
@Description("Verfies that the API returns the status list with expected content.")
public void getMultipleActionStatus() throws Exception {
final String knownTargetId = "targetId";
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
// retrieve list in default descending order for actionstaus entries
final List<ActionStatus> actionStatus = action.getActionStatus().stream()
.sorted((e1, e2) -> Long.compare(e2.getId(), e1.getId())).collect(Collectors.toList());
// sort is default descending order, latest status first
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("canceling")))
.andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
.andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(1).getId().intValue())))
.andExpect(jsonPath("content.[1].type", equalTo("running")))
.andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
}
@Test
@Description("Verfies that the API returns the status list with expected content sorted by reportedAt field.")
public void getMultipleActionStatusSortedByReportedAt() throws Exception {
final String knownTargetId = "targetId";
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
final List<ActionStatus> actionStatus = action.getActionStatus().stream()
.sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId())).collect(Collectors.toList());
// descending order
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
.param(RestConstants.REQUEST_PARAMETER_SORTING, "REPORTEDAT:DESC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(1).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("canceling")))
.andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
.andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(0).getId().intValue())))
.andExpect(jsonPath("content.[1].type", equalTo("running")))
.andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
// ascending order
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
.param(RestConstants.REQUEST_PARAMETER_SORTING, "REPORTEDAT:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[1].id", equalTo(actionStatus.get(1).getId().intValue())))
.andExpect(jsonPath("content.[1].type", equalTo("canceling")))
.andExpect(jsonPath("content.[1].messages", hasItem("manual cancelation requested")))
.andExpect(jsonPath("content.[1].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("running")))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(2)));
}
@Test
@Description("Verfies that the API returns the status list with expected content split into two pages.")
public void getMultipleActionStatusWithPagingLimitRequestParameter() throws Exception {
final String knownTargetId = "targetId";
final Action action = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId).get(0);
final List<ActionStatus> actionStatus = action.getActionStatus().stream()
.sorted((e1, e2) -> Long.compare(e1.getId(), e2.getId())).collect(Collectors.toList());
// Page 1
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1)))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(1).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("canceling")))
.andExpect(jsonPath("content.[0].messages", hasItem("manual cancelation requested")))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(1).getCreatedAt())))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(1)));
// Page 2
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + action.getId() + "/" + RestConstants.TARGET_V1_ACTION_STATUS)
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actionStatus.get(0).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("running")))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(actionStatus.get(0).getCreatedAt())))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(2)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(1)));
}
@Test @Test
public void getMultipleActionsWithPagingLimitRequestParameter() throws Exception { public void getMultipleActionsWithPagingLimitRequestParameter() throws Exception {
final String knownTargetId = "targetId"; final String knownTargetId = "targetId";
@@ -859,7 +961,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
// page 1: one entry // page 1: one entry
mvc.perform(get( mvc.perform(get(
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS) RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))) .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(0).getId().intValue()))) .andExpect(jsonPath("content.[0].id", equalTo(actions.get(0).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("cancel"))) .andExpect(jsonPath("content.[0].type", equalTo("cancel")))
@@ -874,7 +977,9 @@ public class TargetResourceTest extends AbstractIntegrationTest {
mvc.perform(get( mvc.perform(get(
RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS) RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/" + RestConstants.TARGET_V1_ACTIONS)
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1)) .param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(1))
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))) .param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1))
.param(RestConstants.REQUEST_PARAMETER_SORTING, "ID:ASC"))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("content.[0].id", equalTo(actions.get(1).getId().intValue()))) .andExpect(jsonPath("content.[0].id", equalTo(actions.get(1).getId().intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("update"))) .andExpect(jsonPath("content.[0].type", equalTo("update")))
@@ -902,7 +1007,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
+ "?offset=0&limit=50&sort=id:DESC"; + "?offset=0&limit=50&sort=id:DESC";
} }
private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId) { private List<Action> generateTargetWithTwoUpdatesWithOneOverride(final String knownTargetId)
throws InterruptedException {
final PageRequest pageRequest = new PageRequest(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName()); final PageRequest pageRequest = new PageRequest(0, 100, Direction.ASC, ActionStatusFields.ID.getFieldName());
@@ -920,6 +1026,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
final List<Target> updatedTargets = deploymentManagement.assignDistributionSet(one, targets) final List<Target> updatedTargets = deploymentManagement.assignDistributionSet(one, targets)
.getAssignedTargets(); .getAssignedTargets();
// 2nd update // 2nd update
// sleep 10ms to ensure that we can sort by reportedAt
Thread.sleep(10);
deploymentManagement.assignDistributionSet(two, updatedTargets); deploymentManagement.assignDistributionSet(two, updatedTargets);
// two updates, one cancelation // two updates, one cancelation
@@ -946,54 +1054,6 @@ public class TargetResourceTest extends AbstractIntegrationTest {
equalTo(generateStatusreferenceLink(knownTargetId, actions.get(1))))); equalTo(generateStatusreferenceLink(knownTargetId, actions.get(1)))));
} }
@Test
public void getActionStatusWithMultipleResultsWithPagingLimitRequestParameter() throws Exception {
final int limitSize = 1;
final String knownTargetId = "targetId";
final List<Action> actions = generateTargetWithTwoUpdatesWithOneOverride(knownTargetId);
actions.get(0).setStatus(Status.RUNNING);
controllerManagament.addUpdateActionStatus(
new ActionStatus(actions.get(0), Status.RUNNING, System.currentTimeMillis(), "testmessage"),
actions.get(0));
final PageRequest pageRequest = new PageRequest(0, 1000, Direction.ASC, ActionStatusFields.ID.getFieldName());
// limit to 1 - first page -> standard cancel message
Long reportAt = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(0).getCreatedAt();
Long id = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(0).getId();
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize)))
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(limitSize)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_CONTENT, hasSize(limitSize)))
.andExpect(jsonPath("content.[0].id", equalTo(id.intValue())))
.andExpect(jsonPath("content.[0].type", equalTo("running")))
.andExpect(jsonPath("content.[0].messages", hasSize(1)))
.andExpect(jsonPath("content.[0].reportedAt", equalTo(reportAt)));
// limit to 1 - first page -> added custom message
reportAt = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(1).getCreatedAt();
id = deploymentManagement
.findActionsByTarget(pageRequest, targetManagement.findTargetByControllerID(knownTargetId)).getContent()
.get(1).getCreatedAt();
mvc.perform(get(RestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownTargetId + "/"
+ RestConstants.TARGET_V1_ACTIONS + "/" + actions.get(0).getId() + "/status")
.param(RestConstants.REQUEST_PARAMETER_PAGING_LIMIT, String.valueOf(limitSize))
.param(RestConstants.REQUEST_PARAMETER_PAGING_OFFSET, String.valueOf(1)))
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_TOTAL, equalTo(3)))
.andExpect(jsonPath(JSON_PATH_PAGED_LIST_SIZE, equalTo(1)));
}
@Test @Test
public void assignDistributionSetToTarget() throws Exception { public void assignDistributionSetToTarget() throws Exception {
@@ -1232,7 +1292,8 @@ public class TargetResourceTest extends AbstractIntegrationTest {
// prepare test // prepare test
final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement, final DistributionSet dsA = TestDataUtil.generateDistributionSet("", softwareManagement,
distributionSetManagement); distributionSetManagement);
Target tA = targetManagement.createTarget(TestDataUtil.buildTargetFixture("target-id-A", "first description")); final Target tA = targetManagement
.createTarget(TestDataUtil.buildTargetFixture("target-id-A", "first description"));
// assign a distribution set so we get an active update action // assign a distribution set so we get an active update action
deploymentManagement.assignDistributionSet(dsA, Lists.newArrayList(tA)); deploymentManagement.assignDistributionSet(dsA, Lists.newArrayList(tA));
// verify active action // verify active action

View File

@@ -17,7 +17,7 @@
</Console> </Console>
</Appenders> </Appenders>
<Loggers> <Loggers>
<Logger name="org.eclipse.hawkbit.MockMvcResultPrinter" level="debug" /> <Logger name="org.eclipse.hawkbit.MockMvcResultPrinter" level="error" />
<Root level="error"> <Root level="error">
<AppenderRef ref="Console"/> <AppenderRef ref="Console"/>

View File

@@ -16,6 +16,7 @@ import java.util.StringJoiner;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import org.eclipse.hawkbit.repository.ActionStatusFields;
import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
@@ -43,6 +44,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.vaadin.spring.events.EventBus; import org.vaadin.spring.events.EventBus;
import org.vaadin.spring.events.EventScope; import org.vaadin.spring.events.EventScope;
import org.vaadin.spring.events.annotation.EventBusListenerMethod; import org.vaadin.spring.events.annotation.EventBusListenerMethod;
@@ -417,10 +420,10 @@ public class ActionHistoryTable extends TreeTable implements Handler {
final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement final org.eclipse.hawkbit.repository.model.Action action = deploymentManagement
.findActionWithDetails(actionId); .findActionWithDetails(actionId);
final Pageable pageReq = new PageRequest(0, 1000); final Pageable pageReq = new PageRequest(0, 1000,
final Page<ActionStatus> actionStatusList = deploymentManagement new Sort(Direction.DESC, ActionStatusFields.ID.getFieldName()));
.findActionStatusMessagesByActionInDescOrder(pageReq, action, final Page<ActionStatus> actionStatusList = deploymentManagement.findActionStatusByAction(pageReq, action,
managementUIState.isActionHistoryMaximized()); managementUIState.isActionHistoryMaximized());
final List<ActionStatus> content = actionStatusList.getContent(); final List<ActionStatus> content = actionStatusList.getContent();
/* /*
* Since the recent action status and messages are already * Since the recent action status and messages are already