diff --git a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java index 21c41eb3d..5f0b5ed6e 100644 --- a/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java +++ b/hawkbit-rest/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/rollout/MgmtRolloutResponseBody.java @@ -41,6 +41,9 @@ public class MgmtRolloutResponseBody extends MgmtNamedEntity { @JsonProperty private Map totalTargetsPerStatus; + @JsonProperty + private Integer totalGroups; + @JsonProperty private boolean deleted; @@ -125,4 +128,12 @@ public class MgmtRolloutResponseBody extends MgmtNamedEntity { public Integer getWeight() { return weight; } + + public void setTotalGroups(final Integer totalGroups) { + this.totalGroups = totalGroups; + } + + public Integer getTotalGroups() { + return totalGroups; + } } diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java index c43c51dfb..b30207586 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutMapper.java @@ -91,6 +91,7 @@ final class MgmtRolloutMapper { body.addTotalTargetsPerStatus(status.name().toLowerCase(), rollout.getTotalTargetCountStatus().getTotalTargetCountByStatus(status)); } + body.setTotalGroups(rollout.getRolloutGroupsCreated()); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).start(rollout.getId())).withRel("start")); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).pause(rollout.getId())).withRel("pause")); diff --git a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java index b09c8c761..110a7f546 100644 --- a/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java +++ b/hawkbit-rest/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtRolloutResourceTest.java @@ -456,7 +456,8 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.totalTargetsPerStatus.cancelled", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.finished", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.error", equalTo(0))) - .andExpect(jsonPath("$.deleted", equalTo(false))); + .andExpect(jsonPath("$.deleted", equalTo(false))) + .andExpect(jsonPath("$.totalGroups", equalTo(4))); } @Step @@ -474,7 +475,8 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.totalTargetsPerStatus.cancelled", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.finished", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.error", equalTo(0))) - .andExpect(jsonPath("$.deleted", equalTo(false))); + .andExpect(jsonPath("$.deleted", equalTo(false))) + .andExpect(jsonPath("$.totalGroups", equalTo(4))); } @Step @@ -494,7 +496,8 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("$.totalTargetsPerStatus.cancelled", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.finished", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.error", equalTo(0))) - .andExpect(jsonPath("$.deleted", equalTo(false))); + .andExpect(jsonPath("$.deleted", equalTo(false))) + .andExpect(jsonPath("$.totalGroups", equalTo(4))); } @Step @@ -526,7 +529,8 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { allOf(startsWith(HREF_ROLLOUT_PREFIX), endsWith("/triggerNextGroup")))) .andExpect(jsonPath("$._links.groups.href", allOf(startsWith(HREF_ROLLOUT_PREFIX), containsString("/deploygroups")))) - .andExpect(jsonPath("$.deleted", equalTo(false))); + .andExpect(jsonPath("$.deleted", equalTo(false))) + .andExpect(jsonPath("$.totalGroups", equalTo(4))); } @Test @@ -570,6 +574,24 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { .andExpect(jsonPath("content[1]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX))); } + @Test + @Description("Testing representation mode of rollout paged list") + void rolloutPagedListRepresentationMode() throws Exception { + final DistributionSet dsA = testdataFactory.createDistributionSet(""); + + testdataFactory.createTargets(20, "target", "rollout"); + + // setup - create 2 rollouts + postRollout("rollout1", 5, dsA.getId(), "id==target*", 20, Action.ActionType.FORCED); + postRollout("rollout2", 5, dsA.getId(), "id==target-0001*", 10, Action.ActionType.FORCED); + + // Run here, because Scheduler is disabled during tests + rolloutManagement.handleRollouts(); + + retrieveAndCompareRolloutsContent(dsA, "/rest/v1/rollouts", false); + retrieveAndCompareRolloutsContent(dsA, "/rest/v1/rollouts?representation=full", true); + } + @Test @Description("Testing that rollout paged list is limited by the query param limit") void rolloutPagedListIsLimitedToQueryParam() throws Exception { @@ -1301,4 +1323,90 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest { } } + private void retrieveAndCompareRolloutsContent(final DistributionSet dsA, final String urlTemplate, boolean isFullRepresentation) throws Exception { + mvc.perform(get(urlTemplate).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) + .andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) + .andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2))) + .andExpect(jsonPath("content[0].name", equalTo("rollout1"))) + .andExpect(jsonPath("content[0].status", equalTo("ready"))) + .andExpect(jsonPath("content[0].targetFilterQuery", equalTo("id==target*"))) + .andExpect(jsonPath("content[0].distributionSetId", equalTo(dsA.getId().intValue()))) + .andExpect(jsonPath("content[0].createdBy", equalTo("bumlux"))) + .andExpect(jsonPath("content[0].createdAt", not(equalTo(0)))) + .andExpect(jsonPath("content[0].lastModifiedBy", equalTo("bumlux"))) + .andExpect(jsonPath("content[0].lastModifiedAt", not(equalTo(0)))) + .andExpect(jsonPath("content[0].totalTargets", equalTo(20))) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0].totalTargetsPerStatus").exists() + : jsonPath("content[0].totalTargetsPerStatus").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0].totalGroups", equalTo(5)) + : jsonPath("content[0].totalGroups").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.start.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.start.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.pause.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.pause.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.resume.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.resume.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.triggerNextGroup.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.triggerNextGroup.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.approve.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.approve.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.deny.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.deny.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.groups.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[0]._links.groups.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0]._links.distributionset.href", startsWith("http://localhost/rest/v1/distributionsets/")) + : jsonPath("content[0]._links.distributionset.href").doesNotExist()) + .andExpect(jsonPath("content[0]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX))) + .andExpect(jsonPath("content[1].name", equalTo("rollout2"))) + .andExpect(jsonPath("content[1].status", equalTo("ready"))) + .andExpect(jsonPath("content[1].targetFilterQuery", equalTo("id==target-0001*"))) + .andExpect(jsonPath("content[1].distributionSetId", equalTo(dsA.getId().intValue()))) + .andExpect(jsonPath("content[1].createdBy", equalTo("bumlux"))) + .andExpect(jsonPath("content[1].createdAt", not(equalTo(0)))) + .andExpect(jsonPath("content[1].lastModifiedBy", equalTo("bumlux"))) + .andExpect(jsonPath("content[1].lastModifiedAt", not(equalTo(0)))) + .andExpect(jsonPath("content[1].totalTargets", equalTo(10))) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1].totalTargetsPerStatus").exists() + : jsonPath("content[1].totalTargetsPerStatus").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[0].totalGroups", equalTo(5)) + : jsonPath("content[0].totalGroups").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.start.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.start.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.pause.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.pause.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.resume.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.resume.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.triggerNextGroup.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.triggerNextGroup.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.approve.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.approve.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.deny.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.deny.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.groups.href", startsWith(HREF_ROLLOUT_PREFIX)) + : jsonPath("content[1]._links.groups.href").doesNotExist()) + .andExpect(isFullRepresentation + ? jsonPath("$.content[1]._links.distributionset.href", startsWith("http://localhost/rest/v1/distributionsets/")) + : jsonPath("content[1]._links.distributionset.href").doesNotExist()) + .andExpect(jsonPath("content[1]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX))); + } + } diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java index bbe0d1184..ebf06972e 100644 --- a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/documentation/MgmtApiModelProperties.java @@ -102,6 +102,8 @@ public final class MgmtApiModelProperties { public static final String ROLLOUT_DS_ID = "the ID of distributionset of this rollout"; public static final String ROLLOUT_TOTAL_TARGETS = "the total targets of a rollout"; public static final String ROLLOUT_TOTAL_TARGETS_PER_STATUS = "the total targets per status"; + + public static final String ROLLOUT_TOTAL_GROUPS = "the total number of groups created by this rollout"; public static final String ROLLOUT_STATUS = "the status of this rollout"; public static final String ROLLOUT_TYPE = "the type of this rollout"; public static final String ROLLOUT_GROUP_STATUS = "the status of this rollout group"; diff --git a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java index 208938301..3d262695c 100644 --- a/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java +++ b/hawkbit-rest/hawkbit-rest-docs/src/test/java/org/eclipse/hawkbit/rest/mgmt/documentation/RolloutResourceDocumentationTest.java @@ -141,6 +141,8 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati if (withDetails) { allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalTargetsPerStatus") .description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS_PER_STATUS)); + allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalGroups") + .description(MgmtApiModelProperties.ROLLOUT_TOTAL_GROUPS)); allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.start") .description(MgmtApiModelProperties.ROLLOUT_LINKS_START_SYNC)); allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.pause")