Prioritisation of assignments via mgmt-API (#895)
* Updating the schema for targetfilterquery and rollout * Updating the weight validation logic and tests * Make weight optional * Fix existing multi assignment tests by adding weight, remove weight from TargetFilterQuery * Add weight validation tests, fix tests * Add mgmt api tests for assignment and getting action with weight * Add management layer validation and tests for creating rollouts with weight * Fix amqp test, add repo level validation to resource tests * Add weight to rollout mgmt-api and tests * Add weight to mgmt api target Filter create and update * Add target filter auto assign weight. disable enforcement of setting a weight in multiassign mode * Remove ignored tests, fix api doc * Fix minor findings * Fix findings * Remove hardcoded min weight * Add docu text, fix findings * Fix api documentation * Expose weight via DMF * Expose actions according to weight via ddi * Fix documentation * Add method to get actions ordered by weight to deploymentManagement * Updating the schema for targetfilterquery and rollout * Updated the indentation * Updated the helper class, fixed the randomUID in test factory * Updated the class name with prefix JPA * Adding the missing License for WeightValidationHelper class * Adding documentation to the dmf api on weight * Removed the merger markers * Updated the class name * Removed the redundant method * Addressed final PR comments * Updated the missing testcase with latest default weight value * Reverting the default value of weight back to 1000 and updated tests Signed-off-by: Shruthi Manavalli Ramanna <shruthimanavalli.ramanna@bosch-si.com> Signed-off-by: Stefan Klotz <stefan.klotz@bosch-si.com>
This commit is contained in:
committed by
Stefan Behl
parent
09f2d8a481
commit
9cb5d31396
@@ -25,11 +25,13 @@ import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.hawkbit.ddi.rest.resource.DdiApiConfiguration;
|
||||
import org.eclipse.hawkbit.mgmt.rest.resource.MgmtApiConfiguration;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.jpa.RepositoryApplicationConfiguration;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ArtifactUpload;
|
||||
import org.eclipse.hawkbit.repository.model.DeploymentRequestBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
@@ -37,6 +39,7 @@ import org.eclipse.hawkbit.repository.test.TestConfiguration;
|
||||
import org.eclipse.hawkbit.rest.AbstractRestIntegrationTest;
|
||||
import org.eclipse.hawkbit.rest.RestConfiguration;
|
||||
import org.eclipse.hawkbit.rest.util.FilterHttpResponse;
|
||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -98,8 +101,13 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
||||
}
|
||||
|
||||
public static MyFieldFieldDesc requestFieldWithPath(final String path, final boolean mandatory) {
|
||||
return requestFieldWithPath(path, mandatory, mandatory ? "X" : "");
|
||||
}
|
||||
|
||||
private static MyFieldFieldDesc requestFieldWithPath(final String path, final boolean mandatory,
|
||||
final String mandatoryMessage) {
|
||||
final MyFieldFieldDesc myFieldDesc = new MyFieldFieldDesc(path);
|
||||
myFieldDesc.attributes(key("mandatory").value(mandatory ? "X" : ""));
|
||||
myFieldDesc.attributes(key("mandatory").value(mandatoryMessage));
|
||||
// defaults
|
||||
myFieldDesc.attributes(key("value").value(""));
|
||||
|
||||
@@ -118,6 +126,10 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
||||
return requestFieldWithPath(path, false);
|
||||
}
|
||||
|
||||
public static MyFieldFieldDesc requestFieldWithPathMandatoryInMultiAssignMode(final String path) {
|
||||
return requestFieldWithPath(path, false, "when multi-assignment is enabled");
|
||||
}
|
||||
|
||||
public static class MyFieldFieldDesc extends SubsectionDescriptor {
|
||||
|
||||
/**
|
||||
@@ -154,11 +166,17 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
||||
final Target savedTarget = targetManagement.create(entityFactory.target().create().controllerId(name)
|
||||
.status(TargetUpdateStatus.UNKNOWN).address("http://192.168.0.1").description("My name is " + name)
|
||||
.lastTargetQuery(System.currentTimeMillis()));
|
||||
|
||||
final List<Target> updatedTargets = maintenanceWindowSchedule == null
|
||||
? assignWithoutMaintenanceWindow(distributionSet, savedTarget, timeforced)
|
||||
: assignWithMaintenanceWindow(distributionSet, savedTarget, timeforced, maintenanceWindowSchedule,
|
||||
maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
final DeploymentRequestBuilder deploymentRequestBuilder = DeploymentManagement
|
||||
.deploymentRequest(savedTarget.getControllerId(), distributionSet.getId())
|
||||
.setMaintenance(maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
if (timeforced) {
|
||||
deploymentRequestBuilder.setActionType(ActionType.TIMEFORCED);
|
||||
}
|
||||
if (isMultiAssignmentsEnabled()) {
|
||||
deploymentRequestBuilder.setWeight(600);
|
||||
}
|
||||
final List<Target> updatedTargets = makeAssignment(deploymentRequestBuilder.build()).getAssignedEntity()
|
||||
.stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
|
||||
if (inSync) {
|
||||
feedbackToByInSync(distributionSet);
|
||||
@@ -167,28 +185,6 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
||||
return updatedTargets.get(0);
|
||||
}
|
||||
|
||||
private List<Target> assignWithoutMaintenanceWindow(final DistributionSet distributionSet, final Target savedTarget,
|
||||
final boolean timeforced) {
|
||||
final List<Action> actions = timeforced
|
||||
? assignDistributionSet(distributionSet.getId(), savedTarget.getControllerId(), ActionType.TIMEFORCED)
|
||||
.getAssignedEntity()
|
||||
: assignDistributionSet(distributionSet, savedTarget).getAssignedEntity();
|
||||
return actions.stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<Target> assignWithMaintenanceWindow(final DistributionSet distributionSet, final Target savedTarget,
|
||||
final boolean timeforced, final String maintenanceWindowSchedule, final String maintenanceWindowDuration,
|
||||
final String maintenanceWindowTimeZone) {
|
||||
final List<Action> actions = timeforced
|
||||
? assignDistributionSetWithMaintenanceWindow(distributionSet.getId(), savedTarget.getControllerId(),
|
||||
ActionType.TIMEFORCED, maintenanceWindowSchedule, maintenanceWindowDuration,
|
||||
maintenanceWindowTimeZone).getAssignedEntity()
|
||||
: assignDistributionSetWithMaintenanceWindow(distributionSet.getId(), savedTarget.getControllerId(),
|
||||
maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone)
|
||||
.getAssignedEntity();
|
||||
return actions.stream().map(Action::getTarget).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
protected DistributionSet createDistributionSet() {
|
||||
DistributionSet distributionSet = testdataFactory.createDistributionSet("");
|
||||
distributionSet = distributionSetManagement.update(entityFactory.distributionSet()
|
||||
@@ -314,4 +310,9 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
||||
parameterWithName("q").description(ApiModelPropertiesGeneric.FIQL));
|
||||
}
|
||||
|
||||
protected boolean isMultiAssignmentsEnabled() {
|
||||
return Boolean.TRUE.equals(tenantConfigurationManagement
|
||||
.getConfigurationValue(TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED, Boolean.class).getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -109,6 +109,8 @@ public final class MgmtApiModelProperties {
|
||||
public static final String ROLLOUT_LINKS_GROUPS = "Link to retrieve the groups a rollout";
|
||||
public static final String ROLLOUT_START_ASYNC = "Start the rollout asynchronous";
|
||||
|
||||
public static final String RESULTING_ACTIONS_WEIGHT = "Weight of the resulting Actions";
|
||||
|
||||
public static final String UPDATE_STATUS = "Current update status of the target.";
|
||||
public static final String TARGET_ATTRIBUTES = "Target attributes.";
|
||||
|
||||
@@ -138,6 +140,8 @@ public final class MgmtApiModelProperties {
|
||||
|
||||
public static final String ACTION_LIST = "List of actions.";
|
||||
|
||||
public static final String ACTION_WEIGHT = "Weight of the action showing the importance of the update.";
|
||||
|
||||
public static final String IP_ADDRESS = "Last known IP address of the target. Only presented if IP address of the target itself is known (connected directly through DDI API).";
|
||||
|
||||
public static final String ADDRESS = "The last known address URI of the target. Includes information of the target is connected either directly (DDI) through HTTP or indirectly (DMF) through amqp.";
|
||||
@@ -188,6 +192,7 @@ public final class MgmtApiModelProperties {
|
||||
// request parameter
|
||||
public static final String FORCETIME = "Forcetime in milliseconds.";
|
||||
public static final String FORCE = "Force as boolean.";
|
||||
public static final String ASSIGNMENT_WEIGHT = "Importance of the assignment.";
|
||||
public static final String ASSIGNMENT_TYPE = "The type of the assignment.";
|
||||
public static final String TARGET_ASSIGNED = "The number of targets that have been assigned as part of this operation.";
|
||||
public static final String TARGET_ASSIGNED_ALREADY = "The number of targets which already had been the assignment.";
|
||||
|
||||
@@ -385,6 +385,9 @@ public class DistributionSetsDocumentationTest extends AbstractApiRestDocumentat
|
||||
.description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()),
|
||||
requestFields(
|
||||
requestFieldWithPath("[].id").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||
requestFieldWithPathMandatoryInMultiAssignMode("[].weight")
|
||||
.description(MgmtApiModelProperties.ASSIGNMENT_WEIGHT)
|
||||
.type(JsonFieldType.NUMBER).attributes(key("value").value("0 - 1000")),
|
||||
optionalRequestFieldWithPath("[].forcetime")
|
||||
.description(MgmtApiModelProperties.FORCETIME),
|
||||
optionalRequestFieldWithPath("[].maintenanceWindow")
|
||||
|
||||
@@ -23,10 +23,9 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorAction;
|
||||
@@ -52,6 +51,8 @@ import org.springframework.restdocs.payload.FieldDescriptor;
|
||||
import org.springframework.restdocs.payload.JsonFieldType;
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
@@ -80,7 +81,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
@Description("Handles the GET request of retrieving all rollouts. Required Permission: "
|
||||
+ SpPermission.READ_ROLLOUT)
|
||||
public void getRollouts() throws Exception {
|
||||
|
||||
enableMultiAssignments();
|
||||
createRolloutEntity();
|
||||
|
||||
mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING).accept(MediaTypes.HAL_JSON_VALUE))
|
||||
@@ -113,6 +114,8 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "id").description(ApiModelPropertiesGeneric.ITEM_ID));
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "name").description(ApiModelPropertiesGeneric.NAME));
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "weight")
|
||||
.description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT).type(JsonFieldType.NUMBER).optional());
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "deleted").description(ApiModelPropertiesGeneric.DELETED));
|
||||
allFieldDescriptor
|
||||
.add(fieldWithPath(arrayPrefix + "description").description(ApiModelPropertiesGeneric.DESCRPTION));
|
||||
@@ -159,7 +162,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
@Description("Handles the GET request of retrieving a single rollout. Required Permission: "
|
||||
+ SpPermission.READ_ROLLOUT)
|
||||
public void getRollout() throws Exception {
|
||||
|
||||
enableMultiAssignments();
|
||||
final Rollout rollout = createRolloutEntity();
|
||||
|
||||
mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}", rollout.getId())
|
||||
@@ -195,47 +198,47 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
.contentType(MediaTypes.HAL_JSON_UTF8).accept(MediaTypes.HAL_JSON_VALUE))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON_UTF8))
|
||||
.andDo(this.document.document(
|
||||
requestFields(requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
||||
optionalRequestFieldWithPath("type").description(
|
||||
MgmtApiModelProperties.ROLLOUT_TYPE).attributes(
|
||||
key("value").value("['soft', 'forced', 'timeforced', 'downloadonly']")),
|
||||
requestFieldWithPath("distributionSetId")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_DS_ID),
|
||||
requestFieldWithPath("targetFilterQuery")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY),
|
||||
requestFieldWithPath("amountGroups")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_AMOUNT_GROUPS),
|
||||
optionalRequestFieldWithPath("description")
|
||||
.description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||
optionalRequestFieldWithPath("successCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
|
||||
optionalRequestFieldWithPath("successCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("successCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("successAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION),
|
||||
optionalRequestFieldWithPath("successAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)
|
||||
.attributes(key("value").value("['nextgroup']")),
|
||||
optionalRequestFieldWithPath("successAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP),
|
||||
optionalRequestFieldWithPath("errorCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION),
|
||||
optionalRequestFieldWithPath("errorCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("errorCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("errorAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION),
|
||||
optionalRequestFieldWithPath("errorAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)
|
||||
.attributes(key("value").value("['pause']")),
|
||||
optionalRequestFieldWithPath("errorAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)),
|
||||
.andDo(this.document.document(requestFields(
|
||||
requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
||||
requestFieldWithPathMandatoryInMultiAssignMode("weight").type(JsonFieldType.NUMBER)
|
||||
.description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT)
|
||||
.attributes(key("value").value("0 - 1000")),
|
||||
requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
||||
optionalRequestFieldWithPath("type").description(MgmtApiModelProperties.ROLLOUT_TYPE)
|
||||
.attributes(key("value").value("['soft', 'forced', 'timeforced', 'downloadonly']")),
|
||||
requestFieldWithPath("distributionSetId").description(MgmtApiModelProperties.ROLLOUT_DS_ID),
|
||||
requestFieldWithPath("targetFilterQuery")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY),
|
||||
requestFieldWithPath("amountGroups").description(MgmtApiModelProperties.ROLLOUT_AMOUNT_GROUPS),
|
||||
optionalRequestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||
optionalRequestFieldWithPath("successCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
|
||||
optionalRequestFieldWithPath("successCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("successCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("successAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION),
|
||||
optionalRequestFieldWithPath("successAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)
|
||||
.attributes(key("value").value("['nextgroup']")),
|
||||
optionalRequestFieldWithPath("successAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP),
|
||||
optionalRequestFieldWithPath("errorCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION),
|
||||
optionalRequestFieldWithPath("errorCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("errorCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("errorAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION),
|
||||
optionalRequestFieldWithPath("errorAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)
|
||||
.attributes(key("value").value("['pause']")),
|
||||
optionalRequestFieldWithPath("errorAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)),
|
||||
|
||||
getRolloutResponseFields(false, true)));
|
||||
|
||||
@@ -283,77 +286,83 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
.contentType(MediaType.APPLICATION_JSON).accept(MediaTypes.HAL_JSON_VALUE))
|
||||
.andDo(MockMvcResultPrinter.print()).andExpect(status().isCreated())
|
||||
.andExpect(content().contentType(MediaTypes.HAL_JSON_UTF8))
|
||||
.andDo(this.document.document(requestFields(
|
||||
requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
||||
requestFieldWithPath("distributionSetId").description(MgmtApiModelProperties.ROLLOUT_DS_ID),
|
||||
requestFieldWithPath("targetFilterQuery")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY),
|
||||
optionalRequestFieldWithPath("description").description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||
optionalRequestFieldWithPath("successCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
|
||||
optionalRequestFieldWithPath("successCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("successCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("successAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION),
|
||||
optionalRequestFieldWithPath("successAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)
|
||||
.attributes(key("value").value("['nextgroup']")),
|
||||
optionalRequestFieldWithPath("successAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP),
|
||||
optionalRequestFieldWithPath("errorCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION),
|
||||
optionalRequestFieldWithPath("errorCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("errorCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("errorAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION),
|
||||
optionalRequestFieldWithPath("errorAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)
|
||||
.attributes(key("value").value("['pause']")),
|
||||
optionalRequestFieldWithPath("errorAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP),
|
||||
|
||||
requestFieldWithPath("groups").description(MgmtApiModelProperties.ROLLOUT_GROUPS),
|
||||
requestFieldWithPath("groups[].name").description(ApiModelPropertiesGeneric.NAME),
|
||||
requestFieldWithPath("groups[].description").description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||
optionalRequestFieldWithPath("groups[].targetFilterQuery")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_GROUP_FILTER_QUERY),
|
||||
optionalRequestFieldWithPath("groups[].targetPercentage")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_GROUP_TARGET_PERCENTAGE)
|
||||
.attributes(key("value").value("0..100")),
|
||||
optionalRequestFieldWithPath("groups[].successCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
|
||||
optionalRequestFieldWithPath("groups[].successCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("groups[].successCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("groups[].successAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION),
|
||||
optionalRequestFieldWithPath("groups[].successAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)
|
||||
.attributes(key("value").value("['nextgroup']")),
|
||||
optionalRequestFieldWithPath("groups[].successAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP),
|
||||
optionalRequestFieldWithPath("groups[].errorCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION),
|
||||
optionalRequestFieldWithPath("groups[].errorCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("groups[].errorCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("groups[].errorAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION),
|
||||
optionalRequestFieldWithPath("groups[].errorAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)
|
||||
.attributes(key("value").value("['pause']")),
|
||||
optionalRequestFieldWithPath("groups[].errorAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)),
|
||||
.andDo(this.document.document(
|
||||
requestFields(requestFieldWithPath("name").description(ApiModelPropertiesGeneric.NAME),
|
||||
requestFieldWithPathMandatoryInMultiAssignMode("weight")
|
||||
.type(JsonFieldType.NUMBER)
|
||||
.description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT)
|
||||
.attributes(key("value").value("0 - 1000")),
|
||||
requestFieldWithPath("distributionSetId")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_DS_ID),
|
||||
requestFieldWithPath("targetFilterQuery")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_FILTER_QUERY),
|
||||
optionalRequestFieldWithPath("description")
|
||||
.description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||
optionalRequestFieldWithPath("successCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
|
||||
optionalRequestFieldWithPath("successCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("successCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("successAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION),
|
||||
optionalRequestFieldWithPath("successAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)
|
||||
.attributes(key("value").value("['nextgroup']")),
|
||||
optionalRequestFieldWithPath("successAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP),
|
||||
optionalRequestFieldWithPath("errorCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION),
|
||||
optionalRequestFieldWithPath("errorCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("errorCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("errorAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION),
|
||||
optionalRequestFieldWithPath("errorAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)
|
||||
.attributes(key("value").value("['pause']")),
|
||||
optionalRequestFieldWithPath("errorAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP),
|
||||
requestFieldWithPath("groups").description(MgmtApiModelProperties.ROLLOUT_GROUPS),
|
||||
requestFieldWithPath("groups[].name").description(ApiModelPropertiesGeneric.NAME),
|
||||
requestFieldWithPath("groups[].description")
|
||||
.description(ApiModelPropertiesGeneric.DESCRPTION),
|
||||
optionalRequestFieldWithPath("groups[].targetFilterQuery")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_GROUP_FILTER_QUERY),
|
||||
optionalRequestFieldWithPath("groups[].targetPercentage")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_GROUP_TARGET_PERCENTAGE)
|
||||
.attributes(key("value").value("0..100")),
|
||||
optionalRequestFieldWithPath("groups[].successCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION),
|
||||
optionalRequestFieldWithPath("groups[].successCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("groups[].successCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("groups[].successAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION),
|
||||
optionalRequestFieldWithPath("groups[].successAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_ACTION)
|
||||
.attributes(key("value").value("['nextgroup']")),
|
||||
optionalRequestFieldWithPath("groups[].successAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_SUCCESS_ACTION_EXP),
|
||||
optionalRequestFieldWithPath("groups[].errorCondition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION),
|
||||
optionalRequestFieldWithPath("groups[].errorCondition.condition")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_CONDITION)
|
||||
.attributes(key("value").value("['threshold']")),
|
||||
optionalRequestFieldWithPath("groups[].errorCondition.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_CONDITION_EXP),
|
||||
optionalRequestFieldWithPath("groups[].errorAction")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION),
|
||||
optionalRequestFieldWithPath("groups[].errorAction.action")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_ACTION)
|
||||
.attributes(key("value").value("['pause']")),
|
||||
optionalRequestFieldWithPath("groups[].errorAction.expression")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)),
|
||||
getRolloutResponseFields(false, true)));
|
||||
}
|
||||
|
||||
@@ -626,11 +635,13 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
|
||||
private Rollout createRolloutEntity() {
|
||||
testdataFactory.createTargets(20, "exampleTarget");
|
||||
final Rollout rollout = rolloutManagement.create(
|
||||
entityFactory.rollout().create().name("exampleRollout")
|
||||
.targetFilterQuery("controllerId==exampleTarget*").set(testdataFactory.createDistributionSet()),
|
||||
10, new RolloutGroupConditionBuilder().withDefaults()
|
||||
.successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build());
|
||||
final RolloutCreate rolloutCreate = entityFactory.rollout().create().name("exampleRollout")
|
||||
.targetFilterQuery("controllerId==exampleTarget*").set(testdataFactory.createDistributionSet());
|
||||
if (isMultiAssignmentsEnabled()) {
|
||||
rolloutCreate.weight(400);
|
||||
}
|
||||
final Rollout rollout = rolloutManagement.create(rolloutCreate, 10, new RolloutGroupConditionBuilder()
|
||||
.withDefaults().successCondition(RolloutGroupSuccessCondition.THRESHOLD, "10").build());
|
||||
|
||||
// Run here, because Scheduler is disabled during tests
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation;
|
||||
import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric;
|
||||
import org.eclipse.hawkbit.rest.documentation.MgmtApiModelProperties;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -183,15 +184,16 @@ public class TargetFilterQueriesResourceDocumentationTest extends AbstractApiRes
|
||||
@Test
|
||||
@Description("Handles the POST request of setting a distribution set for auto assignment within SP. Required Permission: CREATE_TARGET.")
|
||||
public void postAutoAssignDS() throws Exception {
|
||||
enableMultiAssignments();
|
||||
final TargetFilterQuery tfq = createTargetFilterQuery();
|
||||
final DistributionSet distributionSet = createDistributionSet();
|
||||
final String filterByDistSet = "{\"id\":\"" + distributionSet.getId() + "\", \"type\":\""
|
||||
+ MgmtActionType.SOFT.getName() + "\"}";
|
||||
final String autoAssignBody = new JSONObject().put("id", distributionSet.getId())
|
||||
.put("type", MgmtActionType.SOFT.getName()).put("weight", 200).toString();
|
||||
|
||||
this.mockMvc
|
||||
.perform(
|
||||
post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/{targetFilterQueryId}/autoAssignDS",
|
||||
tfq.getId()).contentType(MediaType.APPLICATION_JSON).content(filterByDistSet))
|
||||
tfq.getId()).contentType(MediaType.APPLICATION_JSON).content(autoAssignBody.toString()))
|
||||
.andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||
.andDo(this.document.document(
|
||||
pathParameters(parameterWithName("targetFilterQueryId")
|
||||
@@ -199,7 +201,10 @@ public class TargetFilterQueriesResourceDocumentationTest extends AbstractApiRes
|
||||
requestFields(requestFieldWithPath("id").description(MgmtApiModelProperties.DS_ID),
|
||||
optionalRequestFieldWithPath("type")
|
||||
.description(MgmtApiModelProperties.ACTION_FORCE_TYPE)
|
||||
.attributes(key("value").value("['forced', 'soft', 'downloadonly']"))),
|
||||
.attributes(key("value").value("['forced', 'soft', 'downloadonly']")),
|
||||
requestFieldWithPathMandatoryInMultiAssignMode("weight")
|
||||
.description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT)
|
||||
.attributes(key("value").value("0 - 1000"))),
|
||||
getResponseFieldTargetFilterQuery(false)));
|
||||
}
|
||||
|
||||
@@ -227,6 +232,9 @@ public class TargetFilterQueriesResourceDocumentationTest extends AbstractApiRes
|
||||
fieldWithPath(arrayPrefix + "autoAssignActionType")
|
||||
.description(MgmtApiModelProperties.ACTION_FORCE_TYPE).type(JsonFieldType.STRING.toString())
|
||||
.attributes(key("value").value("['forced', 'soft', 'downloadonly']")),
|
||||
fieldWithPath(arrayPrefix + "autoAssignWeight")
|
||||
.description(MgmtApiModelProperties.RESULTING_ACTIONS_WEIGHT)
|
||||
.type(JsonFieldType.NUMBER.toString()),
|
||||
fieldWithPath(arrayPrefix + "createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
||||
fieldWithPath(arrayPrefix + "createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
||||
fieldWithPath(arrayPrefix + "lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT),
|
||||
@@ -235,7 +243,8 @@ public class TargetFilterQueriesResourceDocumentationTest extends AbstractApiRes
|
||||
.description(MgmtApiModelProperties.TARGET_FILTER_QUERY_LINK_AUTO_ASSIGN_DS));
|
||||
}
|
||||
|
||||
private String createTargetFilterQueryJson(final String name, final String query) throws JsonProcessingException {
|
||||
private String createTargetFilterQueryJson(final String name, final String query)
|
||||
throws JsonProcessingException {
|
||||
final Map<String, Object> target = new HashMap<>();
|
||||
target.put("name", name);
|
||||
target.put("query", query);
|
||||
@@ -249,6 +258,7 @@ public class TargetFilterQueriesResourceDocumentationTest extends AbstractApiRes
|
||||
|
||||
private TargetFilterQuery createTargetFilterQueryWithDS(final DistributionSet distributionSet) {
|
||||
final TargetFilterQuery targetFilterQuery = createTargetFilterQuery();
|
||||
return targetFilterQueryManagement.updateAutoAssignDS(targetFilterQuery.getId(), distributionSet.getId());
|
||||
return targetFilterQueryManagement.updateAutoAssignDS(entityFactory.targetFilterQuery()
|
||||
.updateAutoAssign(targetFilterQuery.getId()).ds(distributionSet.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
@Test
|
||||
@Description("Handles the GET request of retrieving the full action history of a specific target. Required Permission: READ_TARGET.")
|
||||
public void getActionsFromTarget() throws Exception {
|
||||
enableMultiAssignments();
|
||||
generateActionForTarget(targetId);
|
||||
|
||||
mockMvc.perform(
|
||||
@@ -229,12 +230,14 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
.description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS)
|
||||
.attributes(key("value").value("['finished', 'pending']")),
|
||||
fieldWithPath("content[]._links").description(MgmtApiModelProperties.LINK_TO_ACTION),
|
||||
fieldWithPath("content[].id").description(MgmtApiModelProperties.ACTION_ID))));
|
||||
fieldWithPath("content[].id").description(MgmtApiModelProperties.ACTION_ID),
|
||||
fieldWithPath("content[].weight").description(MgmtApiModelProperties.ACTION_WEIGHT))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Handles the GET request of retrieving the full action history of a specific target with maintenance window. Required Permission: READ_TARGET.")
|
||||
public void getActionsFromTargetWithMaintenanceWindow() throws Exception {
|
||||
enableMultiAssignments();
|
||||
generateActionForTarget(targetId, true, false, getTestSchedule(2), getTestDuration(1), getTestTimeZone());
|
||||
|
||||
mockMvc.perform(
|
||||
@@ -262,6 +265,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
.attributes(key("value").value("['finished', 'pending']")),
|
||||
fieldWithPath("content[]._links").description(MgmtApiModelProperties.LINK_TO_ACTION),
|
||||
fieldWithPath("content[].id").description(MgmtApiModelProperties.ACTION_ID),
|
||||
fieldWithPath("content[].weight").description(MgmtApiModelProperties.ACTION_WEIGHT),
|
||||
fieldWithPath("content[].maintenanceWindow")
|
||||
.description(MgmtApiModelProperties.MAINTENANCE_WINDOW),
|
||||
fieldWithPath("content[].maintenanceWindow.schedule")
|
||||
@@ -317,6 +321,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
@Test
|
||||
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
||||
public void getActionFromTarget() throws Exception {
|
||||
enableMultiAssignments();
|
||||
final Action action = generateActionForTarget(targetId, true, true);
|
||||
assertThat(deploymentManagement.findAction(action.getId()).get().getActionType())
|
||||
.isEqualTo(ActionType.TIMEFORCED);
|
||||
@@ -330,6 +335,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
||||
fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
||||
fieldWithPath("id").description(MgmtApiModelProperties.ACTION_ID),
|
||||
fieldWithPath("weight").description(MgmtApiModelProperties.ACTION_WEIGHT),
|
||||
fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY)
|
||||
.type("String"),
|
||||
fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT)
|
||||
@@ -351,6 +357,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
@Test
|
||||
@Description("Handles the GET request of retrieving a specific action on a specific target. Required Permission: READ_TARGET.")
|
||||
public void getActionFromTargetWithMaintenanceWindow() throws Exception {
|
||||
enableMultiAssignments();
|
||||
final Action action = generateActionForTarget(targetId, true, true, getTestSchedule(2), getTestDuration(1),
|
||||
getTestTimeZone());
|
||||
|
||||
@@ -363,6 +370,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
responseFields(fieldWithPath("createdBy").description(ApiModelPropertiesGeneric.CREATED_BY),
|
||||
fieldWithPath("createdAt").description(ApiModelPropertiesGeneric.CREATED_AT),
|
||||
fieldWithPath("id").description(MgmtApiModelProperties.ACTION_ID),
|
||||
fieldWithPath("weight").description(MgmtApiModelProperties.ACTION_WEIGHT),
|
||||
fieldWithPath("lastModifiedBy").description(ApiModelPropertiesGeneric.LAST_MODIFIED_BY)
|
||||
.type("String"),
|
||||
fieldWithPath("lastModifiedAt").description(ApiModelPropertiesGeneric.LAST_MODIFIED_AT)
|
||||
@@ -514,6 +522,9 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
.description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()),
|
||||
requestFields(
|
||||
requestFieldWithPath("id").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||
requestFieldWithPathMandatoryInMultiAssignMode("weight")
|
||||
.description(MgmtApiModelProperties.ASSIGNMENT_WEIGHT)
|
||||
.type(JsonFieldType.NUMBER).attributes(key("value").value("0 - 1000")),
|
||||
optionalRequestFieldWithPath("forcetime").description(MgmtApiModelProperties.FORCETIME),
|
||||
optionalRequestFieldWithPath("maintenanceWindow")
|
||||
.description(MgmtApiModelProperties.MAINTENANCE_WINDOW),
|
||||
@@ -537,12 +548,12 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
|
||||
final long forceTime = System.currentTimeMillis();
|
||||
final JSONArray body = new JSONArray();
|
||||
body.put(new JSONObject().put("id", sets.get(1).getId()).put("type", "timeforced")
|
||||
body.put(new JSONObject().put("id", sets.get(1).getId()).put("weight", 500).put("type", "timeforced")
|
||||
.put("forcetime", forceTime)
|
||||
.put("maintenanceWindow", new JSONObject().put("schedule", getTestSchedule(100))
|
||||
.put("duration", getTestDuration(10)).put("timezone", getTestTimeZone())))
|
||||
.toString();
|
||||
body.put(new JSONObject().put("id", sets.get(0).getId()).put("type", "forced"));
|
||||
body.put(new JSONObject().put("id", sets.get(0).getId()).put("type", "forced").put("weight", 800));
|
||||
|
||||
enableMultiAssignments();
|
||||
mockMvc.perform(post(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/"
|
||||
@@ -555,6 +566,9 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
.description(MgmtApiModelProperties.OFFLINE_UPDATE).optional()),
|
||||
requestFields(
|
||||
requestFieldWithPath("[].id").description(ApiModelPropertiesGeneric.ITEM_ID),
|
||||
requestFieldWithPathMandatoryInMultiAssignMode("[].weight")
|
||||
.description(MgmtApiModelProperties.ASSIGNMENT_WEIGHT)
|
||||
.attributes(key("value").value("0 - 1000")),
|
||||
optionalRequestFieldWithPath("[].forcetime")
|
||||
.description(MgmtApiModelProperties.FORCETIME),
|
||||
optionalRequestFieldWithPath("[].maintenanceWindow")
|
||||
|
||||
Reference in New Issue
Block a user