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:
Dominik Herbst
2016-11-16 09:26:50 +01:00
committed by Michael Hirsch
parent 66b6983406
commit b6834e9ee2
37 changed files with 2009 additions and 457 deletions

View File

@@ -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) {