Assign multiple distribution sets to a target via mgmt api (#886)

* Add multiassignment to mgmt api target endpoint
* Remove single assignment ds to targets offline
* Fix tests
* Add quota for maxResultingActionsPerManualAssignment
* Fix assignment with same target or distribution set multiple times in one request
* Log UI error
* Add tests
* Enable single assignment requests with multiple DSs and types
* Remove redundant target to DS assignment methods
* Add tests, fix assignment
* Fix possible nullpointer during target assignment request
* Update api docu
* Clean up deployment management code
* Enforce MaxActions quota for offline assignment
* Fix review findings
* Rename property, add migration into
* Add builder for DeploymentRequest
* Change offline assignment method to accept an assignment list, like online assignment
* Fix PR findings

Signed-off-by: Stefan Klotz <stefan.klotz@bosch-si.com>
This commit is contained in:
Stefan Klotz
2019-09-17 14:20:26 +02:00
committed by Stefan Behl
parent dba972423b
commit 8687510131
50 changed files with 1466 additions and 559 deletions

View File

@@ -27,10 +27,12 @@ import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.apache.commons.lang3.RandomStringUtils;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
import org.eclipse.hawkbit.repository.model.Action;
@@ -40,7 +42,6 @@ import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetWithActionType;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
@@ -299,11 +300,10 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
}
@Test
@Description("Ensures that multi target assignment is protected by our 'max targets per manual assignment' quota.")
@Description("Ensures that multi target assignment is protected by our getMaxTargetDistributionSetAssignmentsPerManualAssignment quota.")
public void assignMultipleTargetsToDistributionSetUntilQuotaIsExceeded() throws Exception {
final int maxTargets = quotaManagement.getMaxTargetsPerManualAssignment();
final List<Target> targets = testdataFactory.createTargets(maxTargets + 1);
final int maxActions = quotaManagement.getMaxTargetDistributionSetAssignmentsPerManualAssignment();
final List<Target> targets = testdataFactory.createTargets(maxActions + 1);
final DistributionSet ds = testdataFactory.createDistributionSet();
final JSONArray payload = new JSONArray();
@@ -943,8 +943,7 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
assertThat(distributionSetManagement.findByCompleted(PAGE, true)).hasSize(0);
final DistributionSet set = testdataFactory.createDistributionSet("one");
deploymentManagement.assignDistributionSet(set.getId(),
Arrays.asList(new TargetWithActionType(testdataFactory.createTarget().getControllerId())));
assignDistributionSet(set.getId(), testdataFactory.createTarget().getControllerId());
assertThat(distributionSetManagement.count()).isEqualTo(1);
@@ -1273,4 +1272,63 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
.as("Five targets in repository have DS assigned").hasSize(5);
}
@Test
@Description("A request for assigning a target multiple times results in a Bad Request when multiassignment is disabled.")
public void multiassignmentRequestNotAllowedIfDisabled() throws Exception {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final JSONArray body = new JSONArray();
body.put(getAssignmentObject(targetId, MgmtActionType.SOFT));
body.put(getAssignmentObject(targetId, MgmtActionType.FORCED));
mvc.perform(post("/rest/v1/distributionsets/{ds}/assignedTargets", dsId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
}
@Test
@Description("Identical assignments in a single request are removed when multiassignment is disabled.")
public void identicalAssignmentInRequestAreRemovedIfMultiassignmentsDisabled() throws Exception {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final JSONArray body = new JSONArray();
body.put(getAssignmentObject(targetId, MgmtActionType.FORCED));
body.put(getAssignmentObject(targetId, MgmtActionType.FORCED));
mvc.perform(post("/rest/v1/distributionsets/{ds}/assignedTargets", dsId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("total", equalTo(1)));
}
@Test
@Description("Assigning targets multiple times to a DS in one request works in multiassignment mode.")
public void multiAssignment() throws Exception {
final List<String> targetIds = testdataFactory.createTargets(2).stream().map(Target::getControllerId)
.collect(Collectors.toList());
final Long dsId = testdataFactory.createDistributionSet().getId();
final JSONArray body = new JSONArray();
body.put(getAssignmentObject(targetIds.get(0), MgmtActionType.FORCED));
body.put(getAssignmentObject(targetIds.get(0), MgmtActionType.FORCED));
body.put(getAssignmentObject(targetIds.get(1), MgmtActionType.FORCED));
body.put(getAssignmentObject(targetIds.get(1), MgmtActionType.SOFT));
enableMultiAssignments();
mvc.perform(post("/rest/v1/distributionsets/{ds}/assignedTargets", dsId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("total", equalTo(body.length())));
}
public static JSONObject getAssignmentObject(final String targetId, final MgmtActionType type)
throws JSONException {
final JSONObject obj = new JSONObject();
obj.put("id", targetId);
obj.put("type", type.getName());
return obj;
}
}

View File

@@ -26,6 +26,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@@ -60,6 +61,7 @@ import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.eclipse.hawkbit.util.IpUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.springframework.data.domain.PageRequest;
@@ -1240,8 +1242,8 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
public void updateAction() throws Exception {
final Target target = testdataFactory.createTarget();
final DistributionSet set = testdataFactory.createDistributionSet();
final Long actionId = getFirstAssignedActionId(deploymentManagement.assignDistributionSet(set.getId(),
ActionType.SOFT, 0, Collections.singletonList(target.getControllerId())));
final Long actionId = getFirstAssignedActionId(
assignDistributionSet(set.getId(), target.getControllerId(), ActionType.SOFT));
assertThat(deploymentManagement.findAction(actionId).get().getActionType()).isEqualTo(ActionType.SOFT);
final String body = new JSONObject().put("forceType", "forced").toString();
@@ -1293,7 +1295,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
@Description("Verfies that a DOWNLOAD_ONLY DS to target assignment is properly handled")
public void assignDownloadOnlyDistributionSetToTarget() throws Exception {
Target target = testdataFactory.createTarget();
final Target target = testdataFactory.createTarget();
final DistributionSet set = testdataFactory.createDistributionSet("one");
mvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + target.getControllerId() + "/assignedDS")
@@ -1303,7 +1305,7 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
.andExpect(jsonPath("total", equalTo(1)));
assertThat(deploymentManagement.getAssignedDistributionSet(target.getControllerId()).get()).isEqualTo(set);
Slice<Action> actions = deploymentManagement.findActionsByTarget("targetExist", PageRequest.of(0, 100));
final Slice<Action> actions = deploymentManagement.findActionsByTarget("targetExist", PageRequest.of(0, 100));
assertThat(actions.getSize()).isGreaterThan(0);
actions.stream().filter(a -> a.getDistributionSet().equals(set))
.forEach(a -> ActionType.DOWNLOAD_ONLY.equals(a.getActionType()));
@@ -1866,4 +1868,69 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
.andExpect(jsonPath("total", equalTo(1))).andExpect(jsonPath("content[0].key", equalTo("knownKey1")))
.andExpect(jsonPath("content[0].value", equalTo("knownValue1")));
}
@Test
@Description("A request for assigning multiple DS to a target results in a Bad Request when multiassignment in disabled.")
public void multiassignmentRequestNotAllowedIfDisabled() throws Exception {
final String targetId = testdataFactory.createTarget().getControllerId();
final List<Long> dsIds = testdataFactory.createDistributionSets(2).stream().map(DistributionSet::getId)
.collect(Collectors.toList());
final JSONArray body = getAssignmentBody(dsIds);
mvc.perform(post("/rest/v1/targets/{targetId}/assignedDS", targetId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
}
@Test
@Description("Passing an array in assignment request is allowed if multiassignment is disabled and array size in 1.")
public void multiassignmentRequestAllowedIfDisabledButHasSizeOne() throws Exception {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final JSONArray body = getAssignmentBody(Collections.singletonList(dsId));
mvc.perform(post("/rest/v1/targets/{targetId}/assignedDS", targetId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
}
@Test
@Description("Identical assignments in a single request are removed when multiassignment in disabled.")
public void identicalAssignmentInRequestAreRemovedIfMultiassignmentsDisabled() throws Exception {
final String targetId = testdataFactory.createTarget().getControllerId();
final Long dsId = testdataFactory.createDistributionSet().getId();
final JSONArray body = getAssignmentBody(Arrays.asList(dsId, dsId));
mvc.perform(post("/rest/v1/targets/{targetId}/assignedDS", targetId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(jsonPath("total", equalTo(1)));
}
@Test
@Description("Assign multiple DSs to a target in one request with multiassignments enabled.")
public void multiAssignment() throws Exception {
final String targetId = testdataFactory.createTarget().getControllerId();
final List<Long> dsIds = testdataFactory.createDistributionSets(2).stream().map(DistributionSet::getId)
.collect(Collectors.toList());
final JSONArray body = getAssignmentBody(dsIds);
enableMultiAssignments();
mvc.perform(post("/rest/v1/targets/{targetId}/assignedDS", targetId).content(body.toString())
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(jsonPath("total", equalTo(2)));
}
public static JSONArray getAssignmentBody(final Collection<Long> dsIds) throws JSONException {
final JSONArray body = new JSONArray();
for (final Long id : dsIds) {
final JSONObject obj = new JSONObject();
obj.put("id", id);
body.put(obj);
}
return body;
}
}