ManagementApi: Action does not have property containing rollout name (#1116)
* Mgmt Rest API: Enhance Action payload with rollout properties Signed-off-by: Stefan Behl <stefan.behl@bosch.io> * Enhance Mgmt REST API docs Signed-off-by: Stefan Behl <stefan.behl@bosch.io> * Minor changes Signed-off-by: Stefan Behl <stefan.behl@bosch.io>
This commit is contained in:
@@ -65,6 +65,12 @@ public class MgmtAction extends MgmtBaseEntity {
|
||||
|
||||
@JsonProperty
|
||||
private MgmtMaintenanceWindow maintenanceWindow;
|
||||
|
||||
@JsonProperty
|
||||
private Long rollout;
|
||||
|
||||
@JsonProperty
|
||||
private String rolloutName;
|
||||
|
||||
public MgmtMaintenanceWindow getMaintenanceWindow() {
|
||||
return maintenanceWindow;
|
||||
@@ -121,4 +127,21 @@ public class MgmtAction extends MgmtBaseEntity {
|
||||
public void setType(final String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Long getRollout() {
|
||||
return rollout;
|
||||
}
|
||||
|
||||
public void setRollout(Long rollout) {
|
||||
this.rollout = rollout;
|
||||
}
|
||||
|
||||
public String getRolloutName() {
|
||||
return rolloutName;
|
||||
}
|
||||
|
||||
public void setRolloutName(String rolloutName) {
|
||||
this.rolloutName = rolloutName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -84,6 +84,10 @@ public final class MgmtRestConstants {
|
||||
* The target URL mapping, href link for canceled actions.
|
||||
*/
|
||||
public static final String TARGET_V1_ACTION_STATUS = "status";
|
||||
/**
|
||||
* The target URL mapping, href link for a rollout.
|
||||
*/
|
||||
public static final String TARGET_V1_ROLLOUT = "rollout";
|
||||
|
||||
/**
|
||||
* The target URL mapping rest resource.
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
|
||||
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRolloutRestApi;
|
||||
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi;
|
||||
import org.eclipse.hawkbit.repository.ActionFields;
|
||||
import org.eclipse.hawkbit.repository.ActionStatusFields;
|
||||
@@ -39,6 +40,7 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.PollStatus;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||
import org.eclipse.hawkbit.rest.data.ResponseList;
|
||||
@@ -215,6 +217,12 @@ public final class MgmtTargetMapper {
|
||||
result.setStatus(MgmtAction.ACTION_FINISHED);
|
||||
}
|
||||
|
||||
Rollout rollout = action.getRollout();
|
||||
if (rollout != null) {
|
||||
result.setRollout(rollout.getId());
|
||||
result.setRolloutName(rollout.getName());
|
||||
}
|
||||
|
||||
if (action.hasMaintenanceSchedule()) {
|
||||
final MgmtMaintenanceWindow maintenanceWindow = new MgmtMaintenanceWindow();
|
||||
maintenanceWindow.setSchedule(action.getMaintenanceWindowSchedule());
|
||||
@@ -248,6 +256,12 @@ public final class MgmtTargetMapper {
|
||||
ActionStatusFields.ID.getFieldName() + ":" + SortDirection.DESC))
|
||||
.withRel(MgmtRestConstants.TARGET_V1_ACTION_STATUS));
|
||||
|
||||
final Rollout rollout = action.getRollout();
|
||||
if (rollout != null) {
|
||||
result.add(linkTo(methodOn(MgmtRolloutRestApi.class).getRollout(rollout.getId()))
|
||||
.withRel(MgmtRestConstants.TARGET_V1_ROLLOUT));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ package org.eclipse.hawkbit.mgmt.rest.resource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
@@ -51,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetMetadata;
|
||||
@@ -2039,5 +2041,38 @@ public class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("An action provides information of the rollout it was created for (if any).")
|
||||
public void getActionWithRolloutInfo() throws Exception {
|
||||
|
||||
// setup
|
||||
final int amountTargets = 10;
|
||||
final List<Target> targets = testdataFactory.createTargets(amountTargets, "trg", "trg");
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("");
|
||||
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("My Rollout", "My Rollout Description", 1,
|
||||
"name==trg*", ds, "50", "5");
|
||||
rolloutManagement.start(rollout.getId());
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
// get all actions for the first target
|
||||
final Target target = targets.get(0);
|
||||
mvc.perform(get("/rest/v1/targets/{targetId}/actions", target.getControllerId())).andExpect(status().isOk())
|
||||
.andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(jsonPath("content.[0].rollout", equalTo(rollout.getId().intValue())))
|
||||
.andExpect(jsonPath("content.[0].rolloutName", equalTo(rollout.getName())));
|
||||
|
||||
// get the first action for the first target;
|
||||
// verify that also the rollout link is present
|
||||
final Slice<Action> action = deploymentManagement.findActionsByTarget(target.getControllerId(),
|
||||
PageRequest.of(0, 100));
|
||||
assertThat(action.getContent()).hasSize(1);
|
||||
mvc.perform(get("/rest/v1/targets/{targetId}/actions/{actionId}", target.getControllerId(),
|
||||
action.getContent().get(0).getId())).andExpect(status().isOk()).andDo(MockMvcResultPrinter.print())
|
||||
.andExpect(jsonPath("$.rollout", equalTo(rollout.getId().intValue())))
|
||||
.andExpect(jsonPath("$.rolloutName", equalTo(rollout.getName()))).andExpect(jsonPath(
|
||||
"$._links.rollout.href", containsString("/rest/v1/rollouts/" + rollout.getId().intValue())));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import static org.springframework.restdocs.snippet.Attributes.key;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -33,6 +34,7 @@ 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.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.eclipse.hawkbit.repository.test.TestConfiguration;
|
||||
@@ -161,28 +163,52 @@ public abstract class AbstractApiRestDocumentation extends AbstractRestIntegrati
|
||||
|
||||
protected Target createTargetByGivenNameWithAttributes(final String name, final boolean inSync,
|
||||
final boolean timeforced, final DistributionSet distributionSet) {
|
||||
return createTargetByGivenNameWithAttributes(name, inSync, timeforced, distributionSet, null, null, null);
|
||||
return createTargetByGivenNameWithAttributes(name, inSync, timeforced, distributionSet, null, null, null, false);
|
||||
}
|
||||
|
||||
protected Target createTargetByGivenNameWithAttributes(final String name, final boolean inSync,
|
||||
final boolean timeforced, final DistributionSet distributionSet, final boolean createRollout) {
|
||||
return createTargetByGivenNameWithAttributes(name, inSync, timeforced, distributionSet, null, null, null, createRollout);
|
||||
}
|
||||
|
||||
protected Target createTargetByGivenNameWithAttributes(final String name, final boolean inSync,
|
||||
final boolean timeforced, final DistributionSet distributionSet, final String maintenanceWindowSchedule,
|
||||
final String maintenanceWindowDuration, final String maintenanceWindowTimeZone) {
|
||||
final String maintenanceWindowDuration, final String maintenanceWindowTimeZone, final boolean createRollout) {
|
||||
|
||||
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 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());
|
||||
|
||||
final List<Target> updatedTargets;
|
||||
if (createRollout) {
|
||||
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("rollout", "rollout desc", 1,
|
||||
"name==" + name, distributionSet, "50", "5", timeforced ? ActionType.TIMEFORCED : ActionType.FORCED,
|
||||
isMultiAssignmentsEnabled() ? 600 : null);
|
||||
|
||||
// start the rollout and handle it
|
||||
rolloutManagement.start(rollout.getId());
|
||||
rolloutManagement.handleRollouts();
|
||||
|
||||
updatedTargets = Collections.singletonList(savedTarget);
|
||||
|
||||
} else {
|
||||
final DeploymentRequestBuilder deploymentRequestBuilder = DeploymentManagement
|
||||
.deploymentRequest(savedTarget.getControllerId(), distributionSet.getId())
|
||||
.setMaintenance(maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
|
||||
if (timeforced) {
|
||||
deploymentRequestBuilder.setActionType(ActionType.TIMEFORCED);
|
||||
}
|
||||
|
||||
if (isMultiAssignmentsEnabled()) {
|
||||
deploymentRequestBuilder.setWeight(600);
|
||||
}
|
||||
|
||||
updatedTargets = makeAssignment(deploymentRequestBuilder.build()).getAssignedEntity().stream()
|
||||
.map(Action::getTarget).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
if (inSync) {
|
||||
feedbackToByInSync(distributionSet);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ public final class MgmtApiModelProperties {
|
||||
public static final String LINK_TO_METADATA = "The link to the metadata.";
|
||||
public static final String LINK_TO_MANDATORY_SMT = "Link to mandatory software modules types in this distribution set type.";
|
||||
public static final String LINK_TO_OPTIONAL_SMT = "Link to optional software modules types in this distribution set type.";
|
||||
public static final String LINK_TO_ROLLOUT = "The link to the rollout.";
|
||||
|
||||
// software module types
|
||||
public static final String SMT_TYPE = "The type of the software module identified by its key.";
|
||||
@@ -143,6 +144,10 @@ public final class MgmtApiModelProperties {
|
||||
|
||||
public static final String ACTION_WEIGHT = "Weight of the action showing the importance of the update.";
|
||||
|
||||
public static final String ACTION_ROLLOUT = "The ID of the rollout this action was created for.";
|
||||
|
||||
public static final String ACTION_ROLLOUT_NAME = "The name of the rollout this action was created for.";
|
||||
|
||||
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.";
|
||||
|
||||
@@ -201,7 +201,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
@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);
|
||||
generateRolloutActionForTarget(targetId);
|
||||
|
||||
mockMvc.perform(
|
||||
get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/{targetId}/" + MgmtRestConstants.TARGET_V1_ACTIONS,
|
||||
@@ -228,7 +228,10 @@ 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[].weight").description(MgmtApiModelProperties.ACTION_WEIGHT),
|
||||
fieldWithPath("content[].rollout").description(MgmtApiModelProperties.ACTION_ROLLOUT),
|
||||
fieldWithPath("content[].rolloutName")
|
||||
.description(MgmtApiModelProperties.ACTION_ROLLOUT_NAME))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -323,7 +326,7 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
@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);
|
||||
final Action action = generateRolloutActionForTarget(targetId, true, true);
|
||||
assertThat(deploymentManagement.findAction(action.getId()).get().getActionType())
|
||||
.isEqualTo(ActionType.TIMEFORCED);
|
||||
|
||||
@@ -349,10 +352,15 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
.type("String"),
|
||||
fieldWithPath("status").description(MgmtApiModelProperties.ACTION_EXECUTION_STATUS)
|
||||
.attributes(key("value").value("['finished', 'pending']")),
|
||||
fieldWithPath("rollout").description(MgmtApiModelProperties.ACTION_ROLLOUT),
|
||||
fieldWithPath("rolloutName")
|
||||
.description(MgmtApiModelProperties.ACTION_ROLLOUT_NAME),
|
||||
fieldWithPath("_links.self").ignored(),
|
||||
fieldWithPath("_links.distributionset").description(MgmtApiModelProperties.LINK_TO_DS),
|
||||
fieldWithPath("_links.status")
|
||||
.description(MgmtApiModelProperties.LINKS_ACTION_STATUSES))));
|
||||
.description(MgmtApiModelProperties.LINKS_ACTION_STATUSES),
|
||||
fieldWithPath("_links.rollout")
|
||||
.description(MgmtApiModelProperties.LINK_TO_ROLLOUT))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -820,10 +828,19 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
return generateActionForTarget(knownControllerId, true, false, null, null, null);
|
||||
}
|
||||
|
||||
private Action generateRolloutActionForTarget(final String knownControllerId) throws Exception {
|
||||
return generateActionForTarget(knownControllerId, true, false, null, null, null, true);
|
||||
}
|
||||
|
||||
private Action generateActionForTarget(final String knownControllerId, final boolean inSync) throws Exception {
|
||||
return generateActionForTarget(knownControllerId, inSync, false, null, null, null);
|
||||
}
|
||||
|
||||
private Action generateRolloutActionForTarget(final String knownControllerId, final boolean inSync,
|
||||
final boolean timeforced) throws Exception {
|
||||
return generateActionForTarget(knownControllerId, inSync, timeforced, null, null, null, true);
|
||||
}
|
||||
|
||||
private Action generateActionForTarget(final String knownControllerId, final boolean inSync,
|
||||
final boolean timeforced) throws Exception {
|
||||
return generateActionForTarget(knownControllerId, inSync, timeforced, null, null, null);
|
||||
@@ -832,14 +849,22 @@ public class TargetResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
private Action generateActionForTarget(final String knownControllerId, final boolean inSync,
|
||||
final boolean timeforced, final String maintenanceWindowSchedule, final String maintenanceWindowDuration,
|
||||
final String maintenanceWindowTimeZone) throws Exception {
|
||||
return generateActionForTarget(knownControllerId, inSync, timeforced, maintenanceWindowSchedule,
|
||||
maintenanceWindowDuration, maintenanceWindowTimeZone, false);
|
||||
}
|
||||
|
||||
private Action generateActionForTarget(final String knownControllerId, final boolean inSync,
|
||||
final boolean timeforced, final String maintenanceWindowSchedule, final String maintenanceWindowDuration,
|
||||
final String maintenanceWindowTimeZone, final boolean createRollout) throws Exception {
|
||||
final PageRequest pageRequest = PageRequest.of(0, 1, Direction.ASC, ActionStatusFields.ID.getFieldName());
|
||||
|
||||
createTargetByGivenNameWithAttributes(knownControllerId, inSync, timeforced, createDistributionSet(),
|
||||
maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
maintenanceWindowSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone, createRollout);
|
||||
|
||||
final List<Action> actions = deploymentManagement.findActionsAll(pageRequest).getContent();
|
||||
|
||||
assertThat(actions).hasSize(1);
|
||||
return actions.get(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user