Management API: Expose forceTime and startAt fields in rollout representation (#1336)

* Expose forceTime and startAt fields in rollout representation in Mgmt API
* Change "forceTime" to "forcetime"
* Add checks when making a POST request in the tests
* Change forced to timeforced in tests and extend validity check
* Pass aforcetime and startat arguments as test checks
* remove unused import

Signed-off-by: Stanislav Trailov <stanislav.trailov@bosch.io>
This commit is contained in:
Stanislav Trailov
2023-03-27 11:52:55 +03:00
committed by GitHub
parent 5baf65c1f0
commit 85feeba681
6 changed files with 182 additions and 95 deletions

View File

@@ -44,6 +44,12 @@ public class MgmtRolloutResponseBody extends MgmtNamedEntity {
@JsonProperty @JsonProperty
private Integer totalGroups; private Integer totalGroups;
@JsonProperty
private Long startAt;
@JsonProperty
private Long forcetime;
@JsonProperty @JsonProperty
private boolean deleted; private boolean deleted;
@@ -101,6 +107,22 @@ public class MgmtRolloutResponseBody extends MgmtNamedEntity {
return totalTargets; return totalTargets;
} }
public void setStartAt(final Long startAt) {
this.startAt = startAt;
}
public Long getStartAt() {
return startAt;
}
public void setForcetime(final Long forcetime) {
this.forcetime = forcetime;
}
public Long getForcetime() {
return forcetime;
}
public Map<String, Long> getTotalTargetsPerStatus() { public Map<String, Long> getTotalTargetsPerStatus() {
return totalTargetsPerStatus; return totalTargetsPerStatus;
} }

View File

@@ -84,6 +84,7 @@ final class MgmtRolloutMapper {
body.setTotalTargets(rollout.getTotalTargets()); body.setTotalTargets(rollout.getTotalTargets());
body.setDeleted(rollout.isDeleted()); body.setDeleted(rollout.isDeleted());
body.setType(MgmtRestModelMapper.convertActionType(rollout.getActionType())); body.setType(MgmtRestModelMapper.convertActionType(rollout.getActionType()));
body.setForcetime(rollout.getForcedTime());
rollout.getWeight().ifPresent(body::setWeight); rollout.getWeight().ifPresent(body::setWeight);
if (withDetails) { if (withDetails) {
@@ -92,6 +93,7 @@ final class MgmtRolloutMapper {
rollout.getTotalTargetCountStatus().getTotalTargetCountByStatus(status)); rollout.getTotalTargetCountStatus().getTotalTargetCountByStatus(status));
} }
body.setTotalGroups(rollout.getRolloutGroupsCreated()); body.setTotalGroups(rollout.getRolloutGroupsCreated());
body.setStartAt(rollout.getStartAt());
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).start(rollout.getId())).withRel("start")); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).start(rollout.getId())).withRel("start"));
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).pause(rollout.getId())).withRel("pause")); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).pause(rollout.getId())).withRel("pause"));

View File

@@ -397,7 +397,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
mvc.perform(post("/rest/v1/rollouts") mvc.perform(post("/rest/v1/rollouts")
.content(JsonBuilder.rollout("rollout2", "desc", null, dsA.getId(), "id==ro-target*", .content(JsonBuilder.rollout("rollout2", "desc", null, dsA.getId(), "id==ro-target*",
rolloutGroupConditions, rolloutGroups, null, null, false)) rolloutGroupConditions, rolloutGroups, null, null, null, null, false))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andReturn(); .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andReturn();
@@ -438,7 +438,7 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
mvc.perform(post("/rest/v1/rollouts") mvc.perform(post("/rest/v1/rollouts")
.content(JsonBuilder.rollout("rollout2", "desc", null, dsA.getId(), "id==ro-target*", .content(JsonBuilder.rollout("rollout2", "desc", null, dsA.getId(), "id==ro-target*",
rolloutGroupConditions, rolloutGroups, null, null, null)) rolloutGroupConditions, rolloutGroups, null, null, null, null, null))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)) .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andReturn(); .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andReturn();
@@ -585,6 +585,25 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
.andExpect(jsonPath("content[1]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX))); .andExpect(jsonPath("content[1]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX)));
} }
@Test
void retrieveRolloutWithStartAtAndForcedTimeResponseFields() throws Exception {
final DistributionSet dsA = testdataFactory.createDistributionSet("");
final Long startAt = 21L;
final Long forcetime = 45L;
testdataFactory.createTargets(20, "target", "rollout");
postRollout("rollout1", 5, dsA.getId(), "id==target*", 20, Action.ActionType.TIMEFORCED,
startAt, forcetime);
postRollout("rollout2", 5, dsA.getId(), "id==target-0001*", 10, Action.ActionType.TIMEFORCED,
startAt, forcetime);
// Run here, because Scheduler is disabled during tests
rolloutManagement.handleRollouts();
retrieveAndCompareRolloutsContent(dsA, "/rest/v1/rollouts", false, true, startAt, forcetime);
retrieveAndCompareRolloutsContent(dsA, "/rest/v1/rollouts?representation=full", true, true, startAt, forcetime);
}
@Test @Test
@Description("Testing representation mode of rollout paged list") @Description("Testing representation mode of rollout paged list")
void rolloutPagedListRepresentationMode() throws Exception { void rolloutPagedListRepresentationMode() throws Exception {
@@ -1180,9 +1199,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
final int weight = 66; final int weight = 66;
final String invalideWeightRequest = JsonBuilder.rollout("withWeight", "d", 2, dsId, "id==rollout*", final String invalideWeightRequest = JsonBuilder.rollout("withWeight", "d", 2, dsId, "id==rollout*",
new RolloutGroupConditionBuilder().withDefaults().build(), null, null, Action.WEIGHT_MIN - 1, null); new RolloutGroupConditionBuilder().withDefaults().build(), null, null, Action.WEIGHT_MIN - 1, null, null, null);
final String valideWeightRequest = JsonBuilder.rollout("withWeight", "d", 2, dsId, "id==rollout*", final String valideWeightRequest = JsonBuilder.rollout("withWeight", "d", 2, dsId, "id==rollout*",
new RolloutGroupConditionBuilder().withDefaults().build(), null, null, weight, null); new RolloutGroupConditionBuilder().withDefaults().build(), null, null, weight, null, null, null);
mvc.perform(post("/rest/v1/rollouts").content(valideWeightRequest).contentType(MediaType.APPLICATION_JSON) mvc.perform(post("/rest/v1/rollouts").content(valideWeightRequest).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
@@ -1202,11 +1221,18 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
assertThat(rollouts.get(0).getWeight()).get().isEqualTo(weight); assertThat(rollouts.get(0).getWeight()).get().isEqualTo(weight);
} }
private void postRollout(final String name, final int groupSize, final Long distributionSetId, private void postRollout(final String name, final int groupSize, final Long distributionSetId,
final String targetFilterQuery, final int targets, final Action.ActionType type) throws Exception { final String targetFilterQuery, final int targets, final Action.ActionType type) throws Exception {
postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, null, null);
}
private void postRollout(final String name, final int groupSize, final Long distributionSetId,
final String targetFilterQuery, final int targets, final Action.ActionType type, final Long startTime, final Long forceTime) throws Exception {
final String actionType = MgmtRestModelMapper.convertActionType(type).getName(); final String actionType = MgmtRestModelMapper.convertActionType(type).getName();
final String rollout = JsonBuilder.rollout(name, "desc", groupSize, distributionSetId, targetFilterQuery, final String rollout = JsonBuilder.rollout(name, "desc", groupSize, distributionSetId, targetFilterQuery,
new RolloutGroupConditionBuilder().withDefaults().build(), null, actionType, null, null); new RolloutGroupConditionBuilder().withDefaults().build(), null, actionType, null, startTime,
forceTime, null);
mvc.perform(post("/rest/v1/rollouts").content(rollout).contentType(MediaType.APPLICATION_JSON) mvc.perform(post("/rest/v1/rollouts").content(rollout).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
@@ -1220,6 +1246,12 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
.andExpect(jsonPath("$.lastModifiedBy", equalTo("bumlux"))) .andExpect(jsonPath("$.lastModifiedBy", equalTo("bumlux")))
.andExpect(jsonPath("$.lastModifiedAt", not(equalTo(0)))) .andExpect(jsonPath("$.lastModifiedAt", not(equalTo(0))))
.andExpect(jsonPath("$.totalTargets", equalTo(targets))) .andExpect(jsonPath("$.totalTargets", equalTo(targets)))
.andExpect(startTime != null ?
jsonPath("$.startAt", equalTo(startTime.intValue()))
: jsonPath("$.startAt").doesNotExist())
.andExpect(forceTime != null ?
jsonPath("$.forcetime", equalTo(forceTime.intValue()))
: jsonPath("$.forcetime", equalTo(0)))
.andExpect(jsonPath("$.totalTargetsPerStatus.running", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.running", equalTo(0)))
.andExpect(jsonPath("$.totalTargetsPerStatus.notstarted", equalTo(targets))) .andExpect(jsonPath("$.totalTargetsPerStatus.notstarted", equalTo(targets)))
.andExpect(jsonPath("$.totalTargetsPerStatus.scheduled", equalTo(0))) .andExpect(jsonPath("$.totalTargetsPerStatus.scheduled", equalTo(0)))
@@ -1330,87 +1362,98 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
private void retrieveAndCompareRolloutsContent(final DistributionSet dsA, final String urlTemplate, private void retrieveAndCompareRolloutsContent(final DistributionSet dsA, final String urlTemplate,
final boolean isFullRepresentation) throws Exception { final boolean isFullRepresentation) throws Exception {
retrieveAndCompareRolloutsContent(dsA, urlTemplate, isFullRepresentation, false, null, null);
}
private void retrieveAndCompareRolloutsContent(final DistributionSet dsA, final String urlTemplate,
final boolean isFullRepresentation, final boolean isStartTypeScheduled, final Long startAt, final Long forcetime) throws Exception {
mvc.perform(get(urlTemplate).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()) mvc.perform(get(urlTemplate).accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) .andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2))) .andExpect(jsonPath("$.content", hasSize(2))).andExpect(jsonPath("$.total", equalTo(2)))
.andExpect(jsonPath("content[0].name", equalTo("rollout1"))) .andExpect(jsonPath("content[0].name", equalTo("rollout1")))
.andExpect(jsonPath("content[0].status", equalTo("ready"))) .andExpect(jsonPath("content[0].status", equalTo("ready")))
.andExpect(jsonPath("content[0].targetFilterQuery", equalTo("id==target*"))) .andExpect(jsonPath("content[0].targetFilterQuery", equalTo("id==target*")))
.andExpect(jsonPath("content[0].distributionSetId", equalTo(dsA.getId().intValue()))) .andExpect(jsonPath("content[0].distributionSetId", equalTo(dsA.getId().intValue())))
.andExpect(jsonPath("content[0].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("content[0].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("content[0].createdAt", not(equalTo(0)))) .andExpect(jsonPath("content[0].createdAt", not(equalTo(0))))
.andExpect(jsonPath("content[0].lastModifiedBy", equalTo("bumlux"))) .andExpect(jsonPath("content[0].lastModifiedBy", equalTo("bumlux")))
.andExpect(jsonPath("content[0].lastModifiedAt", not(equalTo(0)))) .andExpect(jsonPath("content[0].lastModifiedAt", not(equalTo(0))))
.andExpect(jsonPath("content[0].totalTargets", equalTo(20))) .andExpect(jsonPath("content[0].totalTargets", equalTo(20)))
.andExpect(isFullRepresentation ? jsonPath("$.content[0].totalTargetsPerStatus").exists() .andExpect(jsonPath("content[0].forcetime", equalTo(isStartTypeScheduled ? forcetime.intValue() : 0)))
: jsonPath("content[0].totalTargetsPerStatus").doesNotExist()) .andExpect(isFullRepresentation ? jsonPath("$.content[0].totalTargetsPerStatus").exists()
.andExpect(isFullRepresentation ? jsonPath("$.content[0].totalGroups", equalTo(5)) : jsonPath("content[0].totalTargetsPerStatus").doesNotExist())
: jsonPath("content[0].totalGroups").doesNotExist()) .andExpect(isFullRepresentation ? jsonPath("$.content[0].totalGroups", equalTo(5))
.andExpect(isFullRepresentation : jsonPath("content[0].totalGroups").doesNotExist())
? jsonPath("$.content[0]._links.start.href", startsWith(HREF_ROLLOUT_PREFIX)) .andExpect(isFullRepresentation && isStartTypeScheduled ? jsonPath("$.content[0].startAt", equalTo(startAt.intValue()))
: jsonPath("content[0]._links.start.href").doesNotExist()) : jsonPath("$.content[0].startAt").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.pause.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[0]._links.start.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[0]._links.pause.href").doesNotExist()) : jsonPath("content[0]._links.start.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.resume.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[0]._links.pause.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[0]._links.resume.href").doesNotExist()) : jsonPath("content[0]._links.pause.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.triggerNextGroup.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[0]._links.resume.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[0]._links.triggerNextGroup.href").doesNotExist()) : jsonPath("content[0]._links.resume.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.approve.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[0]._links.triggerNextGroup.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[0]._links.approve.href").doesNotExist()) : jsonPath("content[0]._links.triggerNextGroup.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.deny.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[0]._links.approve.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[0]._links.deny.href").doesNotExist()) : jsonPath("content[0]._links.approve.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.groups.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[0]._links.deny.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[0]._links.groups.href").doesNotExist()) : jsonPath("content[0]._links.deny.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[0]._links.distributionset.href", ? jsonPath("$.content[0]._links.groups.href", startsWith(HREF_ROLLOUT_PREFIX))
startsWith("http://localhost/rest/v1/distributionsets/")) : jsonPath("content[0]._links.groups.href").doesNotExist())
: jsonPath("content[0]._links.distributionset.href").doesNotExist()) .andExpect(isFullRepresentation
.andExpect(jsonPath("content[0]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX))) ? jsonPath("$.content[0]._links.distributionset.href",
.andExpect(jsonPath("content[1].name", equalTo("rollout2"))) startsWith("http://localhost/rest/v1/distributionsets/"))
.andExpect(jsonPath("content[1].status", equalTo("ready"))) : jsonPath("content[0]._links.distributionset.href").doesNotExist())
.andExpect(jsonPath("content[1].targetFilterQuery", equalTo("id==target-0001*"))) .andExpect(jsonPath("content[0]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX)))
.andExpect(jsonPath("content[1].distributionSetId", equalTo(dsA.getId().intValue()))) .andExpect(jsonPath("content[1].name", equalTo("rollout2")))
.andExpect(jsonPath("content[1].createdBy", equalTo("bumlux"))) .andExpect(jsonPath("content[1].status", equalTo("ready")))
.andExpect(jsonPath("content[1].createdAt", not(equalTo(0)))) .andExpect(jsonPath("content[1].targetFilterQuery", equalTo("id==target-0001*")))
.andExpect(jsonPath("content[1].lastModifiedBy", equalTo("bumlux"))) .andExpect(jsonPath("content[1].distributionSetId", equalTo(dsA.getId().intValue())))
.andExpect(jsonPath("content[1].lastModifiedAt", not(equalTo(0)))) .andExpect(jsonPath("content[1].createdBy", equalTo("bumlux")))
.andExpect(jsonPath("content[1].totalTargets", equalTo(10))) .andExpect(jsonPath("content[1].createdAt", not(equalTo(0))))
.andExpect(isFullRepresentation ? jsonPath("$.content[1].totalTargetsPerStatus").exists() .andExpect(jsonPath("content[1].lastModifiedBy", equalTo("bumlux")))
: jsonPath("content[1].totalTargetsPerStatus").doesNotExist()) .andExpect(jsonPath("content[1].lastModifiedAt", not(equalTo(0))))
.andExpect(isFullRepresentation ? jsonPath("$.content[0].totalGroups", equalTo(5)) .andExpect(jsonPath("content[1].totalTargets", equalTo(10)))
: jsonPath("content[0].totalGroups").doesNotExist()) .andExpect(jsonPath("content[1].forcetime", equalTo(isStartTypeScheduled ? forcetime.intValue() : 0)))
.andExpect(isFullRepresentation .andExpect(isFullRepresentation ? jsonPath("$.content[1].totalTargetsPerStatus").exists()
? jsonPath("$.content[1]._links.start.href", startsWith(HREF_ROLLOUT_PREFIX)) : jsonPath("content[1].totalTargetsPerStatus").doesNotExist())
: jsonPath("content[1]._links.start.href").doesNotExist()) .andExpect(isFullRepresentation ? jsonPath("$.content[1].totalGroups", equalTo(5))
.andExpect(isFullRepresentation : jsonPath("content[1].totalGroups").doesNotExist())
? jsonPath("$.content[1]._links.pause.href", startsWith(HREF_ROLLOUT_PREFIX)) .andExpect(isFullRepresentation && isStartTypeScheduled ? jsonPath("content[1].startAt", equalTo(startAt.intValue()))
: jsonPath("content[1]._links.pause.href").doesNotExist()) : jsonPath("content[1].startAt").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[1]._links.resume.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[1]._links.start.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[1]._links.resume.href").doesNotExist()) : jsonPath("content[1]._links.start.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[1]._links.triggerNextGroup.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[1]._links.pause.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[1]._links.triggerNextGroup.href").doesNotExist()) : jsonPath("content[1]._links.pause.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[1]._links.approve.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[1]._links.resume.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[1]._links.approve.href").doesNotExist()) : jsonPath("content[1]._links.resume.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[1]._links.deny.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[1]._links.triggerNextGroup.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[1]._links.deny.href").doesNotExist()) : jsonPath("content[1]._links.triggerNextGroup.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[1]._links.groups.href", startsWith(HREF_ROLLOUT_PREFIX)) ? jsonPath("$.content[1]._links.approve.href", startsWith(HREF_ROLLOUT_PREFIX))
: jsonPath("content[1]._links.groups.href").doesNotExist()) : jsonPath("content[1]._links.approve.href").doesNotExist())
.andExpect(isFullRepresentation .andExpect(isFullRepresentation
? jsonPath("$.content[1]._links.distributionset.href", ? jsonPath("$.content[1]._links.deny.href", startsWith(HREF_ROLLOUT_PREFIX))
startsWith("http://localhost/rest/v1/distributionsets/")) : jsonPath("content[1]._links.deny.href").doesNotExist())
: jsonPath("content[1]._links.distributionset.href").doesNotExist()) .andExpect(isFullRepresentation
.andExpect(jsonPath("content[1]._links.self.href", startsWith(HREF_ROLLOUT_PREFIX))); ? 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)));
} }
} }

View File

@@ -481,15 +481,15 @@ public abstract class JsonBuilder {
public static String rollout(final String name, final String description, final int groupSize, public static String rollout(final String name, final String description, final int groupSize,
final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions) { final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions) {
return rollout(name, description, groupSize, distributionSetId, targetFilterQuery, conditions, null, null, return rollout(name, description, groupSize, distributionSetId, targetFilterQuery, conditions, null, null, null,
null, null); null, null, null);
} }
public static String rollout(final String name, final String description, final Integer groupSize, public static String rollout(final String name, final String description, final Integer groupSize,
final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions, final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions,
final String type) { final String type) {
return rollout(name, description, groupSize, distributionSetId, targetFilterQuery, conditions, null, type, null, return rollout(name, description, groupSize, distributionSetId, targetFilterQuery, conditions, null, type,
null); null, null, null, null);
} }
public static String rolloutWithGroups(final String name, final String description, final Integer groupSize, public static String rolloutWithGroups(final String name, final String description, final Integer groupSize,
@@ -506,12 +506,13 @@ public abstract class JsonBuilder {
final List<String> rolloutGroupsJson = groups.stream().map(JsonBuilder::rolloutGroup) final List<String> rolloutGroupsJson = groups.stream().map(JsonBuilder::rolloutGroup)
.collect(Collectors.toList()); .collect(Collectors.toList());
return rollout(name, description, groupSize, distributionSetId, targetFilterQuery, conditions, return rollout(name, description, groupSize, distributionSetId, targetFilterQuery, conditions,
rolloutGroupsJson, type, weight, confirmationRequired); rolloutGroupsJson, type, weight, System.currentTimeMillis(), null, confirmationRequired);
} }
public static String rollout(final String name, final String description, final Integer groupSize, public static String rollout(final String name, final String description, final Integer groupSize,
final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions, final long distributionSetId, final String targetFilterQuery, final RolloutGroupConditions conditions,
final List<String> groupJsonList, final String type, final Integer weight, final Boolean confirmationRequired) { final List<String> groupJsonList, final String type, final Integer weight, final Long startAt, final Long forceTime,
final Boolean confirmationRequired) {
final JSONObject json = new JSONObject(); final JSONObject json = new JSONObject();
try { try {
@@ -529,6 +530,14 @@ public abstract class JsonBuilder {
json.put("weight", weight); json.put("weight", weight);
} }
if (startAt != null) {
json.put("startAt", startAt);
}
if (forceTime != null) {
json.put("forcetime", forceTime);
}
if (confirmationRequired != null) { if (confirmationRequired != null) {
json.put("confirmationRequired", confirmationRequired); json.put("confirmationRequired", confirmationRequired);
} }

View File

@@ -130,6 +130,8 @@ public final class MgmtApiModelProperties {
public static final String ROLLOUT_LINKS_DENY = "Link to deny a rollout"; public static final String ROLLOUT_LINKS_DENY = "Link to deny a rollout";
public static final String ROLLOUT_LINKS_GROUPS = "Link to retrieve the groups a rollout"; public static final String ROLLOUT_LINKS_GROUPS = "Link to retrieve the groups a rollout";
public static final String ROLLOUT_START_ASYNC = "Start the rollout asynchronous"; public static final String ROLLOUT_START_ASYNC = "Start the rollout asynchronous";
public static final String ROLLOUT_START_AT = "Start at timestamp of Rollout.";
public static final String RESULTING_ACTIONS_WEIGHT = "Weight of the resulting Actions"; public static final String RESULTING_ACTIONS_WEIGHT = "Weight of the resulting Actions";

View File

@@ -137,12 +137,15 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
.attributes(key("value").value("['forced','soft','timeforced','downloadonly']"))); .attributes(key("value").value("['forced','soft','timeforced','downloadonly']")));
allFieldDescriptor.add( allFieldDescriptor.add(
fieldWithPath(arrayPrefix + "totalTargets").description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS)); fieldWithPath(arrayPrefix + "totalTargets").description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "forcetime").description(MgmtApiModelProperties.FORCETIME));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored()); allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored());
if (withDetails) { if (withDetails) {
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalTargetsPerStatus") allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalTargetsPerStatus")
.description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS_PER_STATUS)); .description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS_PER_STATUS));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalGroups") allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalGroups")
.description(MgmtApiModelProperties.ROLLOUT_TOTAL_GROUPS)); .description(MgmtApiModelProperties.ROLLOUT_TOTAL_GROUPS));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "startAt")
.description(MgmtApiModelProperties.ROLLOUT_START_AT));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.start") allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.start")
.description(MgmtApiModelProperties.ROLLOUT_LINKS_START_SYNC)); .description(MgmtApiModelProperties.ROLLOUT_LINKS_START_SYNC));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.pause") allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.pause")
@@ -200,8 +203,8 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
mockMvc.perform( mockMvc.perform(
post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING) post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING)
.content(JsonBuilder.rollout(name, description, groupSize, dsId, targetFilter, .content(JsonBuilder.rollout(name, description, groupSize, dsId, targetFilter, rolloutGroupConditions, null, type,
rolloutGroupConditions, type)) null, System.currentTimeMillis() + 2000, System.currentTimeMillis() + 3000, false))
.contentType(MediaTypes.HAL_JSON).accept(MediaTypes.HAL_JSON_VALUE)) .contentType(MediaTypes.HAL_JSON).accept(MediaTypes.HAL_JSON_VALUE))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
@@ -211,8 +214,11 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
.description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT) .description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT)
.attributes(key("value").value("0 - 1000")), .attributes(key("value").value("0 - 1000")),
requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME), requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
optionalRequestFieldWithPath("forcetime").description(MgmtApiModelProperties.FORCETIME),
optionalRequestFieldWithPath("type").description(MgmtApiModelProperties.ROLLOUT_TYPE) optionalRequestFieldWithPath("type").description(MgmtApiModelProperties.ROLLOUT_TYPE)
.attributes(key("value").value("['soft', 'forced', 'timeforced', 'downloadonly']")), .attributes(key("value").value("['soft', 'forced', 'timeforced', 'downloadonly']")),
optionalRequestFieldWithPath("startAt").description(MgmtApiModelProperties.ROLLOUT_START_AT)
.type(JsonFieldType.NUMBER),
optionalRequestFieldWithPath("confirmationRequired") optionalRequestFieldWithPath("confirmationRequired")
.description(MgmtApiModelProperties.ROLLOUT_CONFIRMATION_REQUIRED) .description(MgmtApiModelProperties.ROLLOUT_CONFIRMATION_REQUIRED)
.type(JsonFieldType.BOOLEAN.toString()), .type(JsonFieldType.BOOLEAN.toString()),
@@ -311,6 +317,8 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
.description(MgmtApiModelProperties.ROLLOUT_CONFIRMATION_REQUIRED), .description(MgmtApiModelProperties.ROLLOUT_CONFIRMATION_REQUIRED),
optionalRequestFieldWithPath("description") optionalRequestFieldWithPath("description")
.description(ApiModelPropertiesGeneric.DESCRPTION), .description(ApiModelPropertiesGeneric.DESCRPTION),
optionalRequestFieldWithPath("startAt").description(MgmtApiModelProperties.ROLLOUT_START_AT)
.type(JsonFieldType.NUMBER),
optionalRequestFieldWithPath("successCondition") optionalRequestFieldWithPath("successCondition")
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION), .description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
optionalRequestFieldWithPath("successCondition.condition") optionalRequestFieldWithPath("successCondition.condition")
@@ -679,6 +687,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
if (isMultiAssignmentsEnabled()) { if (isMultiAssignmentsEnabled()) {
rolloutCreate.weight(400); rolloutCreate.weight(400);
} }
rolloutCreate.forcedTime(System.currentTimeMillis() + 12345);
final Rollout rollout = rolloutManagement.create(rolloutCreate, 5, false, new RolloutGroupConditionBuilder() final Rollout rollout = rolloutManagement.create(rolloutCreate, 5, false, new RolloutGroupConditionBuilder()
.withDefaults().successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build()); .withDefaults().successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build());
@@ -686,7 +695,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
rolloutManagement.handleRollouts(); rolloutManagement.handleRollouts();
return rolloutManagement return rolloutManagement
.update(entityFactory.rollout().update(rollout.getId()).description("exampleDescription")); .update(entityFactory.rollout().update(rollout.getId()).startAt(System.currentTimeMillis() + 1000).description("exampleDescription"));
} }
} }