Feature mgmt simulator semi aware (#377)

* Mgmt simulator is Semic automatic rollout aware

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2016-12-06 19:33:53 +01:00
committed by GitHub
parent 173f782af8
commit d15084974a
4 changed files with 135 additions and 18 deletions

View File

@@ -8,9 +8,12 @@
*/ */
package org.eclipse.hawkbit.mgmt.client.resource.builder; package org.eclipse.hawkbit.mgmt.client.resource.builder;
import java.util.List;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition; import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition.Condition; import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutCondition.Condition;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBody; import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBody;
import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup;
/** /**
* *
@@ -28,6 +31,7 @@ public class RolloutBuilder {
private String successThreshold; private String successThreshold;
private String errorThreshold; private String errorThreshold;
private String description; private String description;
private List<MgmtRolloutGroup> semiAutomaticGroups;
/** /**
* @param name * @param name
@@ -39,6 +43,16 @@ public class RolloutBuilder {
return this; return this;
} }
/**
* @param semiAutomaticGroups
* as alternative to full automatic, i.e. {@link #groupSize(int)}
* @return the builder itself
*/
public RolloutBuilder semiAutomaticGroups(final List<MgmtRolloutGroup> semiAutomaticGroups) {
this.semiAutomaticGroups = semiAutomaticGroups;
return this;
}
/** /**
* @param groupSize * @param groupSize
* the amount of groups the rollout should be split into * the amount of groups the rollout should be split into
@@ -121,6 +135,7 @@ public class RolloutBuilder {
body.setDescription(description); body.setDescription(description);
body.setSuccessCondition(new MgmtRolloutCondition(Condition.THRESHOLD, successThreshold)); body.setSuccessCondition(new MgmtRolloutCondition(Condition.THRESHOLD, successThreshold));
body.setErrorCondition(new MgmtRolloutCondition(Condition.THRESHOLD, errorThreshold)); body.setErrorCondition(new MgmtRolloutCondition(Condition.THRESHOLD, errorThreshold));
body.setGroups(semiAutomaticGroups);
return body; return body;
} }

View File

@@ -110,7 +110,7 @@ public class TargetBuilder {
public List<MgmtTargetRequestBody> buildAsList(final int offset, final int count) { public List<MgmtTargetRequestBody> buildAsList(final int offset, final int count) {
final List<MgmtTargetRequestBody> bodyList = Lists.newArrayList(); final List<MgmtTargetRequestBody> bodyList = Lists.newArrayList();
for (int index = offset; index < count + offset; index++) { for (int index = offset; index < count + offset; index++) {
bodyList.add(doBuild(String.valueOf(index))); bodyList.add(doBuild(String.format("%06d", index)));
} }
return bodyList; return bodyList;
} }

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.mgmt.client; package org.eclipse.hawkbit.mgmt.client;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -55,8 +56,10 @@ public class ClientConfigurationProperties {
private int artifactsPerSM = 1; private int artifactsPerSM = 1;
private String targetAddress = "amqp:/simulator.replyTo"; private String targetAddress = "amqp:/simulator.replyTo";
private boolean runRollouts = true; private boolean runRollouts = true;
private boolean runSemiAutomaticRollouts = true;
private short rolloutSuccessThreshold = 80; private short rolloutSuccessThreshold = 80;
private int rolloutDeploymentGroups = 4; private int rolloutDeploymentGroups = 4;
private List<String> deviceGroups = Arrays.asList("EU", "AM", "APAC");
/** /**
* Targets tags per page. * Targets tags per page.
@@ -74,6 +77,22 @@ public class ClientConfigurationProperties {
*/ */
private String artifactSize = "1MB"; private String artifactSize = "1MB";
public boolean isRunSemiAutomaticRollouts() {
return runSemiAutomaticRollouts;
}
public void setRunSemiAutomaticRollouts(final boolean runSemiAutomaticRollouts) {
this.runSemiAutomaticRollouts = runSemiAutomaticRollouts;
}
public List<String> getDeviceGroups() {
return deviceGroups;
}
public void setDeviceGroups(final List<String> deviceGroups) {
this.deviceGroups = deviceGroups;
}
public boolean isCleanRepository() { public boolean isCleanRepository() {
return cleanRepository; return cleanRepository;
} }

View File

@@ -8,6 +8,7 @@
*/ */
package org.eclipse.hawkbit.mgmt.client.scenarios; package org.eclipse.hawkbit.mgmt.client.scenarios;
import java.security.SecureRandom;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -32,6 +33,7 @@ import org.eclipse.hawkbit.mgmt.client.scenarios.upload.ArtifactFile;
import org.eclipse.hawkbit.mgmt.json.model.PagedList; import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet; import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody; import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody;
import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule; import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedDistributionSetRequestBody; import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedDistributionSetRequestBody;
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedTargetRequestBody; import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtAssignedTargetRequestBody;
@@ -40,6 +42,8 @@ import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists;
/** /**
* *
* A configurable scenario which runs the configured scenarios. * A configurable scenario which runs the configured scenarios.
@@ -100,12 +104,30 @@ public class ConfigurableScenario {
cleanRepository(); cleanRepository();
} }
createTargets(scenario); final List<Long> deviceGroupTags = createDeviceGroupTags(scenario.getDeviceGroups());
createTargets(scenario, deviceGroupTags);
createDistributionSets(scenario); createDistributionSets(scenario);
if (scenario.isRunRollouts()) { if (scenario.isRunRollouts()) {
runRollouts(scenario); runRollouts(scenario);
} }
if (scenario.isRunRollouts()) {
runRollouts(scenario);
}
if (scenario.isRunSemiAutomaticRollouts() && !scenario.getDeviceGroups().isEmpty()) {
runSemiAutomaticRollouts(scenario);
}
}
private List<Long> createDeviceGroupTags(final List<String> deviceGroups) {
return deviceGroups.stream()
.map(group -> targetTagResource
.createTargetTags(new TagBuilder().name(group).description("Group " + group).build()).getBody()
.get(0).getTagId())
.collect(Collectors.toList());
} }
private void cleanRepository() { private void cleanRepository() {
@@ -174,7 +196,50 @@ public class ConfigurableScenario {
private void runRollouts(final Scenario scenario) { private void runRollouts(final Scenario scenario) {
distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody() distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody()
.getContent().forEach(set -> runRollout(set, scenario)); .getContent().forEach(set -> runRollout(set, scenario));
}
private void runSemiAutomaticRollouts(final Scenario scenario) {
distributionSetResource.getDistributionSets(0, scenario.getDistributionSets(), null, null).getBody()
.getContent().forEach(set -> runSemiAutomaticRollout(set, scenario));
}
private void runSemiAutomaticRollout(final MgmtDistributionSet set, final Scenario scenario) {
LOGGER.info("Run semi automatic rollout for set {}", set.getDsId());
// create a Rollout
final MgmtRolloutResponseBody rolloutResponseBody = rolloutResource.create(new RolloutBuilder()
.name("Rollout" + set.getName() + set.getVersion()).semiAutomaticGroups(createRolloutGroups(scenario))
.targetFilterQuery("name==*").distributionSetId(set.getDsId())
.successThreshold(String.valueOf(scenario.getRolloutSuccessThreshold())).errorThreshold("5").build())
.getBody();
waitUntilRolloutIsReady(rolloutResponseBody.getRolloutId());
// start the created Rollout
rolloutResource.start(rolloutResponseBody.getRolloutId());
waitUntilRolloutIsComplete(scenario);
LOGGER.info("Run rollout for set {} -> Done", set.getDsId());
}
private static List<MgmtRolloutGroup> createRolloutGroups(final Scenario scenario) {
final List<MgmtRolloutGroup> result = Lists.newArrayListWithCapacity(scenario.getDeviceGroups().size() * 2);
scenario.getDeviceGroups().forEach(groupname -> {
result.add(createGroup(1, groupname, 10F));
result.add(createGroup(2, groupname, 50F));
result.add(createGroup(3, groupname, 100F));
});
return result;
}
private static MgmtRolloutGroup createGroup(final int number, final String groupname, final Float percent) {
final MgmtRolloutGroup one = new MgmtRolloutGroup();
one.setName(groupname + "-" + number);
one.setDescription("Group of " + groupname);
one.setTargetFilterQuery("tag==" + groupname);
one.setTargetPercentage(percent);
return one;
} }
private void runRollout(final MgmtDistributionSet set, final Scenario scenario) { private void runRollout(final MgmtDistributionSet set, final Scenario scenario) {
@@ -186,20 +251,16 @@ public class ConfigurableScenario {
.successThreshold(String.valueOf(scenario.getRolloutSuccessThreshold())).errorThreshold("5").build()) .successThreshold(String.valueOf(scenario.getRolloutSuccessThreshold())).errorThreshold("5").build())
.getBody(); .getBody();
do { waitUntilRolloutIsReady(rolloutResponseBody.getRolloutId());
try {
TimeUnit.SECONDS.sleep(5);
} catch (final InterruptedException e) {
LOGGER.warn("Interrupted!");
Thread.currentThread().interrupt();
}
} while (!"READY".equalsIgnoreCase(
rolloutResource.getRollout(rolloutResponseBody.getRolloutId()).getBody().getStatus()));
// start the created Rollout // start the created Rollout
rolloutResource.start(rolloutResponseBody.getRolloutId()); rolloutResource.start(rolloutResponseBody.getRolloutId());
// wait until rollout is complete waitUntilRolloutIsComplete(scenario);
LOGGER.info("Run rollout for set {} -> Done", set.getDsId());
}
private void waitUntilRolloutIsComplete(final Scenario scenario) {
do { do {
try { try {
TimeUnit.SECONDS.sleep(35); TimeUnit.SECONDS.sleep(35);
@@ -209,7 +270,17 @@ public class ConfigurableScenario {
} }
} while (targetResource.getTargets(0, 1, null, "updateStatus==IN_SYNC").getBody().getTotal() < scenario } while (targetResource.getTargets(0, 1, null, "updateStatus==IN_SYNC").getBody().getTotal() < scenario
.getTargets()); .getTargets());
LOGGER.info("Run rollout for set {} -> Done", set.getDsId()); }
private void waitUntilRolloutIsReady(final Long id) {
do {
try {
TimeUnit.SECONDS.sleep(5);
} catch (final InterruptedException e) {
LOGGER.warn("Interrupted!");
Thread.currentThread().interrupt();
}
} while (!"READY".equalsIgnoreCase(rolloutResource.getRollout(id).getBody().getStatus()));
} }
private void createDistributionSets(final Scenario scenario) { private void createDistributionSets(final Scenario scenario) {
@@ -275,16 +346,18 @@ public class ConfigurableScenario {
return modules; return modules;
} }
private void createTargets(final Scenario scenario) { private void createTargets(final Scenario scenario, final List<Long> deviceGroupTags) {
LOGGER.info("Creating {} targets", scenario.getTargets()); LOGGER.info("Creating {} targets", scenario.getTargets());
IntStream.range(0, scenario.getTargets() / PAGE_SIZE).parallel().forEach(i -> createTargetPage(scenario, i)); IntStream.range(0, scenario.getTargets() / PAGE_SIZE).parallel()
.forEach(i -> createTargetPage(scenario, i, deviceGroupTags));
LOGGER.info("Creating {} targets -> Done", scenario.getTargets()); LOGGER.info("Creating {} targets -> Done", scenario.getTargets());
} }
private void createTargetPage(final Scenario scenario, final int page) { private void createTargetPage(final Scenario scenario, final int page, final List<Long> deviceGroupTags) {
final List<MgmtTarget> targets = createTargets(scenario, page); final List<MgmtTarget> targets = createTargets(scenario, page);
tagTargets(scenario, page, targets); tagTargets(scenario, page, targets, deviceGroupTags);
} }
private List<MgmtTarget> createTargets(final Scenario scenario, final int page) { private List<MgmtTarget> createTargets(final Scenario scenario, final int page) {
@@ -297,7 +370,8 @@ public class ConfigurableScenario {
.getBody(); .getBody();
} }
private void tagTargets(final Scenario scenario, final int page, final List<MgmtTarget> targets) { private void tagTargets(final Scenario scenario, final int page, final List<MgmtTarget> targets,
final List<Long> deviceGroupTags) {
if (scenario.getTargetTags() > 0) { if (scenario.getTargetTags() > 0) {
targetTagResource targetTagResource
.createTargetTags(new TagBuilder().name("Page " + page) .createTargetTags(new TagBuilder().name("Page " + page)
@@ -307,6 +381,15 @@ public class ConfigurableScenario {
target -> new MgmtAssignedTargetRequestBody().setControllerId(target.getControllerId())) target -> new MgmtAssignedTargetRequestBody().setControllerId(target.getControllerId()))
.collect(Collectors.toList()))); .collect(Collectors.toList())));
} }
if (!deviceGroupTags.isEmpty()) {
final Long tagid = deviceGroupTags.get(new SecureRandom().nextInt(deviceGroupTags.size()));
targetTagResource.assignTargets(tagid,
targets.stream().map(
target -> new MgmtAssignedTargetRequestBody().setControllerId(target.getControllerId()))
.collect(Collectors.toList()));
}
} }
private static int calculateOffset(final int page) { private static int calculateOffset(final int page) {