Support user consent flow (#1293)

* Introduce user consent flow
* Add permissions to confirmation management
* rename from consent to confirmation
* Reformat code. Remove unused imports. Change and add permission checks when configuring auto-confirmation.
* Do not include null values for DDI confirmation base endpoint
* fix confirmation required checkbox id
* Remove unused import. Fix consume/produce type of new API's.
* Change term processing to proceeding when activating user consent flow
* Align formatting and extend integration test cases for DMF and DDI.
* Extend DMF test cases to consider auto-confirmation
* Refactor action management to fix problem of handling action status updates on closed actions.
* remove unsupported validation
* use new confirmation api for DMF. Extend test cases.,
* Remove unnecessary fields.
* Extend API documentation for DDI and MGMT API.
* adapt ddi api docs adoc file
* Fixed the duplicate migration version for db files
* fix method to support confirmation
* Fixed PR comments
* Addressed PR comments
* Fixed after merge compilation issue
* Fixed after merge compilation issue
* Fix failing tests in MgmtRolloutResourceTest
* Fixed the permissions issue reflected by integration tests
* Added back the missing line of code lost during merge
* Fix the failing test on Jenkins

Signed-off-by: Stanislav Trailov <stanislav.trailov@bosch.io>
Signed-off-by: Dimitar Shterev <dimitar.shterev@bosch.io>
Signed-off-by: Michael Herdt <Michael.Herdt@bosch.io>
Signed-off-by: Shruthi Manavalli Ramanna <shruthimanavalli.ramanna@bosch-si.com>
Co-authored-by: Shruthi Manavalli Ramanna <shruthimanavalli.ramanna@bosch-si.com>
This commit is contained in:
Michael Herdt
2023-01-25 12:11:05 +01:00
committed by GitHub
parent b919ceda5c
commit 21f1569881
208 changed files with 7830 additions and 831 deletions

View File

@@ -14,7 +14,6 @@ import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtTargetAssignmentR
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtDistributionSetAssignment;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.MaintenanceScheduleHelper;
import org.eclipse.hawkbit.repository.model.DeploymentRequest;
import org.eclipse.hawkbit.repository.model.DeploymentRequestBuilder;
/**
@@ -26,38 +25,37 @@ public final class MgmtDeploymentRequestMapper {
}
/**
* Convert assignment information to an {@link DeploymentRequest}
* Convert assignment information to an {@link DeploymentRequestBuilder}
*
* @param dsAssignment
* DS assignment information
* @param targetId
* target to assign the DS to
* @return resulting {@link DeploymentRequest}
* @return resulting {@link DeploymentRequestBuilder}
*/
public static DeploymentRequest createAssignmentRequest(final MgmtDistributionSetAssignment dsAssignment,
final String targetId) {
public static DeploymentRequestBuilder createAssignmentRequestBuilder(
final MgmtDistributionSetAssignment dsAssignment, final String targetId) {
return createAssignmentRequest(targetId, dsAssignment.getId(), dsAssignment.getType(),
return createAssignmentRequestBuilder(targetId, dsAssignment.getId(), dsAssignment.getType(),
dsAssignment.getForcetime(), dsAssignment.getWeight(), dsAssignment.getMaintenanceWindow());
}
/**
* Convert assignment information to an {@link DeploymentRequest}
* Convert assignment information to an {@link DeploymentRequestBuilder}
*
* @param targetAssignment
* target assignment information
* @param dsId
* DS to assign the target to
* @return resulting {@link DeploymentRequest}
* @return resulting {@link DeploymentRequestBuilder}
*/
public static DeploymentRequest createAssignmentRequest(final MgmtTargetAssignmentRequestBody targetAssignment,
final Long dsId) {
return createAssignmentRequest(targetAssignment.getId(), dsId, targetAssignment.getType(),
public static DeploymentRequestBuilder createAssignmentRequestBuilder(
final MgmtTargetAssignmentRequestBody targetAssignment, final Long dsId) {
return createAssignmentRequestBuilder(targetAssignment.getId(), dsId, targetAssignment.getType(),
targetAssignment.getForcetime(), targetAssignment.getWeight(), targetAssignment.getMaintenanceWindow());
}
private static DeploymentRequest createAssignmentRequest(final String targetId, final Long dsId,
private static DeploymentRequestBuilder createAssignmentRequestBuilder(final String targetId, final Long dsId,
final MgmtActionType type, final long forcetime, final Integer weight,
final MgmtMaintenanceWindowRequestBody maintenanceWindow) {
final DeploymentRequestBuilder request = DeploymentManagement.deploymentRequest(targetId, dsId)
@@ -69,6 +67,6 @@ public final class MgmtDeploymentRequestMapper {
MaintenanceScheduleHelper.validateMaintenanceSchedule(cronSchedule, duration, timezone);
request.setMaintenance(cronSchedule, duration, timezone);
}
return request.build();
return request;
}
}

View File

@@ -41,6 +41,7 @@ import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DeploymentRequest;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -51,6 +52,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
@@ -88,13 +90,16 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
private final SystemSecurityContext systemSecurityContext;
private final DistributionSetInvalidationManagement distributionSetInvalidationManagement;
private final TenantConfigHelper tenantConfigHelper;
MgmtDistributionSetResource(final SoftwareModuleManagement softwareModuleManagement,
final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement,
final DeploymentManagement deployManagament, final SystemManagement systemManagement,
final EntityFactory entityFactory, final DistributionSetManagement distributionSetManagement,
final SystemSecurityContext systemSecurityContext,
final DistributionSetInvalidationManagement distributionSetInvalidationManagement) {
final DistributionSetInvalidationManagement distributionSetInvalidationManagement,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.softwareModuleManagement = softwareModuleManagement;
this.targetManagement = targetManagement;
this.targetFilterQueryManagement = targetFilterQueryManagement;
@@ -104,6 +109,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
this.distributionSetManagement = distributionSetManagement;
this.systemSecurityContext = systemSecurityContext;
this.distributionSetInvalidationManagement = distributionSetInvalidationManagement;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@Override
@@ -203,8 +209,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
targetsAssignedDS = this.targetManagement.findByAssignedDistributionSet(pageable, distributionSetId);
}
return ResponseEntity.ok(new PagedList<>(MgmtTargetMapper.toResponse(targetsAssignedDS.getContent()),
targetsAssignedDS.getTotalElements()));
return ResponseEntity
.ok(new PagedList<>(MgmtTargetMapper.toResponse(targetsAssignedDS.getContent(), tenantConfigHelper),
targetsAssignedDS.getTotalElements()));
}
@Override
@@ -231,8 +238,9 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
targetsInstalledDS = this.targetManagement.findByInstalledDistributionSet(pageable, distributionSetId);
}
return ResponseEntity.ok(new PagedList<>(MgmtTargetMapper.toResponse(targetsInstalledDS.getContent()),
targetsInstalledDS.getTotalElements()));
return ResponseEntity
.ok(new PagedList<>(MgmtTargetMapper.toResponse(targetsInstalledDS.getContent(), tenantConfigHelper),
targetsInstalledDS.getTotalElements()));
}
@Override
@@ -251,8 +259,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
.findByAutoAssignDSAndRsql(pageable, distributionSetId, rsqlParam);
return ResponseEntity
.ok(new PagedList<>(MgmtTargetFilterQueryMapper.toResponse(targetFilterQueries.getContent()),
targetFilterQueries.getTotalElements()));
.ok(new PagedList<>(MgmtTargetFilterQueryMapper.toResponse(targetFilterQueries.getContent(),
tenantConfigHelper.isConfirmationFlowEnabled()), targetFilterQueries.getTotalElements()));
}
@Override
@@ -268,9 +276,13 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
.toResponse(deployManagament.offlineAssignedDistributionSets(offlineAssignments)));
}
final List<DeploymentRequest> deploymentRequests = assignments.stream()
.map(assignment -> MgmtDeploymentRequestMapper.createAssignmentRequest(assignment, distributionSetId))
.collect(Collectors.toList());
final List<DeploymentRequest> deploymentRequests = assignments.stream().map(dsAssignment -> {
final boolean isConfirmationRequired = dsAssignment.isConfirmationRequired() == null
? tenantConfigHelper.isConfirmationFlowEnabled()
: dsAssignment.isConfirmationRequired();
return MgmtDeploymentRequestMapper.createAssignmentRequestBuilder(dsAssignment, distributionSetId)
.setConfirmationRequired(isConfirmationRequired).build();
}).collect(Collectors.toList());
final List<DistributionSetAssignmentResult> assignmentResults = deployManagament
.assignDistributionSets(deploymentRequests);
@@ -302,7 +314,6 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
return ResponseEntity
.ok(new PagedList<>(MgmtDistributionSetMapper.toResponseDsMetadata(metaDataPage.getContent()),
metaDataPage.getTotalElements()));
}
@Override

View File

@@ -157,16 +157,18 @@ final class MgmtRolloutMapper {
return conditions.build();
}
static List<MgmtRolloutGroupResponseBody> toResponseRolloutGroup(final List<RolloutGroup> rollouts) {
static List<MgmtRolloutGroupResponseBody> toResponseRolloutGroup(final List<RolloutGroup> rollouts,
final boolean confirmationFlowEnabled) {
if (rollouts == null) {
return Collections.emptyList();
}
return rollouts.stream().map(group -> toResponseRolloutGroup(group, false)).collect(Collectors.toList());
return rollouts.stream().map(group -> toResponseRolloutGroup(group, false, confirmationFlowEnabled))
.collect(Collectors.toList());
}
static MgmtRolloutGroupResponseBody toResponseRolloutGroup(final RolloutGroup rolloutGroup,
final boolean withDetailedStatus) {
final boolean withDetailedStatus, final boolean confirmationFlowEnabled) {
final MgmtRolloutGroupResponseBody body = new MgmtRolloutGroupResponseBody();
body.setCreatedAt(rolloutGroup.getCreatedAt());
body.setCreatedBy(rolloutGroup.getCreatedBy());
@@ -180,6 +182,10 @@ final class MgmtRolloutMapper {
body.setTargetFilterQuery(rolloutGroup.getTargetFilterQuery());
body.setTotalTargets(rolloutGroup.getTotalTargets());
if (confirmationFlowEnabled) {
body.setConfirmationRequired(rolloutGroup.isConfirmationRequired());
}
body.setSuccessCondition(new MgmtRolloutCondition(map(rolloutGroup.getSuccessCondition()),
rolloutGroup.getSuccessConditionExp()));
body.setSuccessAction(

View File

@@ -9,6 +9,7 @@
package org.eclipse.hawkbit.mgmt.rest.resource;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.validation.ValidationException;
@@ -16,6 +17,7 @@ import javax.validation.ValidationException;
import org.eclipse.hawkbit.mgmt.json.model.PagedList;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutResponseBody;
import org.eclipse.hawkbit.mgmt.json.model.rollout.MgmtRolloutRestRequestBody;
import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroup;
import org.eclipse.hawkbit.mgmt.json.model.rolloutgroup.MgmtRolloutGroupResponseBody;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRepresentationMode;
@@ -27,6 +29,7 @@ import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
import org.eclipse.hawkbit.repository.RolloutManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.RolloutCreate;
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
@@ -38,6 +41,8 @@ import org.eclipse.hawkbit.repository.model.RolloutGroupConditions;
import org.eclipse.hawkbit.repository.model.Target;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
@@ -66,15 +71,19 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
private final TargetFilterQueryManagement targetFilterQueryManagement;
private final EntityFactory entityFactory;
private final TenantConfigHelper tenantConfigHelper;
MgmtRolloutResource(final RolloutManagement rolloutManagement, final RolloutGroupManagement rolloutGroupManagement,
final DistributionSetManagement distributionSetManagement,
final TargetFilterQueryManagement targetFilterQueryManagement, final EntityFactory entityFactory) {
final TargetFilterQueryManagement targetFilterQueryManagement, final EntityFactory entityFactory,
final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.rolloutManagement = rolloutManagement;
this.rolloutGroupManagement = rolloutGroupManagement;
this.distributionSetManagement = distributionSetManagement;
this.targetFilterQueryManagement = targetFilterQueryManagement;
this.entityFactory = entityFactory;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@Override
@@ -132,18 +141,26 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
final DistributionSet distributionSet = distributionSetManagement
.getValidAndComplete(rolloutRequestBody.getDistributionSetId());
final RolloutGroupConditions rolloutGroupConditions = MgmtRolloutMapper.fromRequest(rolloutRequestBody, true);
final RolloutCreate create = MgmtRolloutMapper.fromRequest(entityFactory, rolloutRequestBody, distributionSet);
final boolean confirmationFlowActive = tenantConfigHelper.isConfirmationFlowEnabled();
Rollout rollout;
if (rolloutRequestBody.getGroups() != null) {
final List<RolloutGroupCreate> rolloutGroups = rolloutRequestBody.getGroups().stream()
.map(mgmtRolloutGroup -> MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup))
.collect(Collectors.toList());
.map(mgmtRolloutGroup -> {
final boolean confirmationRequired = isConfirmationRequiredForGroup(mgmtRolloutGroup,
rolloutRequestBody).orElse(confirmationFlowActive);
return MgmtRolloutMapper.fromRequest(entityFactory, mgmtRolloutGroup)
.confirmationRequired(confirmationRequired);
}).collect(Collectors.toList());
rollout = rolloutManagement.create(create, rolloutGroups, rolloutGroupConditions);
} else if (rolloutRequestBody.getAmountGroups() != null) {
rollout = rolloutManagement.create(create, rolloutRequestBody.getAmountGroups(), rolloutGroupConditions);
final boolean confirmationRequired = rolloutRequestBody.isConfirmationRequired() == null
? confirmationFlowActive
: rolloutRequestBody.isConfirmationRequired();
rollout = rolloutManagement.create(create, rolloutRequestBody.getAmountGroups(), confirmationRequired,
rolloutGroupConditions);
} else {
throw new ValidationException("Either 'amountGroups' or 'groups' must be defined in the request");
@@ -152,6 +169,16 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtRolloutMapper.toResponseRollout(rollout, true));
}
private Optional<Boolean> isConfirmationRequiredForGroup(final MgmtRolloutGroup group,
final MgmtRolloutRestRequestBody request) {
if (group.isConfirmationRequired() != null) {
return Optional.of(group.isConfirmationRequired());
} else if (request.isConfirmationRequired() != null) {
return Optional.of(request.isConfirmationRequired());
}
return Optional.empty();
}
@Override
public ResponseEntity<Void> approve(@PathVariable("rolloutId") final Long rolloutId, final String remark) {
rolloutManagement.approveOrDeny(rolloutId, Rollout.ApprovalDecision.APPROVED, remark);
@@ -209,7 +236,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
}
final List<MgmtRolloutGroupResponseBody> rest = MgmtRolloutMapper
.toResponseRolloutGroup(findRolloutGroupsAll.getContent());
.toResponseRolloutGroup(findRolloutGroupsAll.getContent(), tenantConfigHelper.isConfirmationFlowEnabled());
return ResponseEntity.ok(new PagedList<>(rest, findRolloutGroupsAll.getTotalElements()));
}
@@ -220,7 +247,8 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
final RolloutGroup rolloutGroup = rolloutGroupManagement.getWithDetailedStatus(groupId)
.orElseThrow(() -> new EntityNotFoundException(RolloutGroup.class, rolloutId));
return ResponseEntity.ok(MgmtRolloutMapper.toResponseRolloutGroup(rolloutGroup, true));
return ResponseEntity.ok(MgmtRolloutMapper.toResponseRolloutGroup(rolloutGroup, true,
tenantConfigHelper.isConfirmationFlowEnabled()));
}
private void findRolloutOrThrowException(final Long rolloutId) {
@@ -251,7 +279,7 @@ public class MgmtRolloutResource implements MgmtRolloutRestApi {
final Page<Target> pageTargets = this.rolloutGroupManagement.findTargetsOfRolloutGroup(pageable, groupId);
rolloutGroupTargets = pageTargets;
}
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(rolloutGroupTargets.getContent());
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(rolloutGroupTargets.getContent(), tenantConfigHelper);
return ResponseEntity.ok(new PagedList<>(rest, rolloutGroupTargets.getTotalElements()));
}

View File

@@ -38,14 +38,15 @@ public final class MgmtTargetFilterQueryMapper {
// Utility class
}
static List<MgmtTargetFilterQuery> toResponse(final List<TargetFilterQuery> filters) {
static List<MgmtTargetFilterQuery> toResponse(final List<TargetFilterQuery> filters,
final boolean confirmationFlowEnabled) {
if (CollectionUtils.isEmpty(filters)) {
return Collections.emptyList();
}
return filters.stream().map(MgmtTargetFilterQueryMapper::toResponse).collect(Collectors.toList());
return filters.stream().map(filter -> toResponse(filter, confirmationFlowEnabled)).collect(Collectors.toList());
}
static MgmtTargetFilterQuery toResponse(final TargetFilterQuery filter) {
static MgmtTargetFilterQuery toResponse(final TargetFilterQuery filter, final boolean confirmationFlowEnabled) {
final MgmtTargetFilterQuery targetRest = new MgmtTargetFilterQuery();
targetRest.setFilterId(filter.getId());
targetRest.setName(filter.getName());
@@ -62,6 +63,9 @@ public final class MgmtTargetFilterQueryMapper {
targetRest.setAutoAssignDistributionSet(distributionSet.getId());
targetRest.setAutoAssignActionType(MgmtRestModelMapper.convertActionType(filter.getAutoAssignActionType()));
filter.getAutoAssignWeight().ifPresent(targetRest::setAutoAssignWeight);
if (confirmationFlowEnabled) {
targetRest.setConfirmationRequired(filter.isConfirmationRequired());
}
}
targetRest.add(linkTo(methodOn(MgmtTargetFilterQueryRestApi.class).getFilter(filter.getId())).withSelfRel());

View File

@@ -20,9 +20,13 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetFilterQueryRestApi;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
@@ -46,18 +50,23 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
private final TargetFilterQueryManagement filterManagement;
private final EntityFactory entityFactory;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetFilterQueryResource(final TargetFilterQueryManagement filterManagement,
final EntityFactory entityFactory) {
MgmtTargetFilterQueryResource(final TargetFilterQueryManagement filterManagement, final EntityFactory entityFactory,
final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.filterManagement = filterManagement;
this.entityFactory = entityFactory;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@Override
public ResponseEntity<MgmtTargetFilterQuery> getFilter(@PathVariable("filterId") final Long filterId) {
final TargetFilterQuery findTarget = findFilterWithExceptionIfNotFound(filterId);
// to single response include poll status
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(findTarget);
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(findTarget,
tenantConfigHelper.isConfirmationFlowEnabled());
MgmtTargetFilterQueryMapper.addLinks(response);
return ResponseEntity.ok(response);
@@ -87,7 +96,7 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
}
final List<MgmtTargetFilterQuery> rest = MgmtTargetFilterQueryMapper
.toResponse(findTargetFiltersAll.getContent());
.toResponse(findTargetFiltersAll.getContent(), tenantConfigHelper.isConfirmationFlowEnabled());
return ResponseEntity.ok(new PagedList<>(rest, countTargetsAll));
}
@@ -97,7 +106,8 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
final TargetFilterQuery createdTarget = filterManagement
.create(MgmtTargetFilterQueryMapper.fromRequest(entityFactory, filter));
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(createdTarget);
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(createdTarget,
tenantConfigHelper.isConfirmationFlowEnabled());
MgmtTargetFilterQueryMapper.addLinks(response);
return new ResponseEntity<>(response, HttpStatus.CREATED);
@@ -112,7 +122,8 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
.update(entityFactory.targetFilterQuery().update(filterId).name(targetFilterRest.getName())
.query(targetFilterRest.getQuery()));
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter);
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter,
tenantConfigHelper.isConfirmationFlowEnabled());
MgmtTargetFilterQueryMapper.addLinks(response);
return ResponseEntity.ok(response);
@@ -130,10 +141,17 @@ public class MgmtTargetFilterQueryResource implements MgmtTargetFilterQueryRestA
@PathVariable("filterId") final Long filterId,
@RequestBody final MgmtDistributionSetAutoAssignment autoAssignRequest) {
final TargetFilterQuery updateFilter = filterManagement.updateAutoAssignDS(
MgmtTargetFilterQueryMapper.fromRequest(entityFactory, filterId, autoAssignRequest));
final boolean confirmationRequired = autoAssignRequest.isConfirmationRequired() == null
? tenantConfigHelper.isConfirmationFlowEnabled()
: autoAssignRequest.isConfirmationRequired();
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter);
final AutoAssignDistributionSetUpdate update = MgmtTargetFilterQueryMapper
.fromRequest(entityFactory, filterId, autoAssignRequest).confirmationRequired(confirmationRequired);
final TargetFilterQuery updateFilter = filterManagement.updateAutoAssignDS(update);
final MgmtTargetFilterQuery response = MgmtTargetFilterQueryMapper.toResponse(updateFilter,
tenantConfigHelper.isConfirmationFlowEnabled());
MgmtTargetFilterQueryMapper.addLinks(response);
return ResponseEntity.ok(response);

View File

@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.mgmt.json.model.MgmtPollStatus;
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtAction;
import org.eclipse.hawkbit.mgmt.json.model.action.MgmtActionStatus;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetAutoConfirm;
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;
@@ -40,6 +41,7 @@ import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.ActionType;
import org.eclipse.hawkbit.repository.model.ActionStatus;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus;
import org.eclipse.hawkbit.repository.model.MetaData;
import org.eclipse.hawkbit.repository.model.PollStatus;
import org.eclipse.hawkbit.repository.model.Rollout;
@@ -48,6 +50,7 @@ import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.rest.data.ResponseList;
import org.eclipse.hawkbit.rest.data.SortDirection;
import org.eclipse.hawkbit.util.IpUtil;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.springframework.data.domain.PageRequest;
/**
@@ -85,6 +88,27 @@ public final class MgmtTargetMapper {
response.add(linkTo(methodOn(MgmtTargetTypeRestApi.class).getTargetType(response.getTargetType()))
.withRel(MgmtRestConstants.TARGET_V1_ASSIGNED_TARGET_TYPE));
}
if (response.getAutoConfirmActive() != null) {
response.add(linkTo(methodOn(MgmtTargetRestApi.class).getAutoConfirmStatus(response.getControllerId()))
.withRel(MgmtRestConstants.TARGET_V1_AUTO_CONFIRM));
}
}
public static MgmtTargetAutoConfirm getTargetAutoConfirmResponse(final Target target) {
final AutoConfirmationStatus status = target.getAutoConfirmationStatus();
final MgmtTargetAutoConfirm response;
if (status != null) {
response = MgmtTargetAutoConfirm.active(status.getActivatedAt());
response.setInitiator(status.getInitiator());
response.setRemark(status.getRemark());
response.add(linkTo(methodOn(MgmtTargetRestApi.class).deactivateAutoConfirm(target.getControllerId()))
.withRel(MgmtRestConstants.TARGET_V1_DEACTIVATE_AUTO_CONFIRM));
} else {
response = MgmtTargetAutoConfirm.disabled();
response.add(linkTo(methodOn(MgmtTargetRestApi.class).activateAutoConfirm(target.getControllerId(), null))
.withRel(MgmtRestConstants.TARGET_V1_ACTIVATE_AUTO_CONFIRM));
}
return response;
}
static void addPollStatus(final Target target, final MgmtTarget targetRest) {
@@ -107,12 +131,13 @@ public final class MgmtTargetMapper {
* list of targets
* @return the response
*/
public static List<MgmtTarget> toResponse(final Collection<Target> targets) {
public static List<MgmtTarget> toResponse(final Collection<Target> targets, final TenantConfigHelper configHelper) {
if (targets == null) {
return Collections.emptyList();
}
return new ResponseList<>(targets.stream().map(MgmtTargetMapper::toResponse).collect(Collectors.toList()));
return new ResponseList<>(
targets.stream().map(target -> toResponse(target, configHelper)).collect(Collectors.toList()));
}
/**
@@ -122,7 +147,7 @@ public final class MgmtTargetMapper {
* the target
* @return the response
*/
public static MgmtTarget toResponse(final Target target) {
public static MgmtTarget toResponse(final Target target, final TenantConfigHelper configHelper) {
if (target == null) {
return null;
}
@@ -163,6 +188,9 @@ public final class MgmtTargetMapper {
targetRest.setTargetType(target.getTargetType().getId());
targetRest.setTargetTypeName(target.getTargetType().getName());
}
if (configHelper.isConfirmationFlowEnabled()) {
targetRest.setAutoConfirmActive(target.getAutoConfirmationStatus() != null);
}
targetRest.add(linkTo(methodOn(MgmtTargetRestApi.class).getTarget(target.getControllerId())).withSelfRel());

View File

@@ -13,6 +13,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.validation.Valid;
@@ -31,13 +32,17 @@ import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtTargetAssignmentR
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtDistributionSetAssignments;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTarget;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetAttributes;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetAutoConfirm;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetAutoConfirmUpdate;
import org.eclipse.hawkbit.mgmt.json.model.target.MgmtTargetRequestBody;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtTargetRestApi;
import org.eclipse.hawkbit.repository.ConfirmationManagement;
import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.ActionStatus;
@@ -45,6 +50,8 @@ import org.eclipse.hawkbit.repository.model.DeploymentRequest;
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetMetadata;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
@@ -69,22 +76,30 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
private final TargetManagement targetManagement;
private final ConfirmationManagement confirmationManagement;
private final DeploymentManagement deploymentManagement;
private final EntityFactory entityFactory;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetResource(final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
final EntityFactory entityFactory) {
final ConfirmationManagement confirmationManagement, final EntityFactory entityFactory,
final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.targetManagement = targetManagement;
this.deploymentManagement = deploymentManagement;
this.confirmationManagement = confirmationManagement;
this.entityFactory = entityFactory;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@Override
public ResponseEntity<MgmtTarget> getTarget(@PathVariable("targetId") final String targetId) {
final Target findTarget = findTargetWithExceptionIfNotFound(targetId);
// to single response include poll status
final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget);
final MgmtTarget response = MgmtTargetMapper.toResponse(findTarget, tenantConfigHelper);
MgmtTargetMapper.addPollStatus(findTarget, response);
MgmtTargetMapper.addTargetLinks(response);
@@ -113,7 +128,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
countTargetsAll = targetManagement.count();
}
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent());
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent(), tenantConfigHelper);
return ResponseEntity.ok(new PagedList<>(rest, countTargetsAll));
}
@@ -123,7 +138,8 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final Collection<Target> createdTargets = this.targetManagement
.create(MgmtTargetMapper.fromRequest(entityFactory, targets));
LOG.debug("{} targets created, return status {}", targets.size(), HttpStatus.CREATED);
return new ResponseEntity<>(MgmtTargetMapper.toResponse(createdTargets), HttpStatus.CREATED);
return new ResponseEntity<>(MgmtTargetMapper.toResponse(createdTargets, tenantConfigHelper),
HttpStatus.CREATED);
}
@Override
@@ -143,7 +159,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
.targetType(targetRest.getTargetType()).securityToken(targetRest.getSecurityToken())
.requestAttributes(targetRest.isRequestAttributes()));
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget);
final MgmtTarget response = MgmtTargetMapper.toResponse(updateTarget, tenantConfigHelper);
MgmtTargetMapper.addPollStatus(updateTarget, response);
MgmtTargetMapper.addTargetLinks(response);
@@ -309,9 +325,13 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
}
findTargetWithExceptionIfNotFound(targetId);
final List<DeploymentRequest> deploymentRequests = dsAssignments.stream()
.map(dsAssignment -> MgmtDeploymentRequestMapper.createAssignmentRequest(dsAssignment, targetId))
.collect(Collectors.toList());
final List<DeploymentRequest> deploymentRequests = dsAssignments.stream().map(dsAssignment -> {
final boolean isConfirmationRequired = dsAssignment.isConfirmationRequired() == null
? tenantConfigHelper.isConfirmationFlowEnabled()
: dsAssignment.isConfirmationRequired();
return MgmtDeploymentRequestMapper.createAssignmentRequestBuilder(dsAssignment, targetId)
.setConfirmationRequired(isConfirmationRequired).build();
}).collect(Collectors.toList());
final List<DistributionSetAssignmentResult> assignmentResults = deploymentManagement
.assignDistributionSets(deploymentRequests);
@@ -416,4 +436,30 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
return new ResponseEntity<>(MgmtTargetMapper.toResponseTargetMetadata(created), HttpStatus.CREATED);
}
@Override
public ResponseEntity<MgmtTargetAutoConfirm> getAutoConfirmStatus(@PathVariable("targetId") final String targetId) {
final Target findTarget = findTargetWithExceptionIfNotFound(targetId);
final MgmtTargetAutoConfirm state = MgmtTargetMapper.getTargetAutoConfirmResponse(findTarget);
return ResponseEntity.ok(state);
}
@Override
public ResponseEntity<Void> activateAutoConfirm(@PathVariable("targetId") final String targetId,
@RequestBody(required = false) final MgmtTargetAutoConfirmUpdate update) {
final String initiator = getNullIfEmpty(update, MgmtTargetAutoConfirmUpdate::getInitiator);
final String remark = getNullIfEmpty(update, MgmtTargetAutoConfirmUpdate::getRemark);
confirmationManagement.activateAutoConfirmation(targetId, initiator, remark);
return new ResponseEntity<>(HttpStatus.OK);
}
private <T, R> R getNullIfEmpty(final T object, final Function<T, R> extractMethod) {
return object == null ? null : extractMethod.apply(object);
}
@Override
public ResponseEntity<Void> deactivateAutoConfirm(@PathVariable("targetId") final String targetId) {
confirmationManagement.deactivateAutoConfirmation(targetId);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -23,10 +23,13 @@ import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
import org.eclipse.hawkbit.repository.TargetManagement;
import org.eclipse.hawkbit.repository.TargetTagManagement;
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.eclipse.hawkbit.repository.model.TargetTagAssignmentResult;
import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.utils.TenantConfigHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
@@ -54,11 +57,15 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
private final EntityFactory entityFactory;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetTagResource(final TargetTagManagement tagManagement, final TargetManagement targetManagement,
final EntityFactory entityFactory) {
final EntityFactory entityFactory, final SystemSecurityContext securityContext,
final TenantConfigurationManagement configurationManagement) {
this.tagManagement = tagManagement;
this.targetManagement = targetManagement;
this.entityFactory = entityFactory;
this.tenantConfigHelper = TenantConfigHelper.usingContext(securityContext, configurationManagement);
}
@Override
@@ -149,7 +156,7 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
findTargetsAll = targetManagement.findByRsqlAndTag(pageable, rsqlParam, targetTagId);
}
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent());
final List<MgmtTarget> rest = MgmtTargetMapper.toResponse(findTargetsAll.getContent(), tenantConfigHelper);
return ResponseEntity.ok(new PagedList<>(rest, findTargetsAll.getTotalElements()));
}
@@ -164,8 +171,10 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
.toggleTagAssignment(findTargetControllerIds(assignedTargetRequestBodies), targetTag.getName());
final MgmtTargetTagAssigmentResult tagAssigmentResultRest = new MgmtTargetTagAssigmentResult();
tagAssigmentResultRest.setAssignedTargets(MgmtTargetMapper.toResponse(assigmentResult.getAssignedEntity()));
tagAssigmentResultRest.setUnassignedTargets(MgmtTargetMapper.toResponse(assigmentResult.getUnassignedEntity()));
tagAssigmentResultRest.setAssignedTargets(
MgmtTargetMapper.toResponse(assigmentResult.getAssignedEntity(), tenantConfigHelper));
tagAssigmentResultRest.setUnassignedTargets(
MgmtTargetMapper.toResponse(assigmentResult.getUnassignedEntity(), tenantConfigHelper));
return ResponseEntity.ok(tagAssigmentResultRest);
}
@@ -175,7 +184,7 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
LOG.debug("Assign Targets {} for target tag {}", assignedTargetRequestBodies.size(), targetTagId);
final List<Target> assignedTarget = this.targetManagement
.assignTag(findTargetControllerIds(assignedTargetRequestBodies), targetTagId);
return ResponseEntity.ok(MgmtTargetMapper.toResponse(assignedTarget));
return ResponseEntity.ok(MgmtTargetMapper.toResponse(assignedTarget, tenantConfigHelper));
}
@Override