Semi automatic Rollouts with fine groups definition (#337)
* Rollout Mgmt API accepts now extended Group definition. Filling Reollout Groups with Targets is now a scheduled task. Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Fire RolloutGroupCreated event and fix db migration. Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Fill groups now excludes targets in own group Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Starting of Rollouts as scheduled task Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Finished implementation of new Rollout starting proccess Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Reset last check on status change and fixed unused imports Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Code quality improvements Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com> * Reworked start of scheduled Actions. Improved code quality. Signed-off-by: Dominik Herbst <dominik.herbst@bosch-si.com>
This commit is contained in:
committed by
Michael Hirsch
parent
66b6983406
commit
b6834e9ee2
@@ -18,6 +18,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -30,6 +31,7 @@ import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||
@@ -117,8 +119,85 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
@Test
|
||||
@Description("Testing that rollout can be created")
|
||||
public void createRollout() throws Exception {
|
||||
targetManagement.createTargets(testdataFactory.generateTargets(20, "target", "rollout"));
|
||||
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
postRollout("rollout1", 10, dsA.getId(), "name==target1");
|
||||
postRollout("rollout1", 10, dsA.getId(), "id==target*");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout can be created with groups")
|
||||
public void createRolloutWithGroupsDefinitions() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro");
|
||||
|
||||
final int amountTargets = 10;
|
||||
targetManagement.createTargets(testdataFactory.generateTargets(amountTargets, "ro-target", "rollout"));
|
||||
|
||||
List<RolloutGroup> rolloutGroups = new ArrayList<>(2);
|
||||
final int percentTargetsInGroup1 = 20;
|
||||
final int percentTargetsInGroup2 = 100;
|
||||
|
||||
RolloutGroup group1 = entityFactory.generateRolloutGroup();
|
||||
group1.setName("Group1");
|
||||
group1.setDescription("Group1desc");
|
||||
group1.setTargetPercentage(percentTargetsInGroup1);
|
||||
rolloutGroups.add(group1);
|
||||
|
||||
RolloutGroup group2 = entityFactory.generateRolloutGroup();
|
||||
group2.setName("Group2");
|
||||
group2.setDescription("Group2desc");
|
||||
group2.setTargetPercentage(percentTargetsInGroup2);
|
||||
rolloutGroups.add(group2);
|
||||
|
||||
RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().build();
|
||||
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout2", "desc", null, dsA.getId(), "id==ro-target*",
|
||||
rolloutGroupConditions, rolloutGroups))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andReturn();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that no rollout with groups that have illegal percentages can be created")
|
||||
public void createRolloutWithIllegalPercentages() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro2");
|
||||
|
||||
final int amountTargets = 10;
|
||||
targetManagement.createTargets(testdataFactory.generateTargets(amountTargets, "ro-target", "rollout"));
|
||||
|
||||
List<RolloutGroup> rolloutGroups = new ArrayList<>(2);
|
||||
|
||||
RolloutGroup group1 = entityFactory.generateRolloutGroup();
|
||||
group1.setName("Group1");
|
||||
group1.setDescription("Group1desc");
|
||||
group1.setTargetPercentage(0);
|
||||
rolloutGroups.add(group1);
|
||||
|
||||
RolloutGroup group2 = entityFactory.generateRolloutGroup();
|
||||
group2.setName("Group2");
|
||||
group2.setDescription("Group2desc");
|
||||
group2.setTargetPercentage(100);
|
||||
rolloutGroups.add(group2);
|
||||
|
||||
RolloutGroupConditions rolloutGroupConditions = new RolloutGroupConditionBuilder().build();
|
||||
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout4", "desc", null, dsA.getId(), "id==ro-target*",
|
||||
rolloutGroupConditions, rolloutGroups))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isInternalServerError())
|
||||
.andExpect(jsonPath("$.errorCode", equalTo("hawkbit.server.error.repo.constraintViolation")));
|
||||
|
||||
group1.setTargetPercentage(101);
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout4", "desc", null, dsA.getId(), "id==ro-target*",
|
||||
rolloutGroupConditions, rolloutGroups))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isInternalServerError())
|
||||
.andExpect(jsonPath("$.errorCode", equalTo("hawkbit.server.error.repo.constraintViolation")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -133,20 +212,26 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
@Description("Testing that rollout paged list contains rollouts")
|
||||
public void rolloutPagedListContainsAllRollouts() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
targetManagement.createTargets(testdataFactory.generateTargets(20, "target", "rollout"));
|
||||
|
||||
// setup - create 2 rollouts
|
||||
postRollout("rollout1", 10, dsA.getId(), "name==target1");
|
||||
postRollout("rollout2", 5, dsA.getId(), "name==target2");
|
||||
postRollout("rollout1", 10, dsA.getId(), "id==target*");
|
||||
postRollout("rollout2", 5, dsA.getId(), "id==target-0001*");
|
||||
|
||||
// Run here, because Scheduler is disabled during tests
|
||||
rolloutManagement.checkCreatingRollouts(0);
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_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("name==target1")))
|
||||
.andExpect(jsonPath("content[0].targetFilterQuery", equalTo("id==target*")))
|
||||
.andExpect(jsonPath("content[0].distributionSetId", equalTo(dsA.getId().intValue())))
|
||||
.andExpect(jsonPath("content[1].name", equalTo("rollout2")))
|
||||
.andExpect(jsonPath("content[1].status", equalTo("ready")))
|
||||
.andExpect(jsonPath("content[1].targetFilterQuery", equalTo("name==target2")))
|
||||
.andExpect(jsonPath("content[1].targetFilterQuery", equalTo("id==target-0001*")))
|
||||
.andExpect(jsonPath("content[1].distributionSetId", equalTo(dsA.getId().intValue())));
|
||||
}
|
||||
|
||||
@@ -154,9 +239,15 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
@Description("Testing that rollout paged list is limited by the query param limit")
|
||||
public void rolloutPagedListIsLimitedToQueryParam() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
targetManagement.createTargets(testdataFactory.generateTargets(20, "target", "rollout"));
|
||||
|
||||
// setup - create 2 rollouts
|
||||
postRollout("rollout1", 10, dsA.getId(), "name==target1");
|
||||
postRollout("rollout2", 5, dsA.getId(), "name==target2");
|
||||
postRollout("rollout1", 10, dsA.getId(), "id==target*");
|
||||
postRollout("rollout2", 5, dsA.getId(), "id==target*");
|
||||
|
||||
// Run here, because Scheduler is disabled during tests
|
||||
rolloutManagement.checkCreatingRollouts(0);
|
||||
|
||||
mvc.perform(get("/rest/v1/rollouts?limit=1")).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
@@ -186,7 +277,7 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that starting the rollout switches the state to running")
|
||||
@Description("Testing that starting the rollout switches the state to starting and then to running")
|
||||
public void startingRolloutSwitchesIntoRunningState() throws Exception {
|
||||
// setup
|
||||
final int amountTargets = 20;
|
||||
@@ -200,6 +291,15 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// check rollout is in starting state
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("id", equalTo(rollout.getId().intValue())))
|
||||
.andExpect(jsonPath("status", equalTo("starting")));
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
// check rollout is in running state
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
@@ -222,6 +322,9 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
// pausing rollout
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/pause", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
@@ -248,6 +351,9 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
// pausing rollout
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/pause", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
@@ -278,6 +384,9 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
// starting rollout - already started should lead into bad request
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isBadRequest())
|
||||
@@ -316,6 +425,9 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
// retrieve rollout groups from created rollout - 2 groups exists
|
||||
// (amountTargets / groupSize = 2)
|
||||
mvc.perform(get("/rest/v1/rollouts/{rolloutId}/deploygroups?sort=ID:ASC", rollout.getId()))
|
||||
@@ -409,6 +521,9 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
|
||||
rolloutManagement.startRollout(rollout);
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
final RolloutGroup firstGroup = rolloutGroupManagement
|
||||
.findRolloutGroupsByRolloutId(rollout.getId(), new PageRequest(0, 1, Direction.ASC, "id")).getContent()
|
||||
.get(0);
|
||||
@@ -432,10 +547,12 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
final Rollout rollout = createRollout("rollout1", 4, dsA.getId(), "controllerId==rollout*");
|
||||
|
||||
// starting rollout
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())
|
||||
.param(MgmtRestConstants.REQUEST_PARAMETER_ASYNC, "true")).andDo(MockMvcResultPrinter.print())
|
||||
mvc.perform(post("/rest/v1/rollouts/{rolloutId}/start", rollout.getId())).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Run here, because scheduler is disabled during tests
|
||||
rolloutManagement.checkStartingRollouts(0);
|
||||
|
||||
// check if running
|
||||
assertThat(doWithTimeout(() -> getRollout(rollout.getId()), result -> success(result), 60_000, 100))
|
||||
.isNotNull();
|
||||
@@ -549,19 +666,25 @@ public class MgmtRolloutResourceTest extends AbstractRestIntegrationTest {
|
||||
private void postRollout(final String name, final int groupSize, final long distributionSetId,
|
||||
final String targetFilterQuery) throws Exception {
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout(name, "desc", groupSize, distributionSetId, targetFilterQuery, null))
|
||||
.content(JsonBuilder.rollout(name, "desc", groupSize, distributionSetId, targetFilterQuery,
|
||||
new RolloutGroupConditionBuilder().build()))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated()).andReturn();
|
||||
}
|
||||
|
||||
private Rollout createRollout(final String name, final int amountGroups, final long distributionSetId,
|
||||
final String targetFilterQuery) {
|
||||
final Rollout rollout = entityFactory.generateRollout();
|
||||
Rollout rollout = entityFactory.generateRollout();
|
||||
rollout.setDistributionSet(distributionSetManagement.findDistributionSetById(distributionSetId));
|
||||
rollout.setName(name);
|
||||
rollout.setTargetFilterQuery(targetFilterQuery);
|
||||
return rolloutManagement.createRollout(rollout, amountGroups, new RolloutGroupConditionBuilder()
|
||||
rollout = rolloutManagement.createRollout(rollout, amountGroups, new RolloutGroupConditionBuilder()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "100").build());
|
||||
|
||||
// Run here, because Scheduler is disabled during tests
|
||||
rolloutManagement.fillRolloutGroupsWithTargets(rolloutManagement.findRolloutById(rollout.getId()));
|
||||
|
||||
return rolloutManagement.findRolloutById(rollout.getId());
|
||||
}
|
||||
|
||||
protected boolean success(final Rollout result) {
|
||||
|
||||
Reference in New Issue
Block a user