Feature Approval Workflow for rollouts (#678)
* implement feature approval workflow Signed-off-by: Ioannis Spyropoulos <ioannis.spyropoulos@bosch-si.com> Signed-off-by: Michael Müller <Michael.Mueller17@bosch-si.com> * add documentation for REST endpoints Signed-off-by: Ioannis Spyropoulos <ioannis.spyropoulos@bosch-si.com> Signed-off-by: Michael Müller <Michael.Mueller17@bosch-si.com> * fix broken documentation test Signed-off-by: Ioannis Spyropoulos <ioannis.spyropoulos@bosch-si.com> * fix broken documentation test II Signed-off-by: Ioannis Spyropoulos <ioannis.spyropoulos@bosch-si.com>
This commit is contained in:
committed by
Dominic Schabel
parent
8a14c931c8
commit
cef7c2bbf2
@@ -81,6 +81,36 @@ public interface MgmtRolloutRestApi {
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<MgmtRolloutResponseBody> create(MgmtRolloutRestRequestBody rolloutRequestBody);
|
||||
|
||||
/**
|
||||
* Handles the request for approving a rollout.
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to be approved.
|
||||
* @param remark
|
||||
* an optional remark on the approval decision
|
||||
* @return OK response (200) if rollout is approved now. In case of any
|
||||
* exception the corresponding errors occur.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{rolloutId}/approve", produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<Void> approve(@PathVariable("rolloutId") Long rolloutId,
|
||||
@RequestParam(value = "remark", required = false) String remark);
|
||||
|
||||
/**
|
||||
* Handles the request for denying the approval of a rollout.
|
||||
*
|
||||
* @param rolloutId
|
||||
* the ID of the rollout to be denied.
|
||||
* @param remark
|
||||
* an optional remark on the denial decision
|
||||
* @return OK response (200) if rollout is denied now. In case of any
|
||||
* exception the corresponding errors occur.
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{rolloutId}/deny", produces = { MediaTypes.HAL_JSON_VALUE,
|
||||
MediaType.APPLICATION_JSON_VALUE })
|
||||
ResponseEntity<Void> deny(@PathVariable("rolloutId") Long rolloutId,
|
||||
@RequestParam(value = "remark", required = false) String remark);
|
||||
|
||||
/**
|
||||
* Handles the POST request for starting a rollout.
|
||||
*
|
||||
|
||||
@@ -88,6 +88,8 @@ final class MgmtRolloutMapper {
|
||||
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).start(rollout.getId())).withRel("start"));
|
||||
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).pause(rollout.getId())).withRel("pause"));
|
||||
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).resume(rollout.getId())).withRel("resume"));
|
||||
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).approve(rollout.getId(), null)).withRel("approve"));
|
||||
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).deny(rollout.getId(), null)).withRel("deny"));
|
||||
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).getRolloutGroups(rollout.getId(),
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_OFFSET_VALUE,
|
||||
MgmtRestConstants.REQUEST_PARAMETER_PAGING_DEFAULT_LIMIT_VALUE, null, null)).withRel("groups"));
|
||||
|
||||
@@ -129,6 +129,18 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
|
||||
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtRolloutMapper.toResponseRollout(rollout, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> approve(@PathVariable("rolloutId") final Long rolloutId, final String remark) {
|
||||
rolloutManagement.approveOrDeny(rolloutId, Rollout.ApprovalDecision.APPROVED, remark);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> deny(@PathVariable("rolloutId") final Long rolloutId, final String remark) {
|
||||
rolloutManagement.approveOrDeny(rolloutId, Rollout.ApprovalDecision.DENIED, remark);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseEntity<Void> start(@PathVariable("rolloutId") final Long rolloutId) {
|
||||
this.rolloutManagement.start(rolloutId);
|
||||
|
||||
@@ -179,6 +179,81 @@ include::../errors/415.adoc[]
|
||||
include::../errors/429.adoc[]
|
||||
|===
|
||||
|
||||
== POST /rest/v1/rollouts/{rolloutId}/approve
|
||||
|
||||
=== Implementation Notes
|
||||
Handles the POST request of approving a created rollout within SP.
|
||||
Only possible if approval workflow is enabled in system configuration and rollout is in state WAITING_FOR_APPROVAL.
|
||||
Required Permission: APPROVE_ROLLOUT
|
||||
|
||||
=== Approve Rollout
|
||||
|
||||
==== CURL
|
||||
|
||||
include::{snippets}/rollouts/approve-rollout/curl-request.adoc[]
|
||||
|
||||
|
||||
==== Request URL
|
||||
|
||||
include::{snippets}/rollouts/approve-rollout/http-request.adoc[]
|
||||
|
||||
|
||||
=== Response (Status 200)
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/rollouts/approve-rollout/http-response.adoc[]
|
||||
|
||||
=== Error responses
|
||||
|
||||
|===
|
||||
| HTTP Status Code | Reason | Response Model
|
||||
include::../errors/400.adoc[]
|
||||
include::../errors/401.adoc[]
|
||||
include::../errors/403.adoc[]
|
||||
include::../errors/405.adoc[]
|
||||
include::../errors/406.adoc[]
|
||||
include::../errors/429.adoc[]
|
||||
|===
|
||||
|
||||
== POST /rest/v1/rollouts/{rolloutId}/deny
|
||||
|
||||
=== Implementation Notes
|
||||
Handles the POST request of denying a created rollout within SP.
|
||||
Only possible if approval workflow is enabled in system configuration and rollout is in state WAITING_FOR_APPROVAL.
|
||||
Required Permission: APPROVE_ROLLOUT
|
||||
|
||||
=== Deny Rollout
|
||||
|
||||
|
||||
==== CURL
|
||||
|
||||
include::{snippets}/rollouts/deny-rollout/curl-request.adoc[]
|
||||
|
||||
|
||||
==== Request URL
|
||||
|
||||
include::{snippets}/rollouts/deny-rollout/http-request.adoc[]
|
||||
|
||||
|
||||
=== Response (Status 200)
|
||||
|
||||
==== Response example
|
||||
|
||||
include::{snippets}/rollouts/deny-rollout/http-response.adoc[]
|
||||
|
||||
=== Error responses
|
||||
|
||||
|===
|
||||
| HTTP Status Code | Reason | Response Model
|
||||
include::../errors/400.adoc[]
|
||||
include::../errors/401.adoc[]
|
||||
include::../errors/403.adoc[]
|
||||
include::../errors/405.adoc[]
|
||||
include::../errors/406.adoc[]
|
||||
include::../errors/429.adoc[]
|
||||
|===
|
||||
|
||||
== POST /rest/v1/rollouts/{rolloutId}/start
|
||||
|
||||
=== Implementation Notes
|
||||
|
||||
@@ -103,6 +103,8 @@ public final class MgmtApiModelProperties {
|
||||
public static final String ROLLOUT_LINKS_START_ASYNC = "Link to start the rollout in async mode";
|
||||
public static final String ROLLOUT_LINKS_PAUSE = "Link to pause a running rollout";
|
||||
public static final String ROLLOUT_LINKS_RESUME = "Link to resume a paused rollout";
|
||||
public static final String ROLLOUT_LINKS_APPROVE = "Link to approve a rollout";
|
||||
public static final String ROLLOUT_LINKS_DENY = "Link to deny a rollout";
|
||||
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";
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessActi
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
|
||||
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
|
||||
import org.eclipse.hawkbit.rest.documentation.AbstractApiRestDocumentation;
|
||||
import org.eclipse.hawkbit.rest.documentation.ApiModelPropertiesGeneric;
|
||||
import org.eclipse.hawkbit.rest.documentation.DocumenationResponseFieldsSnippet;
|
||||
@@ -41,6 +42,7 @@ import org.eclipse.hawkbit.rest.util.JsonBuilder;
|
||||
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.hateoas.MediaTypes;
|
||||
import org.springframework.http.MediaType;
|
||||
@@ -62,12 +64,16 @@ import ru.yandex.qatools.allure.annotations.Stories;
|
||||
@Stories("Rollout Resource")
|
||||
public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentation {
|
||||
|
||||
@Autowired
|
||||
private RolloutTestApprovalStrategy approvalStrategy;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.resourceName = "rollouts";
|
||||
super.setUp();
|
||||
arrayPrefix = "content[].";
|
||||
approvalStrategy.setApprovalNeeded(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,7 +133,6 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
allFieldDescriptor.add(
|
||||
fieldWithPath(arrayPrefix + "totalTargets").description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS));
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.self").ignored());
|
||||
|
||||
if (withDetails) {
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "totalTargetsPerStatus")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_TOTAL_TARGETS_PER_STATUS));
|
||||
@@ -139,6 +144,10 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
.description(MgmtApiModelProperties.ROLLOUT_LINKS_RESUME));
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.groups")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_LINKS_GROUPS));
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.approve")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_LINKS_APPROVE));
|
||||
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.deny")
|
||||
.description(MgmtApiModelProperties.ROLLOUT_LINKS_DENY));
|
||||
}
|
||||
|
||||
return new DocumenationResponseFieldsSnippet(allFieldDescriptor);
|
||||
@@ -386,6 +395,29 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
|
||||
pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Handles the POST request of approving a rollout. Required Permission: "
|
||||
+ SpPermission.APPROVE_ROLLOUT)
|
||||
public void approveRollout() throws Exception {
|
||||
approvalStrategy.setApprovalNeeded(true);
|
||||
final Rollout rollout = createRolloutEntity();
|
||||
mockMvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/approve", rollout.getId())
|
||||
.accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(this.document.document(
|
||||
pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Handles the POST request of denying a rollout. Required Permission: " + SpPermission.APPROVE_ROLLOUT)
|
||||
public void denyRollout() throws Exception {
|
||||
approvalStrategy.setApprovalNeeded(true);
|
||||
final Rollout rollout = createRolloutEntity();
|
||||
mockMvc.perform(post(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}/deny", rollout.getId())
|
||||
.accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
|
||||
.andDo(this.document.document(
|
||||
pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Handles the GET request of retrieving the deploy groups of a rollout. Required Permission: "
|
||||
+ SpPermission.READ_ROLLOUT)
|
||||
|
||||
@@ -80,6 +80,8 @@ public class TenantResourceDocumentationTest extends AbstractApiRestDocumentatio
|
||||
"if the anonymous download mode is enabled.");
|
||||
CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED,
|
||||
"if autoclose running actions with new Distribution Set assignment is enabled.");
|
||||
CONFIG_ITEM_DESCRIPTIONS.put(TenantConfigurationKey.ROLLOUT_APPROVAL_ENABLED,
|
||||
"if approval mode for Rollout Management is enabled.");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
|
||||
Reference in New Issue
Block a user