Expose approval remark and decided by in rollout mgmt API (#1389)

Signed-off-by: Stanislav Trailov <Stanislav.Trailov@bosch.io>
This commit is contained in:
Stanislav Trailov
2023-07-11 08:59:12 +03:00
committed by GitHub
parent 3402808ee9
commit 593a0bb146
5 changed files with 79 additions and 6 deletions

View File

@@ -19,6 +19,8 @@ public class RolloutTestApprovalStrategy implements RolloutApprovalStrategy {
private boolean approvalNeeded = false; private boolean approvalNeeded = false;
private String approvalDecidedBy;
@Override @Override
public boolean isApprovalNeeded(Rollout rollout) { public boolean isApprovalNeeded(Rollout rollout) {
return approvalNeeded; return approvalNeeded;
@@ -28,6 +30,10 @@ public class RolloutTestApprovalStrategy implements RolloutApprovalStrategy {
this.approvalNeeded = approvalNeeded; this.approvalNeeded = approvalNeeded;
} }
public void setApproveDecidedBy(final String user) {
this.approvalDecidedBy = user;
}
@Override @Override
public void onApprovalRequired(Rollout rollout) { public void onApprovalRequired(Rollout rollout) {
// do nothing, as no action is needed when testing // do nothing, as no action is needed when testing
@@ -35,6 +41,6 @@ public class RolloutTestApprovalStrategy implements RolloutApprovalStrategy {
@Override @Override
public String getApprovalUser(Rollout rollout) { public String getApprovalUser(Rollout rollout) {
return null; return approvalDecidedBy;
} }
} }

View File

@@ -59,6 +59,12 @@ public class MgmtRolloutResponseBody extends MgmtNamedEntity {
@JsonProperty @JsonProperty
private Integer weight; private Integer weight;
@JsonProperty
private String approvalRemark;
@JsonProperty
private String approveDecidedBy;
public boolean isDeleted() { public boolean isDeleted() {
return deleted; return deleted;
} }
@@ -158,4 +164,20 @@ public class MgmtRolloutResponseBody extends MgmtNamedEntity {
public Integer getTotalGroups() { public Integer getTotalGroups() {
return totalGroups; return totalGroups;
} }
public void setApprovalRemark(final String approvalRemark) {
this.approvalRemark = approvalRemark;
}
public String getApprovalRemark() {
return approvalRemark;
}
public void setApproveDecidedBy(final String approveDecidedBy) {
this.approveDecidedBy = approveDecidedBy;
}
public String getApproveDecidedBy(final String approveDecidedBy) {
return approveDecidedBy;
}
} }

View File

@@ -95,6 +95,9 @@ final class MgmtRolloutMapper {
body.setTotalGroups(rollout.getRolloutGroupsCreated()); body.setTotalGroups(rollout.getRolloutGroupsCreated());
body.setStartAt(rollout.getStartAt()); body.setStartAt(rollout.getStartAt());
body.setApproveDecidedBy(rollout.getApprovalDecidedBy());
body.setApprovalRemark(rollout.getApprovalRemark());
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).start(rollout.getId())).withRel("start").expand()); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).start(rollout.getId())).withRel("start").expand());
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).pause(rollout.getId())).withRel("pause").expand()); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).pause(rollout.getId())).withRel("pause").expand());
body.add(linkTo(methodOn(MgmtRolloutRestApi.class).resume(rollout.getId())).withRel("resume").expand()); body.add(linkTo(methodOn(MgmtRolloutRestApi.class).resume(rollout.getId())).withRel("resume").expand());

View File

@@ -48,6 +48,7 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCond
import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder; import org.eclipse.hawkbit.repository.model.RolloutGroupConditionBuilder;
import org.eclipse.hawkbit.repository.model.RolloutGroupConditions; import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule; import org.eclipse.hawkbit.repository.test.util.WithSpringAuthorityRule;
import org.eclipse.hawkbit.repository.test.util.WithUser; import org.eclipse.hawkbit.repository.test.util.WithUser;
import org.eclipse.hawkbit.rest.util.JsonBuilder; import org.eclipse.hawkbit.rest.util.JsonBuilder;
@@ -83,6 +84,9 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
@Autowired @Autowired
private RolloutGroupManagement rolloutGroupManagement; private RolloutGroupManagement rolloutGroupManagement;
@Autowired
private RolloutTestApprovalStrategy approvalStrategy;
@Test @Test
@Description("Testing that creating rollout with wrong body returns bad request") @Description("Testing that creating rollout with wrong body returns bad request")
void createRolloutWithInvalidBodyReturnsBadRequest() throws Exception { void createRolloutWithInvalidBodyReturnsBadRequest() throws Exception {
@@ -1286,6 +1290,34 @@ class MgmtRolloutResourceTest extends AbstractManagementApiIntegrationTest {
assertThat(rollouts.get(0).getWeight()).get().isEqualTo(weight); assertThat(rollouts.get(0).getWeight()).get().isEqualTo(weight);
} }
@Test
@Description("Check if approvalDecidedBy and approvalRemark are present when rollout is approved")
public void validateIfApprovalFieldsArePresentAfterApproval() throws Exception {
approvalStrategy.setApprovalNeeded(true);
approvalStrategy.setApproveDecidedBy("testUser");
final int amountTargets = 2;
final String remark = "Some remark";
final List<Target> targets = testdataFactory.createTargets(amountTargets, "rollout");
final DistributionSet dsA = testdataFactory.createDistributionSet("");
final Rollout rollout = createRollout("rollout1", 3, dsA.getId(), "controllerId==rollout*", false);
rolloutHandler.handleAll();
mvc.perform(get("/rest/v1/rollouts/{rolloutid}", rollout.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk()).andExpect(jsonPath("$.status", equalTo("waiting_for_approval")));
rolloutManagement.approveOrDeny(rollout.getId(), Rollout.ApprovalDecision.APPROVED, remark);
mvc.perform(get("/rest/v1/rollouts/{rolloutid}", rollout.getId())).andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.status", equalTo("ready")))
.andExpect(jsonPath("$.approvalRemark", equalTo(remark)))
.andExpect(jsonPath("$.approveDecidedBy", equalTo("testUser")));
// revert
approvalStrategy.setApprovalNeeded(false);
}
private void postRollout(final String name, final int groupSize, final Long distributionSetId, private void postRollout(final String name, final int groupSize, final Long distributionSetId,
final String targetFilterQuery, final int targets, final Action.ActionType type) throws Exception { final String targetFilterQuery, final int targets, final Action.ActionType type) throws Exception {
postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, null, null); postRollout(name, groupSize, distributionSetId, targetFilterQuery, targets, type, null, null);

View File

@@ -87,7 +87,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING).accept(MediaTypes.HAL_JSON_VALUE)) mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING).accept(MediaTypes.HAL_JSON_VALUE))
.andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andDo(this.document.document(getRolloutResponseFields(true, false, .andDo(this.document.document(getRolloutResponseFields(true, false, false,
fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS), fieldWithPath("total").description(ApiModelPropertiesGeneric.TOTAL_ELEMENTS),
fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE), fieldWithPath("size").type(JsonFieldType.NUMBER).description(ApiModelPropertiesGeneric.SIZE),
fieldWithPath("content").description(MgmtApiModelProperties.ROLLOUT_LIST)))); fieldWithPath("content").description(MgmtApiModelProperties.ROLLOUT_LIST))));
@@ -106,7 +106,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
.andDo(this.document.document(getFilterRequestParamter())); .andDo(this.document.document(getFilterRequestParamter()));
} }
private Snippet getRolloutResponseFields(final boolean isArray, final boolean withDetails, private Snippet getRolloutResponseFields(final boolean isArray, final boolean withDetails, final boolean isApproveRequired,
final FieldDescriptor... descriptors) { final FieldDescriptor... descriptors) {
final String arrayPrefix = getArrayPrefix(isArray); final String arrayPrefix = getArrayPrefix(isArray);
final List<FieldDescriptor> allFieldDescriptor = new ArrayList<>(); final List<FieldDescriptor> allFieldDescriptor = new ArrayList<>();
@@ -162,6 +162,12 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
fieldWithPath(arrayPrefix + "_links.deny").description(MgmtApiModelProperties.ROLLOUT_LINKS_DENY)); fieldWithPath(arrayPrefix + "_links.deny").description(MgmtApiModelProperties.ROLLOUT_LINKS_DENY));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.distributionset") allFieldDescriptor.add(fieldWithPath(arrayPrefix + "_links.distributionset")
.description(MgmtApiModelProperties.LINK_TO_DS)); .description(MgmtApiModelProperties.LINK_TO_DS));
if (isApproveRequired) {
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "approveDecidedBy")
.description("Who Approved/Denied the rollout. Not present if the rollout is missing approval."));
allFieldDescriptor.add(fieldWithPath(arrayPrefix + "approvalRemark")
.description("A user remark of the approve/denied decision. Not present if the rollout is missing approval."));
}
} }
return new DocumenationResponseFieldsSnippet(allFieldDescriptor); return new DocumenationResponseFieldsSnippet(allFieldDescriptor);
@@ -172,12 +178,16 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
+ SpPermission.READ_ROLLOUT) + SpPermission.READ_ROLLOUT)
public void getRollout() throws Exception { public void getRollout() throws Exception {
enableMultiAssignments(); enableMultiAssignments();
approvalStrategy.setApprovalNeeded(true);
approvalStrategy.setApproveDecidedBy("exampleUsername");
final Rollout rollout = createRolloutEntity(); final Rollout rollout = createRolloutEntity();
rolloutManagement.approveOrDeny(rollout.getId(), Rollout.ApprovalDecision.APPROVED, "Approved remark.");
mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}", rollout.getId()) mockMvc.perform(get(MgmtRestConstants.ROLLOUT_V1_REQUEST_MAPPING + "/{rolloutId}", rollout.getId())
.accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk()) .accept(MediaTypes.HAL_JSON_VALUE)).andDo(MockMvcResultPrinter.print()).andExpect(status().isOk())
.andExpect(content().contentType(MediaTypes.HAL_JSON)) .andExpect(content().contentType(MediaTypes.HAL_JSON))
.andDo(this.document.document(getRolloutResponseFields(false, true), .andDo(this.document.document(getRolloutResponseFields(false, true, true),
pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID)))); pathParameters(parameterWithName("rolloutId").description(ApiModelPropertiesGeneric.ITEM_ID))));
} }
@@ -256,7 +266,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
optionalRequestFieldWithPath("errorAction.expression") optionalRequestFieldWithPath("errorAction.expression")
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)), .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)),
getRolloutResponseFields(false, true))); getRolloutResponseFields(false, true, false)));
} }
@@ -386,7 +396,7 @@ public class RolloutResourceDocumentationTest extends AbstractApiRestDocumentati
.attributes(key("value").value("['pause']")), .attributes(key("value").value("['pause']")),
optionalRequestFieldWithPath("groups[].errorAction.expression") optionalRequestFieldWithPath("groups[].errorAction.expression")
.description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)), .description(MgmtApiModelProperties.ROLLOUT_ERROR_ACTION_EXP)),
getRolloutResponseFields(false, true))); getRolloutResponseFields(false, true, false)));
} }
@Test @Test