Protection against misuse with system-wide quota definitions (#670)
* Added quota for meta data per software module Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Added unit test for "meta data per module" quota Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * quota test enhancements Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Verify enforcement of meta data quota via REST Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quota for distribution set meta data Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Verify enforcement of distribution set meta data quota via REST Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * software modules per distribution set quota Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Integration test enhancements for Modules per DistSet quota Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quota for software module types per distribution set type Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quota for max artifacts per software module Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quotas for ActionStatus per Action and Messages per ActionStatus Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quota attributes per target Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quota targets per rollout group Signed-off-by: stefbehl <stefan.behl@bosch-si.com> * Quota max targets per rollout group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per rollout group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per rollout group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per rollout group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * quota max actions per target Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per rollout group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max actions per target Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max actions per target Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per auto assignment Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per manual assignment Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per auto assignment Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per auto assign Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per auto assignment Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max actions per target Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per manual assignment Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix issues caused by merge Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Improve JavaDoc Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Sonar issues Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Sonar findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max artifact size Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Optimize quota configuration Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix test failures Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Improve test coverage Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max rollout groups per rollout Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Configure Rollout UI enhancements Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * UI enhancements Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Minor changes Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Quota max targets per group Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Sonar findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Sonar findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Sonar finding Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix code review findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix review findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * New approach for 'max artifact size' enforcement Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Sonar findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix failing tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Reduce max artifact size for tests Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com> * Fix Kai's review findings Signed-off-by: Stefan Behl <stefan.behl@bosch-si.com>
This commit is contained in:
committed by
Kai Zimmermann
parent
fcc15a0484
commit
6dd98d2134
@@ -46,11 +46,13 @@ final class MgmtRestModelMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a action rest type to a action repository type.
|
||||
* Convert the given {@link MgmtActionType} into a corresponding repository
|
||||
* {@link ActionType}.
|
||||
*
|
||||
* @param actionTypeRest
|
||||
* the rest type
|
||||
* @return <null> or the action repository type
|
||||
* the REST representation of the action type
|
||||
*
|
||||
* @return <null> or the repository action type
|
||||
*/
|
||||
public static ActionType convertActionType(final MgmtActionType actionTypeRest) {
|
||||
if (actionTypeRest == null) {
|
||||
@@ -70,11 +72,13 @@ final class MgmtRestModelMapper {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a action repository type to rest type.
|
||||
* Converts the given repository {@link ActionType} into a corresponding
|
||||
* {@link MgmtActionType}.
|
||||
*
|
||||
* @param actionType
|
||||
* the rest type
|
||||
* @return <null> or the action repository type
|
||||
* the repository representation of the action type
|
||||
*
|
||||
* @return <null> or the REST action type
|
||||
*/
|
||||
public static MgmtActionType convertActionType(final ActionType actionType) {
|
||||
if (actionType == null) {
|
||||
|
||||
@@ -83,7 +83,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
|
||||
try (InputStream in = file.getInputStream()) {
|
||||
final Artifact result = artifactManagement.create(in, softwareModuleId, fileName,
|
||||
md5Sum == null ? null : md5Sum.toLowerCase(), sha1Sum == null ? null : sha1Sum.toLowerCase(), false,
|
||||
file.getContentType());
|
||||
file.getContentType(), file.getSize());
|
||||
|
||||
final MgmtArtifact reponse = MgmtSoftwareModuleMapper.toResponse(result);
|
||||
MgmtSoftwareModuleMapper.addLinks(result, reponse);
|
||||
|
||||
@@ -27,9 +27,12 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
@@ -44,9 +47,11 @@ import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
|
||||
@@ -179,6 +184,45 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
||||
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet.getId() + "/assignedSM"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.size", equalTo(smIDs.size())));
|
||||
|
||||
// verify quota enforcement
|
||||
final int maxSoftwareModules = quotaManagement.getMaxSoftwareModulesPerDistributionSet();
|
||||
final List<Long> moduleIDs = Lists.newArrayList();
|
||||
for (int i = 0; i < maxSoftwareModules + 1; ++i) {
|
||||
moduleIDs.add(testdataFactory.createSoftwareModuleApp("sm" + i).getId());
|
||||
}
|
||||
|
||||
// post assignment
|
||||
final String jsonIDs = JsonBuilder.ids(moduleIDs.subList(0, maxSoftwareModules - smIDs.size()));
|
||||
mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet.getId() + "/assignedSM")
|
||||
.contentType(MediaType.APPLICATION_JSON).content(jsonIDs)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk());
|
||||
// test if size corresponds with quota
|
||||
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet.getId()
|
||||
+ "/assignedSM?limit={limit}", maxSoftwareModules * 2)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isOk()).andExpect(jsonPath("$.size", equalTo(maxSoftwareModules)));
|
||||
|
||||
// post one more to cause the quota to be exceeded
|
||||
mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet.getId() + "/assignedSM")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(JsonBuilder.ids(Collections.singletonList(moduleIDs.get(moduleIDs.size() - 1)))))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
// verify quota is also enforced for bulk uploads
|
||||
final DistributionSet disSet2 = testdataFactory.createDistributionSetWithNoSoftwareModules("Saturn", "4.0");
|
||||
mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet2.getId() + "/assignedSM")
|
||||
.contentType(MediaType.APPLICATION_JSON).content(JsonBuilder.ids(moduleIDs)))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
// verify size is still 0
|
||||
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + disSet2.getId() + "/assignedSM"))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.size", equalTo(0)));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -229,6 +273,48 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
||||
.as("Five targets in repository have DS assigned").hasSize(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that multi target assignment is protected by our 'max targets per manual assignment' quota.")
|
||||
public void assignMultipleTargetsToDistributionSetUntilQuotaIsExceeded() throws Exception {
|
||||
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerManualAssignment();
|
||||
final List<Target> targets = testdataFactory.createTargets(maxTargets + 1);
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet();
|
||||
|
||||
final JSONArray payload = new JSONArray();
|
||||
targets.forEach(trg -> payload.put(new JSONObject().put("id", trg.getId())));
|
||||
|
||||
mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + ds.getId() + "/assignedTargets")
|
||||
.contentType(MediaType.APPLICATION_JSON).content(payload.toString())).andExpect(status().isForbidden());
|
||||
|
||||
assertThat(targetManagement.findByAssignedDistributionSet(PAGE, ds.getId()).getContent()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the 'max actions per target' quota is enforced if the distribution set assignment of a target is changed permanently")
|
||||
public void changeDistributionSetAssignmentForTargetUntilQuotaIsExceeded() throws Exception {
|
||||
|
||||
// create one target
|
||||
final Target testTarget = testdataFactory.createTarget("trg1");
|
||||
final int maxActions = quotaManagement.getMaxActionsPerTarget();
|
||||
|
||||
// create a set of distribution sets
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("ds3");
|
||||
|
||||
IntStream.range(0, maxActions).forEach(i -> {
|
||||
// toggle the distribution set
|
||||
assignDistributionSet(i % 2 == 0 ? ds1 : ds2, testTarget);
|
||||
});
|
||||
|
||||
// assign our test target to another distribution set and verify that
|
||||
// the 'max actions per target' quota is exceeded
|
||||
final String json = new JSONArray().put(new JSONObject().put("id", testTarget.getControllerId())).toString();
|
||||
mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + ds3.getId() + "/assignedTargets")
|
||||
.contentType(MediaType.APPLICATION_JSON).content(json)).andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that offline reported multi target assignment through API is reflected by the repository.")
|
||||
public void offlineAssignmentOfMultipleTargetsToDistributionSet() throws Exception {
|
||||
@@ -433,14 +519,13 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
||||
final Set<DistributionSet> createDistributionSetsAlphabetical = createDistributionSetsAlphabetical(1);
|
||||
final DistributionSet createdDs = createDistributionSetsAlphabetical.iterator().next();
|
||||
|
||||
targetFilterQueryManagement.updateAutoAssignDS(
|
||||
targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(knownFilterName).query("x==y")).getId(),
|
||||
targetFilterQueryManagement.updateAutoAssignDS(targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(knownFilterName).query("name==y")).getId(),
|
||||
createdDs.getId());
|
||||
|
||||
// create some dummy target filter queries
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("b").query("x==y"));
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("c").query("x==y"));
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("b").query("name==y"));
|
||||
targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name("c").query("name==y"));
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING + "/" + createdDs.getId()
|
||||
+ "/autoAssignTargetFilters")).andExpect(status().isOk()).andExpect(jsonPath("$.size", equalTo(1)))
|
||||
@@ -495,16 +580,16 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
||||
private void prepareTestFilters(final String filterNamePrefix, final DistributionSet createdDs) {
|
||||
// create target filter queries that should be found
|
||||
targetFilterQueryManagement.updateAutoAssignDS(targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "1").query("x==y")).getId(),
|
||||
createdDs.getId());
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "1").query("name==y"))
|
||||
.getId(), createdDs.getId());
|
||||
targetFilterQueryManagement.updateAutoAssignDS(targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "2").query("x==y")).getId(),
|
||||
createdDs.getId());
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "2").query("name==y"))
|
||||
.getId(), createdDs.getId());
|
||||
// create some dummy target filter queries
|
||||
targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "b").query("x==y"));
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "b").query("name==y"));
|
||||
targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "c").query("x==y"));
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "c").query("name==y"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -902,12 +987,12 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
||||
final String knownValue1 = "knownValue1";
|
||||
final String knownValue2 = "knownValue2";
|
||||
|
||||
final JSONArray jsonArray = new JSONArray();
|
||||
jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||
jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2));
|
||||
final JSONArray metaData1 = new JSONArray();
|
||||
metaData1.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||
metaData1.put(new JSONObject().put("key", knownKey2).put("value", knownValue2));
|
||||
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId()).accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString()))
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData1.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
@@ -921,6 +1006,25 @@ public class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegr
|
||||
|
||||
assertThat(metaKey1.getValue()).isEqualTo(knownValue1);
|
||||
assertThat(metaKey2.getValue()).isEqualTo(knownValue2);
|
||||
|
||||
// verify quota enforcement
|
||||
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerDistributionSet();
|
||||
|
||||
final JSONArray metaData2 = new JSONArray();
|
||||
for (int i = 0; i < maxMetaData - metaData1.length() + 1; ++i) {
|
||||
metaData2.put(new JSONObject().put("key", knownKey1 + i).put("value", knownValue1 + i));
|
||||
}
|
||||
|
||||
mvc.perform(post("/rest/v1/distributionsets/{dsId}/metadata", testDS.getId()).accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData2.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden());
|
||||
|
||||
// verify that the number of meta data entries has not changed
|
||||
// (we cannot use the PAGE constant here as it tries to sort by ID)
|
||||
assertThat(distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(new PageRequest(0, Integer.MAX_VALUE), testDS.getId())
|
||||
.getTotalElements()).isEqualTo(metaData1.length());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -27,7 +27,11 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
@@ -239,6 +243,60 @@ public class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIn
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Verifies quota enforcement for /rest/v1/distributionsettypes/{ID}/optionalmoduletypes POST requests.")
|
||||
public void assignModuleTypesToDistributionSetTypeUntilQuotaExceeded() throws Exception {
|
||||
|
||||
// create software module types
|
||||
final int maxSoftwareModuleTypes = quotaManagement.getMaxSoftwareModuleTypesPerDistributionSetType();
|
||||
final List<Long> moduleTypeIds = Lists.newArrayList();
|
||||
for (int i = 0; i < maxSoftwareModuleTypes + 1; ++i) {
|
||||
final SoftwareModuleTypeCreate smCreate = entityFactory.softwareModuleType().create().name("smType_" + i)
|
||||
.description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i);
|
||||
moduleTypeIds.add(softwareModuleTypeManagement.create(smCreate).getId());
|
||||
}
|
||||
|
||||
// verify quota enforcement for optional module types
|
||||
|
||||
final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType()
|
||||
.create().key("testType").name("testType").description("testType").colour("col12"));
|
||||
assertThat(testType.getOptLockRevision()).isEqualTo(1);
|
||||
|
||||
for (int i = 0; i < moduleTypeIds.size() - 1; ++i) {
|
||||
mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/optionalmoduletypes", testType.getId())
|
||||
.content("{\"id\":" + moduleTypeIds.get(i) + "}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/optionalmoduletypes", testType.getId())
|
||||
.content("{\"id\":" + moduleTypeIds.get(moduleTypeIds.size() - 1) + "}")
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
// verify quota enforcement for mandatory module types
|
||||
|
||||
final DistributionSetType testType2 = distributionSetTypeManagement.create(entityFactory.distributionSetType()
|
||||
.create().key("testType2").name("testType2").description("testType2").colour("col12"));
|
||||
assertThat(testType2.getOptLockRevision()).isEqualTo(1);
|
||||
|
||||
for (int i = 0; i < moduleTypeIds.size() - 1; ++i) {
|
||||
mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/mandatorymoduletypes", testType2.getId())
|
||||
.content("{\"id\":" + moduleTypeIds.get(i) + "}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
}
|
||||
|
||||
mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/mandatorymoduletypes", testType2.getId())
|
||||
.content("{\"id\":" + moduleTypeIds.get(moduleTypeIds.size() - 1) + "}")
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUser(principal = "uploadTester", allSpPermissions = true)
|
||||
@Description("Checks the correct behaviour of /rest/v1/distributionsettypes/{ID}/mandatorymoduletypes GET requests.")
|
||||
|
||||
@@ -27,9 +27,11 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||
@@ -131,9 +133,45 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
postRollout("rollout1", 10, dsA.getId(), "id==target*", 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that rollout cannot be created if too many rollout groups are specified.")
|
||||
public void createRolloutWithTooManyRolloutGroups() throws Exception {
|
||||
|
||||
final int maxGroups = quotaManagement.getMaxRolloutGroupsPerRollout();
|
||||
testdataFactory.createTargets(20, "target", "rollout");
|
||||
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout1", "rollout1Desc", maxGroups + 1,
|
||||
testdataFactory.createDistributionSet("ds").getId(), "id==target*",
|
||||
new RolloutGroupConditionBuilder().withDefaults().build()))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that rollout cannot be created if the 'max targets per rollout group' quota would be violated for one of the groups.")
|
||||
public void createRolloutFailsIfRolloutGroupQuotaIsViolated() throws Exception {
|
||||
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerRolloutGroup();
|
||||
testdataFactory.createTargets(maxTargets + 1, "target", "rollout");
|
||||
|
||||
mvc.perform(post("/rest/v1/rollouts")
|
||||
.content(JsonBuilder.rollout("rollout1", "rollout1Desc", 1,
|
||||
testdataFactory.createDistributionSet("ds").getId(), "id==target*",
|
||||
new RolloutGroupConditionBuilder().withDefaults().build()))
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Testing that rollout can be created with groups")
|
||||
public void createRolloutWithGroupsDefinitions() throws Exception {
|
||||
public void createRolloutWithGroupDefinitions() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro");
|
||||
|
||||
final int amountTargets = 10;
|
||||
@@ -160,7 +198,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that no rollout with groups that have illegal percentages can be created")
|
||||
public void createRolloutWithToLowlPercentage() throws Exception {
|
||||
public void createRolloutWithTooLowPercentage() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro2");
|
||||
|
||||
final int amountTargets = 10;
|
||||
@@ -185,7 +223,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
|
||||
@Test
|
||||
@Description("Testing that no rollout with groups that have illegal percentages can be created")
|
||||
public void createRolloutWithToHighPercentage() throws Exception {
|
||||
public void createRolloutWithTooHighPercentage() throws Exception {
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("ro2");
|
||||
|
||||
final int amountTargets = 10;
|
||||
@@ -217,7 +255,7 @@ public class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTes
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Terives sinle rollout from management API includinfg extra data that is delieverd only for single rollout access.")
|
||||
@Description("Retrieves single rollout from management API including extra data that is delivered only for single rollout access.")
|
||||
public void retrieveSingleRollout() throws Exception {
|
||||
testdataFactory.createTargets(20, "rollout", "rollout");
|
||||
final DistributionSet dsA = testdataFactory.createDistributionSet("");
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
@@ -36,6 +37,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.Constants;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.Artifact;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -49,8 +51,10 @@ import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@@ -66,6 +70,7 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
*/
|
||||
@Features("Component Tests - Management API")
|
||||
@Stories("Software Module Resource")
|
||||
@TestPropertySource(properties = { "hawkbit.server.security.dos.maxArtifactSize=100000" })
|
||||
public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
|
||||
@Before
|
||||
@@ -147,7 +152,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests the uppload of an artifact binary. The upload is executed and the content checked in the repository for completenes.")
|
||||
@Description("Tests the upload of an artifact binary. The upload is executed and the content checked in the repository for completeness.")
|
||||
public void uploadArtifact() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
@@ -183,6 +188,24 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
assertArtifact(sm, random);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that artifacts which exceed the configured maximum size cannot be uploaded.")
|
||||
public void uploadArtifactFailsIfTooLarge() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModule("quota", "quota");
|
||||
final long maxSize = quotaManagement.getMaxArtifactSize();
|
||||
|
||||
// create a file which exceeds the configured maximum size
|
||||
final byte[] randomBytes = new byte[Math.toIntExact(maxSize) + 1024];
|
||||
new Random().nextBytes(randomBytes);
|
||||
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename", null, randomBytes);
|
||||
|
||||
// try to upload
|
||||
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
private void assertArtifact(final SoftwareModule sm, final byte[] random) throws IOException {
|
||||
// check result in db...
|
||||
// repo
|
||||
@@ -312,17 +335,57 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies that only a limited number of artifacts can be uploaded for one software module.")
|
||||
public void uploadArtifactsUntilQuotaExceeded() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
final long maxArtifacts = quotaManagement.getMaxArtifactsPerSoftwareModule();
|
||||
|
||||
for (int i = 0; i < maxArtifacts; ++i) {
|
||||
// create test file
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final String md5sum = HashGeneratorUtils.generateMD5(random);
|
||||
final String sha1sum = HashGeneratorUtils.generateSHA1(random);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename" + i, null, random);
|
||||
|
||||
// upload
|
||||
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("$.hashes.md5", equalTo(md5sum)))
|
||||
.andExpect(jsonPath("$.hashes.sha1", equalTo(sha1sum)))
|
||||
.andExpect(jsonPath("$.size", equalTo(random.length)))
|
||||
.andExpect(jsonPath("$.providedFilename", equalTo("origFilename" + i))).andReturn();
|
||||
}
|
||||
|
||||
// upload one more file to cause the quota to be exceeded
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
HashGeneratorUtils.generateMD5(random);
|
||||
HashGeneratorUtils.generateSHA1(random);
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "origFilename_final", null, random);
|
||||
|
||||
// upload
|
||||
mvc.perform(fileUpload("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).file(file)
|
||||
.accept(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath("$.exceptionClass", equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath("$.errorCode", equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests binary download of an artifact including verfication that the downloaded binary is consistent and that the etag header is as expected identical to the SHA1 hash of the file.")
|
||||
public void downloadArtifact() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
|
||||
false);
|
||||
false, artifactSize);
|
||||
final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2",
|
||||
false);
|
||||
false, artifactSize);
|
||||
|
||||
downloadAndVerify(sm, random, artifact);
|
||||
downloadAndVerify(sm, random, artifact2);
|
||||
@@ -348,9 +411,11 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
// prepare data for test
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
|
||||
false);
|
||||
false, artifactSize);
|
||||
|
||||
// perform test
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
|
||||
@@ -373,12 +438,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
public void getArtifacts() throws Exception {
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
|
||||
false);
|
||||
false, artifactSize);
|
||||
final Artifact artifact2 = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2",
|
||||
false);
|
||||
false, artifactSize);
|
||||
|
||||
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts", sm.getId()).accept(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -402,7 +468,9 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
@Test
|
||||
@Description("Verfies that the system refuses unsupported request types and answers as defined to them, e.g. NOT FOUND on a non existing resource. Or a HTTP POST for updating a resource results in METHOD NOT ALLOWED etc.")
|
||||
public void invalidRequestsOnArtifactResource() throws Exception {
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random);
|
||||
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
@@ -415,7 +483,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isNotFound());
|
||||
|
||||
// SM does not exist
|
||||
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", false);
|
||||
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize);
|
||||
mvc.perform(get("/rest/v1/softwaremodules/1234567890/artifacts")).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(status().isNotFound());
|
||||
|
||||
@@ -723,9 +791,10 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", false);
|
||||
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1", false, artifactSize);
|
||||
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).as("Softwaremoudle size is wrong").hasSize(1);
|
||||
assertThat(artifactManagement.count()).isEqualTo(1);
|
||||
@@ -743,11 +812,12 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
public void deleteAssignedSoftwareModule() throws Exception {
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("a");
|
||||
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
final Long appTypeSmId = ds1.findFirstModuleByType(appType).get().getId();
|
||||
|
||||
artifactManagement.create(new ByteArrayInputStream(random), appTypeSmId, "file1", false);
|
||||
artifactManagement.create(new ByteArrayInputStream(random), appTypeSmId, "file1", false, artifactSize);
|
||||
|
||||
assertThat(softwareModuleManagement.count()).isEqualTo(3);
|
||||
assertThat(artifactManagement.count()).isEqualTo(1);
|
||||
@@ -771,12 +841,13 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
// Create 1 SM
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final byte random[] = RandomStringUtils.random(5 * 1024).getBytes();
|
||||
final int artifactSize = 5 * 1024;
|
||||
final byte random[] = RandomStringUtils.random(artifactSize).getBytes();
|
||||
|
||||
// Create 2 artifacts
|
||||
final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file1",
|
||||
false);
|
||||
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2", false);
|
||||
false, artifactSize);
|
||||
artifactManagement.create(new ByteArrayInputStream(random), sm.getId(), "file2", false, artifactSize);
|
||||
|
||||
// check repo before delete
|
||||
assertThat(softwareModuleManagement.findAll(PAGE)).hasSize(1);
|
||||
@@ -797,7 +868,7 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verfies the successfull creation of metadata.")
|
||||
@Description("Verfies the successful creation of metadata and the enforcement of the meta data quota.")
|
||||
public void createMetadata() throws Exception {
|
||||
|
||||
final String knownKey1 = "knownKey1";
|
||||
@@ -807,12 +878,12 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
final JSONArray jsonArray = new JSONArray();
|
||||
jsonArray.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||
jsonArray.put(new JSONObject().put("key", knownKey2).put("value", knownValue2).put("targetVisible", true));
|
||||
final JSONArray metaData1 = new JSONArray();
|
||||
metaData1.put(new JSONObject().put("key", knownKey1).put("value", knownValue1));
|
||||
metaData1.put(new JSONObject().put("key", knownKey2).put("value", knownValue2).put("targetVisible", true));
|
||||
|
||||
mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(jsonArray.toString()))
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData1.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
|
||||
.andExpect(jsonPath("[0]key", equalTo(knownKey1))).andExpect(jsonPath("[0]value", equalTo(knownValue1)))
|
||||
@@ -827,6 +898,25 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
|
||||
assertThat(metaKey1.getValue()).as("Metadata key is wrong").isEqualTo(knownValue1);
|
||||
assertThat(metaKey2.getValue()).as("Metadata key is wrong").isEqualTo(knownValue2);
|
||||
|
||||
// verify quota enforcement
|
||||
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerSoftwareModule();
|
||||
|
||||
final JSONArray metaData2 = new JSONArray();
|
||||
for (int i = 0; i < maxMetaData - metaData1.length() + 1; ++i) {
|
||||
metaData2.put(new JSONObject().put("key", knownKey1 + i).put("value", knownValue1 + i));
|
||||
}
|
||||
|
||||
mvc.perform(post("/rest/v1/softwaremodules/{swId}/metadata", sm.getId()).accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON).content(metaData2.toString()))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden());
|
||||
|
||||
// verify that the number of meta data entries has not changed
|
||||
// (we cannot use the PAGE constant here as it tries to sort by ID)
|
||||
assertThat(softwareModuleManagement
|
||||
.findMetaDataBySoftwareModuleId(new PageRequest(0, Integer.MAX_VALUE), sm.getId()).getTotalElements())
|
||||
.isEqualTo(metaData1.length());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -930,4 +1020,5 @@ public class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegra
|
||||
character++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
||||
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.exception.QuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.rest.exception.MessageNotReadableException;
|
||||
@@ -53,6 +54,8 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
private static final String JSON_PATH_FIELD_SIZE = ".size";
|
||||
private static final String JSON_PATH_FIELD_TOTAL = ".total";
|
||||
private static final String JSON_PATH_FIELD_AUTO_ASSIGN_DS = ".autoAssignDistributionSet";
|
||||
private static final String JSON_PATH_FIELD_EXCEPTION_CLASS = ".exceptionClass";
|
||||
private static final String JSON_PATH_FIELD_ERROR_CODE = ".errorCode";
|
||||
|
||||
// target
|
||||
// $.field
|
||||
@@ -64,6 +67,8 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
private static final String JSON_PATH_ID = JSON_PATH_ROOT + JSON_PATH_FIELD_ID;
|
||||
private static final String JSON_PATH_QUERY = JSON_PATH_ROOT + JSON_PATH_FIELD_QUERY;
|
||||
private static final String JSON_PATH_AUTO_ASSIGN_DS = JSON_PATH_ROOT + JSON_PATH_FIELD_AUTO_ASSIGN_DS;
|
||||
private static final String JSON_PATH_EXCEPTION_CLASS = JSON_PATH_ROOT + JSON_PATH_FIELD_EXCEPTION_CLASS;
|
||||
private static final String JSON_PATH_ERROR_CODE = JSON_PATH_ROOT + JSON_PATH_FIELD_ERROR_CODE;
|
||||
|
||||
@Test
|
||||
@Description("Ensures that deletion is executed if permitted.")
|
||||
@@ -126,8 +131,8 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
final String body = new JSONObject().put("name", filterName2).toString();
|
||||
|
||||
// prepare
|
||||
final TargetFilterQuery tfq = targetFilterQueryManagement.create(
|
||||
entityFactory.targetFilterQuery().create().name(filterName).query(filterQuery));
|
||||
final TargetFilterQuery tfq = targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(filterName).query(filterQuery));
|
||||
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId()).content(body)
|
||||
.contentType(MediaType.APPLICATION_JSON)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
@@ -230,6 +235,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that a single target filter query can be retrieved via its id.")
|
||||
public void getSingleTarget() throws Exception {
|
||||
// create first a target which can be retrieved by rest interface
|
||||
final String knownQuery = "name=test01";
|
||||
@@ -247,6 +253,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the retrieval of a non-existing target filter query results in a HTTP Not found error (404).")
|
||||
public void getSingleTargetNoExistsResponseNotFound() throws Exception {
|
||||
final String targetIdNotExists = "546546";
|
||||
// test
|
||||
@@ -262,6 +269,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the creation of a target filter query based on an invalid request payload results in a HTTP Bad Request error (400).")
|
||||
public void createTargetFilterQueryWithBadPayloadBadRequest() throws Exception {
|
||||
final String notJson = "abc";
|
||||
|
||||
@@ -279,22 +287,72 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
assertThat(exceptionInfo.getErrorCode()).isEqualTo(SpServerError.SP_REST_BODY_NOT_READABLE.getKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the assignment of an auto-assign distribution set results in a HTTP Forbidden error (403) "
|
||||
+ "if the (existing) query addresses too many targets.")
|
||||
public void setAutoAssignDistributionSetOnFilterQueryThatExceedsQuota() throws Exception {
|
||||
|
||||
// create targets
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerAutoAssignment();
|
||||
testdataFactory.createTargets(maxTargets + 1, "target%s");
|
||||
|
||||
// create the filter query and the distribution set
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
final TargetFilterQuery filterQuery = createSingleTargetFilterQuery("1", "controllerId==target*");
|
||||
|
||||
mvc.perform(
|
||||
post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId() + "/autoAssignDS")
|
||||
.content("{\"id\":" + set.getId() + "}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath(JSON_PATH_EXCEPTION_CLASS, equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath(JSON_PATH_ERROR_CODE, equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Ensures that the update of a target filter query results in a HTTP Forbidden error (403) "
|
||||
+ "if the updated query addresses too many targets.")
|
||||
public void updateTargetFilterQueryWithQueryThatExceedsQuota() throws Exception {
|
||||
|
||||
// create targets
|
||||
final int maxTargets = quotaManagement.getMaxTargetsPerAutoAssignment();
|
||||
testdataFactory.createTargets(maxTargets + 1, "target%s");
|
||||
|
||||
// create the filter query and the distribution set
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
final TargetFilterQuery filterQuery = createSingleTargetFilterQuery("1", "controllerId==target1");
|
||||
|
||||
// assign the auto-assign distribution set, this should work
|
||||
mvc.perform(
|
||||
post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId() + "/autoAssignDS")
|
||||
.content("{\"id\":" + set.getId() + "}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
assertThat(targetFilterQueryManagement.get(filterQuery.getId()).get().getAutoAssignDistributionSet())
|
||||
.isEqualTo(set);
|
||||
|
||||
// update the query of the filter query to trigger a quota hit
|
||||
mvc.perform(put(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + filterQuery.getId())
|
||||
.content("{\"query\":\"controllerId==target*\"}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isForbidden())
|
||||
.andExpect(jsonPath(JSON_PATH_EXCEPTION_CLASS, equalTo(QuotaExceededException.class.getName())))
|
||||
.andExpect(jsonPath(JSON_PATH_ERROR_CODE, equalTo(SpServerError.SP_QUOTA_EXCEEDED.getKey())));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setAutoAssignDistributionSetToTargetFilterQuery() throws Exception {
|
||||
|
||||
final String knownQuery = "name=test05";
|
||||
final String knownQuery = "name==test05";
|
||||
final String knownName = "filter05";
|
||||
|
||||
final DistributionSet set = testdataFactory.createDistributionSet("one");
|
||||
final DistributionSet set = testdataFactory.createDistributionSet();
|
||||
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery);
|
||||
|
||||
mvc.perform(post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS")
|
||||
.content("{\"id\":" + set.getId() + "}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk());
|
||||
|
||||
assertThat(
|
||||
targetFilterQueryManagement.get(tfq.getId()).get().getAutoAssignDistributionSet())
|
||||
.isEqualTo(set);
|
||||
assertThat(targetFilterQueryManagement.get(tfq.getId()).get().getAutoAssignDistributionSet()).isEqualTo(set);
|
||||
|
||||
final String hrefPrefix = "http://localhost" + MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/"
|
||||
+ tfq.getId();
|
||||
@@ -311,7 +369,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
@Test
|
||||
public void deleteAutoAssignDistributionSetOfTargetFilterQuery() throws Exception {
|
||||
|
||||
final String knownQuery = "name=test06";
|
||||
final String knownQuery = "name==test06";
|
||||
final String knownName = "filter06";
|
||||
final String dsName = "testDS";
|
||||
|
||||
@@ -319,9 +377,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
final TargetFilterQuery tfq = createSingleTargetFilterQuery(knownName, knownQuery);
|
||||
targetFilterQueryManagement.updateAutoAssignDS(tfq.getId(), set.getId());
|
||||
|
||||
assertThat(
|
||||
targetFilterQueryManagement.get(tfq.getId()).get().getAutoAssignDistributionSet())
|
||||
.isEqualTo(set);
|
||||
assertThat(targetFilterQueryManagement.get(tfq.getId()).get().getAutoAssignDistributionSet()).isEqualTo(set);
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS"))
|
||||
.andExpect(status().isOk()).andExpect(jsonPath(JSON_PATH_NAME, equalTo(dsName)));
|
||||
@@ -329,9 +385,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
mvc.perform(delete(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS"))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
assertThat(
|
||||
targetFilterQueryManagement.get(tfq.getId()).get().getAutoAssignDistributionSet())
|
||||
.isNull();
|
||||
assertThat(targetFilterQueryManagement.get(tfq.getId()).get().getAutoAssignDistributionSet()).isNull();
|
||||
|
||||
mvc.perform(get(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS"))
|
||||
.andExpect(status().isNoContent());
|
||||
@@ -339,8 +393,7 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
|
||||
}
|
||||
|
||||
private TargetFilterQuery createSingleTargetFilterQuery(final String name, final String query) {
|
||||
return targetFilterQueryManagement
|
||||
.create(entityFactory.targetFilterQuery().create().name(name).query(query));
|
||||
return targetFilterQueryManagement.create(entityFactory.targetFilterQuery().create().name(name).query(query));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user