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:
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository;
|
||||
|
||||
import org.eclipse.hawkbit.im.authentication.SpPermission;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus;
|
||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Service layer for all confirmation related operations.
|
||||
*/
|
||||
public interface ConfirmationManagement {
|
||||
|
||||
/**
|
||||
* Find active actions in the {@link Action.Status#WAIT_FOR_CONFIRMATION} state
|
||||
* for a specific target with a specified controllerId.
|
||||
*
|
||||
* @param controllerId
|
||||
* of the target to check
|
||||
* @return a list of {@link Action}
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
List<Action> findActiveActionsWaitingConfirmation(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Activate auto confirmation for a given controller ID. In case auto
|
||||
* confirmation is active already, this method will fail with an exception.
|
||||
*
|
||||
* @param controllerId
|
||||
* to activate the feature for
|
||||
* @param initiator
|
||||
* who initiated this operation. If 'null' we will take the current
|
||||
* user from {@link TenantAware#getCurrentUsername()}
|
||||
* @param remark
|
||||
* optional field to set a remark
|
||||
* @return the persisted {@link AutoConfirmationStatus}
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.IS_CONTROLLER_OR_HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
AutoConfirmationStatus activateAutoConfirmation(@NotEmpty String controllerId, final String initiator,
|
||||
final String remark);
|
||||
|
||||
/**
|
||||
* Get the current state of auto-confirmation for a given controllerId
|
||||
*
|
||||
* @param controllerId
|
||||
* to check the state for
|
||||
* @return instance of {@link AutoConfirmationStatus} wrapped in an
|
||||
* {@link Optional}. Present if active and empty if disabled.
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.HAS_AUTH_READ_TARGET)
|
||||
Optional<AutoConfirmationStatus> getStatus(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Auto confirm active actions for a specific controller ID having the
|
||||
* {@link Action.Status#WAIT_FOR_CONFIRMATION} status.
|
||||
*
|
||||
* @param controllerId
|
||||
* to confirm actions for
|
||||
* @return a list of confirmed actions
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.IS_CONTROLLER_OR_HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
List<Action> autoConfirmActiveActions(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Confirm a given action to put it from
|
||||
* {@link Action.Status#WAIT_FOR_CONFIRMATION} to {@link Action.Status#RUNNING}
|
||||
* state.
|
||||
*
|
||||
* @param actionId
|
||||
* mandatory to know which action to confirm
|
||||
* @param code
|
||||
* optional value to specify a code for the created action status
|
||||
* @param messages
|
||||
* optional value to specify message for the created action status
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.IS_CONTROLLER_OR_HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
Action confirmAction(long actionId, Integer code, Collection<String> messages);
|
||||
|
||||
/**
|
||||
* Deny a given action and leave it in
|
||||
* {@link Action.Status#WAIT_FOR_CONFIRMATION} state.
|
||||
*
|
||||
* @param actionId
|
||||
* mandatory to know which action to deny
|
||||
* @param code
|
||||
* optional value to specify a code for the created action status
|
||||
* @param messages
|
||||
* optional value to specify message for the created action status
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.IS_CONTROLLER_OR_HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
Action denyAction(long actionId, Integer code, Collection<String> messages);
|
||||
|
||||
/**
|
||||
* Deactivate auto confirmation for a specific controller id
|
||||
*
|
||||
* @param controllerId
|
||||
* to disable auto confirmation for
|
||||
*/
|
||||
@PreAuthorize(SpPermission.SpringEvalExpressions.IS_CONTROLLER_OR_HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
|
||||
void deactivateAutoConfirmation(@NotEmpty String controllerId);
|
||||
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import org.eclipse.hawkbit.repository.exception.InvalidTargetAttributeException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.ActionStatus;
|
||||
import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
@@ -508,4 +509,28 @@ public interface ControllerManagement {
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
Optional<Action> getInstalledActionByTarget(@NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Activate auto confirmation for a given controllerId
|
||||
*
|
||||
* @param controllerId
|
||||
* to activate auto-confirmation on
|
||||
* @param initiator
|
||||
* can be set optionally (fallback is the current acting security
|
||||
* user)
|
||||
* @param remark
|
||||
* (optional) remark
|
||||
* @return the persisted {@link AutoConfirmationStatus}
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
AutoConfirmationStatus activateAutoConfirmation(@NotEmpty String controllerId, String initiator, String remark);
|
||||
|
||||
/**
|
||||
* Deactivate auto confirmation for a given controllerId
|
||||
*
|
||||
* @param controllerId
|
||||
* to deactivate auto-confirmation on
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.IS_CONTROLLER)
|
||||
void deactivateAutoConfirmation(@NotEmpty String controllerId);
|
||||
}
|
||||
|
||||
@@ -449,8 +449,8 @@ public interface DeploymentManagement {
|
||||
Page<Action> findInActiveActionsByTarget(@NotNull Pageable pageable, @NotEmpty String controllerId);
|
||||
|
||||
/**
|
||||
* Retrieves active {@link Action}s with highest weight that are assigned to
|
||||
* a {@link Target}.
|
||||
* Retrieves active {@link Action}s with highest weight that are assigned to a
|
||||
* {@link Target}.
|
||||
*
|
||||
* @param controllerId
|
||||
* identifies the target to retrieve the action from
|
||||
@@ -522,6 +522,8 @@ public interface DeploymentManagement {
|
||||
*
|
||||
* @param rolloutId
|
||||
* the rollout the actions belong to
|
||||
* @param distributionSetId
|
||||
* to assign
|
||||
* @param rolloutGroupParentId
|
||||
* the parent rollout group the actions should reference. null
|
||||
* references the first group
|
||||
|
||||
@@ -108,27 +108,28 @@ public interface RolloutManagement {
|
||||
|
||||
/**
|
||||
* Persists a new rollout entity. The filter within the
|
||||
* {@link Rollout#getTargetFilterQuery()} is used to retrieve the targets
|
||||
* which are effected by this rollout to create. The amount of groups will
|
||||
* be defined as equally sized.
|
||||
* {@link Rollout#getTargetFilterQuery()} is used to retrieve the targets which
|
||||
* are effected by this rollout to create. The amount of groups will be defined
|
||||
* as equally sized.
|
||||
*
|
||||
* The rollout is not started. Only the preparation of the rollout is done,
|
||||
* creating and persisting all the necessary groups. The Rollout and the
|
||||
* groups are persisted in {@link RolloutStatus#CREATING} and
|
||||
* creating and persisting all the necessary groups. The Rollout and the groups
|
||||
* are persisted in {@link RolloutStatus#CREATING} and
|
||||
* {@link RolloutGroupStatus#CREATING}.
|
||||
*
|
||||
* The RolloutScheduler will start to assign targets to the groups. Once all
|
||||
* targets have been assigned to the groups, the rollout status is changed
|
||||
* to {@link RolloutStatus#READY} so it can be started with
|
||||
* {@link #start(Rollout)}.
|
||||
* targets have been assigned to the groups, the rollout status is changed to
|
||||
* {@link RolloutStatus#READY} so it can be started with .
|
||||
*
|
||||
* @param create
|
||||
* the rollout entity to create
|
||||
* @param amountGroup
|
||||
* the amount of groups to split the rollout into
|
||||
* @param confirmationRequired
|
||||
* if a confirmation is required by the device group(s) of the rollout
|
||||
* @param conditions
|
||||
* the rolloutgroup conditions and actions which should be
|
||||
* applied for each {@link RolloutGroup}
|
||||
* the rolloutgroup conditions and actions which should be applied
|
||||
* for each {@link RolloutGroup}
|
||||
* @return the persisted rollout.
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
@@ -140,22 +141,23 @@ public interface RolloutManagement {
|
||||
* exceeded.
|
||||
*/
|
||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE)
|
||||
Rollout create(@NotNull @Valid RolloutCreate create, int amountGroup, @NotNull RolloutGroupConditions conditions);
|
||||
Rollout create(@NotNull @Valid RolloutCreate create, int amountGroup, boolean confirmationRequired,
|
||||
@NotNull RolloutGroupConditions conditions);
|
||||
|
||||
/**
|
||||
* Persists a new rollout entity. The filter within the
|
||||
* {@link Rollout#getTargetFilterQuery()} is used to filter the targets
|
||||
* which are affected by this rollout. The given groups will be used to
|
||||
* create the groups.
|
||||
* {@link Rollout#getTargetFilterQuery()} is used to filter the targets which
|
||||
* are affected by this rollout. The given groups will be used to create the
|
||||
* groups.
|
||||
*
|
||||
* The rollout is not started. Only the preparation of the rollout is done,
|
||||
* creating and persisting all the necessary groups. The Rollout and the
|
||||
* groups are persisted in {@link RolloutStatus#CREATING} and
|
||||
* creating and persisting all the necessary groups. The Rollout and the groups
|
||||
* are persisted in {@link RolloutStatus#CREATING} and
|
||||
* {@link RolloutGroupStatus#CREATING}.
|
||||
*
|
||||
* The RolloutScheduler will start to assign targets to the groups. Once all
|
||||
* targets have been assigned to the groups, the rollout status is changed
|
||||
* to {@link RolloutStatus#READY} so it can be started with
|
||||
* targets have been assigned to the groups, the rollout status is changed to
|
||||
* {@link RolloutStatus#READY} so it can be started with
|
||||
* {@link #start(Rollout)}.
|
||||
*
|
||||
* @param rollout
|
||||
@@ -163,9 +165,9 @@ public interface RolloutManagement {
|
||||
* @param groups
|
||||
* optional definition of groups
|
||||
* @param conditions
|
||||
* the rollout group conditions and actions which should be
|
||||
* applied for each {@link RolloutGroup} if not defined by the
|
||||
* RolloutGroup itself
|
||||
* the rollout group conditions and actions which should be applied
|
||||
* for each {@link RolloutGroup} if not defined by the RolloutGroup
|
||||
* itself
|
||||
* @return the persisted rollout.
|
||||
*
|
||||
* @throws EntityNotFoundException
|
||||
|
||||
@@ -29,6 +29,8 @@ public class AutoAssignDistributionSetUpdate {
|
||||
@Max(Action.WEIGHT_MAX)
|
||||
private Integer weight;
|
||||
|
||||
private Boolean confirmationRequired;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@@ -75,6 +77,19 @@ public class AutoAssignDistributionSetUpdate {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify initial confirmation state of resulting {@link Action}
|
||||
*
|
||||
* @param confirmationRequired
|
||||
* if confirmation is required for this auto assignment (considered
|
||||
* with confirmation flow active)
|
||||
* @return updated builder instance
|
||||
*/
|
||||
public AutoAssignDistributionSetUpdate confirmationRequired(final boolean confirmationRequired) {
|
||||
this.confirmationRequired = confirmationRequired;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Long getDsId() {
|
||||
return dsId;
|
||||
}
|
||||
@@ -87,6 +102,10 @@ public class AutoAssignDistributionSetUpdate {
|
||||
return weight;
|
||||
}
|
||||
|
||||
public Boolean isConfirmationRequired() {
|
||||
return confirmationRequired;
|
||||
}
|
||||
|
||||
public long getTargetFilterId() {
|
||||
return targetFilterId;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,14 @@ public interface RolloutGroupCreate {
|
||||
*/
|
||||
RolloutGroupCreate conditions(RolloutGroupConditions conditions);
|
||||
|
||||
/**
|
||||
* @param confirmationRequired
|
||||
* if confirmation is required for this rollout group (considered
|
||||
* with confirmation flow active)
|
||||
* @return updated builder instance
|
||||
*/
|
||||
RolloutGroupCreate confirmationRequired(boolean confirmationRequired);
|
||||
|
||||
/**
|
||||
* @return peek on current state of {@link RolloutGroup} in the builder
|
||||
*/
|
||||
|
||||
@@ -83,6 +83,17 @@ public interface TargetFilterQueryCreate {
|
||||
*/
|
||||
TargetFilterQueryCreate autoAssignWeight(Integer weight);
|
||||
|
||||
/**
|
||||
* Specify initial confirmation state of resulting {@link Action} in auto
|
||||
* assignment
|
||||
*
|
||||
* @param confirmationRequired
|
||||
* if confirmation is required for configured auto assignment (considered
|
||||
* with confirmation flow active)
|
||||
* @return updated builder instance
|
||||
*/
|
||||
TargetFilterQueryCreate confirmationRequired(boolean confirmationRequired);
|
||||
|
||||
/**
|
||||
* @return peek on current state of {@link TargetFilterQuery} in the builder
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
|
||||
/**
|
||||
* The {@link AutoConfirmationAlreadyActiveException} is thrown when auto
|
||||
* confirmation is already active for a device but the
|
||||
* {@link org.eclipse.hawkbit.repository.ConfirmationManagement#activateAutoConfirmation}
|
||||
* is getting called.
|
||||
*/
|
||||
public class AutoConfirmationAlreadyActiveException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_AUTO_CONFIRMATION_ALREADY_ACTIVE;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public AutoConfirmationAlreadyActiveException() {
|
||||
super(THIS_ERROR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameterized constructor.
|
||||
*
|
||||
* @param cause
|
||||
* of the exception
|
||||
*/
|
||||
public AutoConfirmationAlreadyActiveException(final Throwable cause) {
|
||||
super(THIS_ERROR, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameterized constructor for auto confirmation is already active for given
|
||||
* controller ID
|
||||
*
|
||||
* @param controllerId
|
||||
* of affected device
|
||||
*/
|
||||
public AutoConfirmationAlreadyActiveException(final String controllerId) {
|
||||
super("Auto confirmation is already active for device " + controllerId, THIS_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.exception;
|
||||
|
||||
import org.eclipse.hawkbit.exception.AbstractServerRtException;
|
||||
import org.eclipse.hawkbit.exception.SpServerError;
|
||||
|
||||
/**
|
||||
* This exception is indicating that the confirmation feedback cannot be
|
||||
* processed for a specific actions for different reasons which are listed as
|
||||
* enum {@link Reason}.
|
||||
*/
|
||||
public class InvalidConfirmationFeedbackException extends AbstractServerRtException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final SpServerError THIS_ERROR = SpServerError.SP_CONFIRMATION_FEEDBACK_INVALID;
|
||||
|
||||
private final Reason reason;
|
||||
|
||||
protected InvalidConfirmationFeedbackException(final Reason reason) {
|
||||
super(THIS_ERROR);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public InvalidConfirmationFeedbackException(final Reason reason, final String message) {
|
||||
super(message, THIS_ERROR);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Reason getReason() {
|
||||
return reason;
|
||||
}
|
||||
|
||||
public enum Reason {
|
||||
ACTION_CLOSED, NOT_AWAITING_CONFIRMATION
|
||||
}
|
||||
}
|
||||
@@ -259,7 +259,12 @@ public interface Action extends TenantAwareBaseEntity {
|
||||
* Action has been downloaded by the target and waiting for update to
|
||||
* start.
|
||||
*/
|
||||
DOWNLOADED
|
||||
DOWNLOADED,
|
||||
|
||||
/**
|
||||
* Action is waiting to be confirmed by the user
|
||||
*/
|
||||
WAIT_FOR_CONFIRMATION
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -330,4 +335,11 @@ public interface Action extends TenantAwareBaseEntity {
|
||||
* @return true if maintenance window is available, else false.
|
||||
*/
|
||||
boolean isMaintenanceWindowAvailable();
|
||||
|
||||
/**
|
||||
* Checks if the action is waiting for confirmation.
|
||||
* @return true if the action is waiting for confirmation, else false
|
||||
*/
|
||||
boolean isWaitingConfirmation();
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
@@ -22,6 +24,8 @@ public class ActionProperties implements Serializable {
|
||||
private String tenant;
|
||||
private boolean maintenanceWindowAvailable;
|
||||
|
||||
private Action.Status status;
|
||||
|
||||
public ActionProperties() {
|
||||
}
|
||||
|
||||
@@ -35,6 +39,7 @@ public class ActionProperties implements Serializable {
|
||||
this.actionType = action.getActionType();
|
||||
this.tenant = action.getTenant();
|
||||
this.maintenanceWindowAvailable = action.isMaintenanceWindowAvailable();
|
||||
this.status = action.getStatus();
|
||||
}
|
||||
|
||||
public void setId(final Long id) {
|
||||
@@ -68,4 +73,13 @@ public class ActionProperties implements Serializable {
|
||||
public void setActionType(final Action.ActionType actionType) {
|
||||
this.actionType = actionType;
|
||||
}
|
||||
|
||||
public Action.Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean isWaitingConfirmation() {
|
||||
return status == Action.Status.WAIT_FOR_CONFIRMATION;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Bosch.IO GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.model;
|
||||
|
||||
/**
|
||||
* {@link AutoConfirmationStatus} of a {@link Target}.
|
||||
*
|
||||
*/
|
||||
public interface AutoConfirmationStatus extends BaseEntity {
|
||||
|
||||
/**
|
||||
* For which target this status is corresponding to.
|
||||
*
|
||||
* @return the {@link Target}
|
||||
*/
|
||||
Target getTarget();
|
||||
|
||||
/**
|
||||
* The user who initiated the auto confirmation. Will be set on auto
|
||||
* confirmation activation and could be null. In this case the created_by can be
|
||||
* considered as initiator.
|
||||
*
|
||||
* @return the user
|
||||
*/
|
||||
String getInitiator();
|
||||
|
||||
/**
|
||||
* Unix timestamp of the activation.
|
||||
*
|
||||
* @return activation time as unix timestamp
|
||||
*/
|
||||
long getActivatedAt();
|
||||
|
||||
/**
|
||||
* Optional value, which can be set during activation.
|
||||
*
|
||||
* @return the remark
|
||||
*/
|
||||
String getRemark();
|
||||
|
||||
/**
|
||||
* Construct the action message based on the current status.
|
||||
*
|
||||
* @return the constructed message which can be used for the action status as a
|
||||
* message
|
||||
*/
|
||||
String constructActionMessage();
|
||||
|
||||
}
|
||||
@@ -25,8 +25,8 @@ public class DeploymentRequest {
|
||||
private final TargetWithActionType targetWithActionType;
|
||||
|
||||
/**
|
||||
* Constructor that also accepts maintenance schedule parameters and checks
|
||||
* for validity of the specified maintenance schedule.
|
||||
* Constructor that also accepts maintenance schedule parameters and checks for
|
||||
* validity of the specified maintenance schedule.
|
||||
*
|
||||
* @param controllerId
|
||||
* for which the action is created.
|
||||
@@ -48,18 +48,30 @@ public class DeploymentRequest {
|
||||
* window, for example 00:30:00 for 30 minutes
|
||||
* @param maintenanceWindowTimeZone
|
||||
* is the time zone specified as +/-hh:mm offset from UTC, for
|
||||
* example +02:00 for CET summer time and +00:00 for UTC. The
|
||||
* start time of a maintenance window calculated based on the
|
||||
* cron expression is relative to this time zone.
|
||||
* example +02:00 for CET summer time and +00:00 for UTC. The start
|
||||
* time of a maintenance window calculated based on the cron
|
||||
* expression is relative to this time zone.
|
||||
*
|
||||
* @param confirmationRequired
|
||||
* is a flag whether the confirmation should be required for the
|
||||
* resulting {@link Action} or not. In case the confirmation is not
|
||||
* required, the action will be automatically confirmed and put in
|
||||
* the
|
||||
* {@link org.eclipse.hawkbit.repository.model.Action.Status#RUNNING}
|
||||
* state. Otherwise the confirmation flow will be triggered
|
||||
* and the {@link Action} will stay in the
|
||||
* {@link org.eclipse.hawkbit.repository.model.Action.Status#WAIT_FOR_CONFIRMATION}
|
||||
* state until the confirmation is given. (Only considered
|
||||
* with CONFIRMATION_FLOW active via tenant configuration)
|
||||
* @throws InvalidMaintenanceScheduleException
|
||||
* if the parameters do not define a valid maintenance schedule.
|
||||
*/
|
||||
public DeploymentRequest(final String controllerId, final Long distributionSetId, final ActionType actionType,
|
||||
final long forceTime, final Integer weight, final String maintenanceSchedule,
|
||||
final String maintenanceWindowDuration, final String maintenanceWindowTimeZone) {
|
||||
final String maintenanceWindowDuration, final String maintenanceWindowTimeZone,
|
||||
final boolean confirmationRequired) {
|
||||
this.targetWithActionType = new TargetWithActionType(controllerId, actionType, forceTime, weight,
|
||||
maintenanceSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
maintenanceSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone, confirmationRequired);
|
||||
this.distributionSetId = distributionSetId;
|
||||
}
|
||||
|
||||
@@ -78,11 +90,11 @@ public class DeploymentRequest {
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"DeploymentRequest [controllerId=%s, distributionSetId=%d, actionType=%s, forceTime=%d, weight=%d, maintenanceSchedule=%s, maintenanceWindowDuration=%s, maintenanceWindowTimeZone=%s]",
|
||||
"DeploymentRequest [controllerId=%s, distributionSetId=%d, actionType=%s, forceTime=%d, weight=%d, maintenanceSchedule=%s, maintenanceWindowDuration=%s, maintenanceWindowTimeZone=%s, confirmationRequired=%s]",
|
||||
targetWithActionType.getControllerId(), getDistributionSetId(), targetWithActionType.getActionType(),
|
||||
targetWithActionType.getForceTime(), targetWithActionType.getWeight(),
|
||||
targetWithActionType.getMaintenanceSchedule(), targetWithActionType.getMaintenanceWindowDuration(),
|
||||
targetWithActionType.getMaintenanceWindowTimeZone());
|
||||
targetWithActionType.getMaintenanceWindowTimeZone(), targetWithActionType.isConfirmationRequired());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -24,6 +24,7 @@ public class DeploymentRequestBuilder {
|
||||
private String maintenanceSchedule;
|
||||
private String maintenanceWindowDuration;
|
||||
private String maintenanceWindowTimeZone;
|
||||
private boolean confirmationRequired;
|
||||
|
||||
/**
|
||||
* Create a builder for a target distribution set assignment with the
|
||||
@@ -100,6 +101,18 @@ public class DeploymentRequestBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if a confirmation is required.
|
||||
*
|
||||
* @param confirmationRequired
|
||||
* if a confirmation is required for the {@link Action}
|
||||
* @return builder
|
||||
*/
|
||||
public DeploymentRequestBuilder setConfirmationRequired(final boolean confirmationRequired) {
|
||||
this.confirmationRequired = confirmationRequired;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* build the request
|
||||
*
|
||||
@@ -107,7 +120,7 @@ public class DeploymentRequestBuilder {
|
||||
*/
|
||||
public DeploymentRequest build() {
|
||||
return new DeploymentRequest(controllerId, distributionSetId, actionType, forceTime, weight,
|
||||
maintenanceSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
maintenanceSchedule, maintenanceWindowDuration, maintenanceWindowTimeZone, confirmationRequired);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -109,6 +109,12 @@ public interface RolloutGroup extends NamedEntity {
|
||||
*/
|
||||
float getTargetPercentage();
|
||||
|
||||
/**
|
||||
* @return if a confirmation is required for the resulting actions (considered
|
||||
* with confirmation flow active only)
|
||||
*/
|
||||
boolean isConfirmationRequired();
|
||||
|
||||
/**
|
||||
* Rollout group state machine.
|
||||
*
|
||||
|
||||
@@ -98,6 +98,14 @@ public interface Target extends NamedEntity {
|
||||
*/
|
||||
PollStatus getPollStatus();
|
||||
|
||||
/**
|
||||
* The auto confirmation status is present, when it's active for the target.
|
||||
* Will only be considered in case the confirmation flow is active.
|
||||
*
|
||||
* @return the {@link AutoConfirmationStatus} if activated
|
||||
*/
|
||||
AutoConfirmationStatus getAutoConfirmationStatus();
|
||||
|
||||
/**
|
||||
* @return <code>true</code> if the {@link Target} has not jet provided
|
||||
* {@link #getControllerAttributes()}.
|
||||
|
||||
@@ -81,4 +81,10 @@ public interface TargetFilterQuery extends TenantAwareBaseEntity {
|
||||
* @return the user that triggered the auto assignment
|
||||
*/
|
||||
String getAutoAssignInitiatedBy();
|
||||
|
||||
/**
|
||||
* @return if confirmation is required for configured auto assignment
|
||||
* (considered with confirmation flow active)
|
||||
*/
|
||||
boolean isConfirmationRequired();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public class TargetWithActionType {
|
||||
private String maintenanceSchedule;
|
||||
private String maintenanceWindowDuration;
|
||||
private String maintenanceWindowTimeZone;
|
||||
private final boolean confirmationRequired;
|
||||
|
||||
/**
|
||||
* Constructor that uses {@link ActionType#FORCED}
|
||||
@@ -38,7 +39,7 @@ public class TargetWithActionType {
|
||||
* ID if the controller
|
||||
*/
|
||||
public TargetWithActionType(final String controllerId) {
|
||||
this(controllerId, ActionType.FORCED, 0, null);
|
||||
this(controllerId, ActionType.FORCED, 0, null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,17 +50,22 @@ public class TargetWithActionType {
|
||||
* @param actionType
|
||||
* specified for the action.
|
||||
* @param forceTime
|
||||
* after that point in time the action is exposed as forced in
|
||||
* case the type is {@link ActionType#TIMEFORCED}
|
||||
* after that point in time the action is exposed as forced in case
|
||||
* the type is {@link ActionType#TIMEFORCED}
|
||||
* @param weight
|
||||
* the priority of an {@link Action}
|
||||
* @param confirmationRequired
|
||||
* sets the confirmation required flag when starting the
|
||||
* {@link Action}
|
||||
*/
|
||||
public TargetWithActionType(final String controllerId, final ActionType actionType, final long forceTime,
|
||||
final Integer weight) {
|
||||
public TargetWithActionType(
|
||||
final String controllerId, final ActionType actionType, final long forceTime,
|
||||
final Integer weight, final boolean confirmationRequired) {
|
||||
this.controllerId = controllerId;
|
||||
this.actionType = actionType != null ? actionType : ActionType.FORCED;
|
||||
this.forceTime = forceTime;
|
||||
this.weight = weight;
|
||||
this.confirmationRequired = confirmationRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,8 +99,8 @@ public class TargetWithActionType {
|
||||
*/
|
||||
public TargetWithActionType(final String controllerId, final ActionType actionType, final long forceTime,
|
||||
final Integer weight, final String maintenanceSchedule, final String maintenanceWindowDuration,
|
||||
final String maintenanceWindowTimeZone) {
|
||||
this(controllerId, actionType, forceTime, weight);
|
||||
final String maintenanceWindowTimeZone, final boolean confirmationRequired) {
|
||||
this(controllerId, actionType, forceTime, weight, confirmationRequired);
|
||||
|
||||
this.maintenanceSchedule = maintenanceSchedule;
|
||||
this.maintenanceWindowDuration = maintenanceWindowDuration;
|
||||
@@ -152,18 +158,27 @@ public class TargetWithActionType {
|
||||
return maintenanceWindowTimeZone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if a confirmation is required for this assignment (depends on confirmation flow active)
|
||||
*
|
||||
* @return the flag
|
||||
*/
|
||||
public boolean isConfirmationRequired() {
|
||||
return confirmationRequired;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TargetWithActionType [controllerId=" + controllerId + ", actionType=" + getActionType() + ", forceTime="
|
||||
+ getForceTime() + ", weight=" + getWeight() + ", maintenanceSchedule=" + getMaintenanceSchedule()
|
||||
+ ", maintenanceWindowDuration=" + getMaintenanceWindowDuration() + ", maintenanceWindowTimeZone="
|
||||
+ getMaintenanceWindowTimeZone() + "]";
|
||||
+ getMaintenanceWindowTimeZone() + ", confirmationRequired=" + isConfirmationRequired() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(actionType, controllerId, forceTime, weight, maintenanceSchedule, maintenanceWindowDuration,
|
||||
maintenanceWindowTimeZone);
|
||||
return Objects.hash(actionType, controllerId, forceTime, weight, confirmationRequired, maintenanceSchedule,
|
||||
maintenanceWindowDuration, maintenanceWindowTimeZone);
|
||||
}
|
||||
|
||||
@SuppressWarnings("squid:S1067")
|
||||
@@ -181,8 +196,10 @@ public class TargetWithActionType {
|
||||
final TargetWithActionType other = (TargetWithActionType) obj;
|
||||
return Objects.equals(actionType, other.actionType) && Objects.equals(controllerId, other.controllerId)
|
||||
&& Objects.equals(forceTime, other.forceTime) && Objects.equals(weight, other.weight)
|
||||
&& Objects.equals(confirmationRequired, other.confirmationRequired)
|
||||
&& Objects.equals(maintenanceSchedule, other.maintenanceSchedule)
|
||||
&& Objects.equals(maintenanceWindowDuration, other.maintenanceWindowDuration)
|
||||
&& Objects.equals(maintenanceWindowTimeZone, other.maintenanceWindowTimeZone);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -161,6 +161,7 @@ public class TotalTargetCountStatus {
|
||||
case RUNNING:
|
||||
case WARNING:
|
||||
case DOWNLOAD:
|
||||
case WAIT_FOR_CONFIRMATION:
|
||||
case CANCELING:
|
||||
return Status.RUNNING;
|
||||
case DOWNLOADED:
|
||||
|
||||
@@ -152,6 +152,11 @@ public class TenantConfigurationProperties {
|
||||
*/
|
||||
public static final String BATCH_ASSIGNMENTS_ENABLED = "batch.assignments.enabled";
|
||||
|
||||
/**
|
||||
* Switch to enable/disable the user-confirmation flow
|
||||
*/
|
||||
public static final String USER_CONFIRMATION_ENABLED = "user.confirmation.flow.enabled";
|
||||
|
||||
private String keyName;
|
||||
private String defaultValue = "";
|
||||
private Class<?> dataType = String.class;
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) 2019 Bosch Software Innovations GmbH and others.
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*/
|
||||
package org.eclipse.hawkbit.utils;
|
||||
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.MULTI_ASSIGNMENTS_ENABLED;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.USER_CONFIRMATION_ENABLED;
|
||||
|
||||
import org.eclipse.hawkbit.repository.TenantConfigurationManagement;
|
||||
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||
|
||||
/**
|
||||
* A collection of static helper methods for the tenant configuration
|
||||
*/
|
||||
public final class TenantConfigHelper {
|
||||
|
||||
private final TenantConfigurationManagement tenantConfigurationManagement;
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
|
||||
private TenantConfigHelper(final SystemSecurityContext systemSecurityContext,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
this.tenantConfigurationManagement = tenantConfigurationManagement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting the context of the tenant.
|
||||
*
|
||||
* @param systemSecurityContext
|
||||
* Security context used to get the tenant and for execution
|
||||
* @param tenantConfigurationManagement
|
||||
* to get the value from
|
||||
* @return is active
|
||||
*/
|
||||
public static TenantConfigHelper usingContext(final SystemSecurityContext systemSecurityContext,
|
||||
final TenantConfigurationManagement tenantConfigurationManagement) {
|
||||
return new TenantConfigHelper(systemSecurityContext, tenantConfigurationManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is multi-assignments enabled for the current tenant
|
||||
*
|
||||
* @return is active
|
||||
*/
|
||||
public boolean isMultiAssignmentsEnabled() {
|
||||
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement
|
||||
.getConfigurationValue(MULTI_ASSIGNMENTS_ENABLED, Boolean.class).getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Is confirmation flow enabled for the current tenant
|
||||
*
|
||||
* @return is enabled
|
||||
*/
|
||||
public boolean isConfirmationFlowEnabled() {
|
||||
return systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement
|
||||
.getConfigurationValue(USER_CONFIRMATION_ENABLED, Boolean.class).getValue());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user