Move rollout executor related target management methods in executor (#2812)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -9,6 +9,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository;
|
package org.eclipse.hawkbit.repository;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_ROLLOUT;
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpPermission.DISTRIBUTION_SET;
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpPermission.HANDLE_ROLLOUT;
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpPermission.ROLLOUT;
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_ROLLOUT;
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_READ_REPOSITORY;
|
||||||
|
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UPDATE_REPOSITORY;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -50,7 +58,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
*/
|
*/
|
||||||
public interface DeploymentManagement extends PermissionSupport {
|
public interface DeploymentManagement extends PermissionSupport {
|
||||||
|
|
||||||
String HAS_UPDATE_TARGET_AND_READ_DISTRIBUTION_SET = SpringEvalExpressions.HAS_UPDATE_REPOSITORY + " and hasAuthority('READ_" + SpPermission.DISTRIBUTION_SET + "')";
|
String HAS_UPDATE_TARGET_AND_READ_DISTRIBUTION_SET = HAS_UPDATE_REPOSITORY + " and hasPermission(#root, 'READ_" + DISTRIBUTION_SET + "')";
|
||||||
|
String HAS_UPDATE_TARGET_OR_CREATE_UPDATE_ROLLOUT = HAS_UPDATE_REPOSITORY + " or hasPermission(#root, '" + CREATE_ROLLOUT + "')" + " or hasPermission(#root, '" + UPDATE_ROLLOUT + "')";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String permissionGroup() {
|
default String permissionGroup() {
|
||||||
@@ -129,7 +138,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @throws CancelActionNotAllowedException in case the given action is not active or is already a cancel action
|
* @throws CancelActionNotAllowedException in case the given action is not active or is already a cancel action
|
||||||
* @throws EntityNotFoundException if action with given ID does not exist
|
* @throws EntityNotFoundException if action with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_REPOSITORY)
|
||||||
Action cancelAction(long actionId);
|
Action cancelAction(long actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -143,7 +152,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
||||||
* @throws EntityNotFoundException if target with given ID does not exist
|
* @throws EntityNotFoundException if target with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
long countActionsByTarget(@NotNull String rsql, @NotEmpty String controllerId);
|
long countActionsByTarget(@NotNull String rsql, @NotEmpty String controllerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,7 +160,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
*
|
*
|
||||||
* @return the total amount of stored actions
|
* @return the total amount of stored actions
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
long countActionsAll();
|
long countActionsAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,7 +169,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param rsql RSQL query.
|
* @param rsql RSQL query.
|
||||||
* @return the total number of actions matching the given RSQL query.
|
* @return the total number of actions matching the given RSQL query.
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
long countActions(@NotNull String rsql);
|
long countActions(@NotNull String rsql);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -170,7 +179,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @return the count value of found actions associated to the target
|
* @return the count value of found actions associated to the target
|
||||||
* @throws EntityNotFoundException if target with given ID does not exist
|
* @throws EntityNotFoundException if target with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
long countActionsByTarget(@NotEmpty String controllerId);
|
long countActionsByTarget(@NotEmpty String controllerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,7 +188,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param actionId to be id of the action
|
* @param actionId to be id of the action
|
||||||
* @return the corresponding {@link Action}
|
* @return the corresponding {@link Action}
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Optional<Action> findAction(long actionId);
|
Optional<Action> findAction(long actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,7 +197,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param pageable pagination parameter
|
* @param pageable pagination parameter
|
||||||
* @return a paged list of {@link Action}s
|
* @return a paged list of {@link Action}s
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Slice<Action> findActionsAll(@NotNull Pageable pageable);
|
Slice<Action> findActionsAll(@NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,7 +207,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param pageable the page request parameter for paging and sorting the result
|
* @param pageable the page request parameter for paging and sorting the result
|
||||||
* @return a paged list of {@link Action}s.
|
* @return a paged list of {@link Action}s.
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Slice<Action> findActions(@NotNull String rsql, @NotNull Pageable pageable);
|
Slice<Action> findActions(@NotNull String rsql, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -212,7 +221,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* given {@code fieldNameProvider}
|
* given {@code fieldNameProvider}
|
||||||
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Slice<Action> findActionsByTarget(@NotNull String rsql, @NotEmpty String controllerId, @NotNull Pageable pageable);
|
Slice<Action> findActionsByTarget(@NotNull String rsql, @NotEmpty String controllerId, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,7 +231,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param pageable the pageable request to limit, sort the actions
|
* @param pageable the pageable request to limit, sort the actions
|
||||||
* @return a slice of actions found for a specific target
|
* @return a slice of actions found for a specific target
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Slice<Action> findActionsByTarget(@NotEmpty String controllerId, @NotNull Pageable pageable);
|
Slice<Action> findActionsByTarget(@NotEmpty String controllerId, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -233,7 +242,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @return the corresponding {@link Page} of {@link ActionStatus}
|
* @return the corresponding {@link Page} of {@link ActionStatus}
|
||||||
* @throws EntityNotFoundException if action with given ID does not exist
|
* @throws EntityNotFoundException if action with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Page<ActionStatus> findActionStatusByAction(long actionId, @NotNull Pageable pageable);
|
Page<ActionStatus> findActionStatusByAction(long actionId, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,7 +252,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param pageable the page request parameter for paging and sorting the result
|
* @param pageable the page request parameter for paging and sorting the result
|
||||||
* @return a page of messages by a specific {@link ActionStatus} id
|
* @return a page of messages by a specific {@link ActionStatus} id
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Page<String> findMessagesByActionStatusId(long actionStatusId, @NotNull Pageable pageable);
|
Page<String> findMessagesByActionStatusId(long actionStatusId, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,7 +261,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param actionId to be id of the action
|
* @param actionId to be id of the action
|
||||||
* @return the corresponding {@link Action}
|
* @return the corresponding {@link Action}
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Optional<Action> findActionWithDetails(long actionId);
|
Optional<Action> findActionWithDetails(long actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -263,7 +272,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @return a list of actions associated with the given target
|
* @return a list of actions associated with the given target
|
||||||
* @throws EntityNotFoundException if target with given ID does not exist
|
* @throws EntityNotFoundException if target with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Page<Action> findActiveActionsByTarget(@NotEmpty String controllerId, @NotNull Pageable pageable);
|
Page<Action> findActiveActionsByTarget(@NotEmpty String controllerId, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -273,7 +282,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param maxActionCount max size of returned list
|
* @param maxActionCount max size of returned list
|
||||||
* @return the action
|
* @return the action
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
List<Action> findActiveActionsWithHighestWeight(@NotEmpty String controllerId, int maxActionCount);
|
List<Action> findActiveActionsWithHighestWeight(@NotEmpty String controllerId, int maxActionCount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -285,7 +294,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @throws CancelActionNotAllowedException in case the given action is not active
|
* @throws CancelActionNotAllowedException in case the given action is not active
|
||||||
* @throws EntityNotFoundException if action with given ID does not exist
|
* @throws EntityNotFoundException if action with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_REPOSITORY)
|
||||||
Action forceQuitAction(long actionId);
|
Action forceQuitAction(long actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -295,11 +304,12 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @return the updated or the found {@link Action}
|
* @return the updated or the found {@link Action}
|
||||||
* @throws EntityNotFoundException if action with given ID does not exist
|
* @throws EntityNotFoundException if action with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_REPOSITORY)
|
||||||
Action forceTargetAction(long actionId);
|
Action forceTargetAction(long actionId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes the current action by id.
|
* Deletes the current action by id.
|
||||||
|
*
|
||||||
* @param actionId - action id
|
* @param actionId - action id
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasAuthority('UPDATE_" + SpPermission.TARGET + "')")
|
@PreAuthorize("hasAuthority('UPDATE_" + SpPermission.TARGET + "')")
|
||||||
@@ -307,6 +317,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes actions matching the provided rsql filter
|
* Deletes actions matching the provided rsql filter
|
||||||
|
*
|
||||||
* @param rsql - rsql filter for actions to be deleted
|
* @param rsql - rsql filter for actions to be deleted
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasAuthority('UPDATE_" + SpPermission.TARGET + "')")
|
@PreAuthorize("hasAuthority('UPDATE_" + SpPermission.TARGET + "')")
|
||||||
@@ -314,6 +325,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes actions present in provided list of ids
|
* Deletes actions present in provided list of ids
|
||||||
|
*
|
||||||
* @param actionIds - list of action ids to be deleted
|
* @param actionIds - list of action ids to be deleted
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasAuthority('UPDATE_" + SpPermission.TARGET + "')")
|
@PreAuthorize("hasAuthority('UPDATE_" + SpPermission.TARGET + "')")
|
||||||
@@ -342,7 +354,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
*
|
*
|
||||||
* @param targetIds ids of the {@link Target}s the actions belong to
|
* @param targetIds ids of the {@link Target}s the actions belong to
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_TARGET_OR_CREATE_UPDATE_ROLLOUT)
|
||||||
void cancelInactiveScheduledActionsForTargets(List<Long> targetIds);
|
void cancelInactiveScheduledActionsForTargets(List<Long> targetIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -352,7 +364,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param distributionSetId to assign
|
* @param distributionSetId to assign
|
||||||
* @param rolloutGroupParentId the parent rollout group the actions should reference. null references the first group
|
* @param rolloutGroupParentId the parent rollout group the actions should reference. null references the first group
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_TARGET_OR_CREATE_UPDATE_ROLLOUT)
|
||||||
void startScheduledActionsByRolloutGroupParent(long rolloutId, long distributionSetId, Long rolloutGroupParentId);
|
void startScheduledActionsByRolloutGroupParent(long rolloutId, long distributionSetId, Long rolloutGroupParentId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -360,7 +372,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
*
|
*
|
||||||
* @param rolloutGroupActions rollouts group actions part of a same group
|
* @param rolloutGroupActions rollouts group actions part of a same group
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_TARGET_OR_CREATE_UPDATE_ROLLOUT)
|
||||||
void startScheduledActions(final List<Action> rolloutGroupActions);
|
void startScheduledActions(final List<Action> rolloutGroupActions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,7 +382,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @return assigned {@link DistributionSet}
|
* @return assigned {@link DistributionSet}
|
||||||
* @throws EntityNotFoundException if target with given ID does not exist
|
* @throws EntityNotFoundException if target with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Optional<DistributionSet> findAssignedDistributionSet(@NotEmpty String controllerId);
|
Optional<DistributionSet> findAssignedDistributionSet(@NotEmpty String controllerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -380,7 +392,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @return installed {@link DistributionSet}
|
* @return installed {@link DistributionSet}
|
||||||
* @throws EntityNotFoundException if target with given ID does not exist
|
* @throws EntityNotFoundException if target with given ID does not exist
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
Optional<DistributionSet> findInstalledDistributionSet(@NotEmpty String controllerId);
|
Optional<DistributionSet> findInstalledDistributionSet(@NotEmpty String controllerId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -400,7 +412,7 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param targetId of target
|
* @param targetId of target
|
||||||
* @return if actions in CANCELING state are present
|
* @return if actions in CANCELING state are present
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
|
@PreAuthorize(HAS_READ_REPOSITORY)
|
||||||
boolean hasPendingCancellations(@NotNull Long targetId);
|
boolean hasPendingCancellations(@NotNull Long targetId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -409,9 +421,9 @@ public interface DeploymentManagement extends PermissionSupport {
|
|||||||
* @param cancelationType defines if a force or soft cancel is executed
|
* @param cancelationType defines if a force or soft cancel is executed
|
||||||
* @param set the distribution set for that the actions should be canceled
|
* @param set the distribution set for that the actions should be canceled
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
|
@PreAuthorize(HAS_UPDATE_REPOSITORY)
|
||||||
void cancelActionsForDistributionSet(final ActionCancellationType cancelationType, final DistributionSet set);
|
void cancelActionsForDistributionSet(final ActionCancellationType cancelationType, final DistributionSet set);
|
||||||
|
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY + " or " + SpringEvalExpressions.IS_SYSTEM_CODE)
|
@PreAuthorize(HAS_UPDATE_REPOSITORY + " or " + SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||||
void handleMaxAssignmentsExceeded(Long targetId, Long requested, AssignmentQuotaExceededException quotaExceededException);
|
void handleMaxAssignmentsExceeded(Long targetId, Long requested, AssignmentQuotaExceededException quotaExceededException);
|
||||||
}
|
}
|
||||||
@@ -57,8 +57,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
*/
|
*/
|
||||||
public interface RolloutManagement extends PermissionSupport {
|
public interface RolloutManagement extends PermissionSupport {
|
||||||
|
|
||||||
String HAS_ROLLOUT_APPROVE = "hasPermission(#root, 'APPROVE')";
|
String HAS_ROLLOUT_APPROVE = "hasPermission(#root, 'APPROVE_${permissionGroup}')";
|
||||||
String HAS_ROLLOUT_HANDLE = "hasPermission(#root, 'HANDLE')";
|
String HAS_ROLLOUT_HANDLE = "hasPermission(#root, 'HANDLE_${permissionGroup}')";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default String permissionGroup() {
|
default String permissionGroup() {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldExc
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
@@ -144,49 +143,6 @@ public interface TargetManagement<T extends Target>
|
|||||||
Slice<Target> findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(
|
Slice<Target> findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(
|
||||||
long distributionSetId, @NotNull String rsql, @NotNull Pageable pageable);
|
long distributionSetId, @NotNull String rsql, @NotNull Pageable pageable);
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s
|
|
||||||
* and are compatible with the passed {@link DistributionSetType}.
|
|
||||||
*
|
|
||||||
* @param groups the list of {@link RolloutGroup}s
|
|
||||||
* @param rsql filter definition in RSQL syntax
|
|
||||||
* @param distributionSetType type of the {@link DistributionSet} the targets must be compatible withs
|
|
||||||
* @param pageable the pageable to enhance the query for paging and sorting
|
|
||||||
* @return a page of the found {@link Target}s
|
|
||||||
*/
|
|
||||||
@PreAuthorize(HAS_UPDATE_TARGET_AND_READ_ROLLOUT)
|
|
||||||
Slice<Target> findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
|
||||||
@NotEmpty Collection<Long> groups, @NotNull String rsql, @NotNull DistributionSetType distributionSetType,
|
|
||||||
@NotNull Pageable pageable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds all targets with failed actions for specific Rollout and that are not assigned to one of the retried {@link RolloutGroup}s and
|
|
||||||
* are compatible with the passed {@link DistributionSetType}.
|
|
||||||
*
|
|
||||||
* @param rolloutId rolloutId of the rollout to be retried.
|
|
||||||
* @param groups the list of {@link RolloutGroup}s
|
|
||||||
* @param pageable the pageable to enhance the query for paging and sorting
|
|
||||||
* @return a page of the found {@link Target}s
|
|
||||||
*/
|
|
||||||
@PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT)
|
|
||||||
Slice<Target> findByFailedRolloutAndNotInRolloutGroups(
|
|
||||||
@NotNull String rolloutId, @NotEmpty Collection<Long> groups, @NotNull Pageable pageable);
|
|
||||||
|
|
||||||
@PreAuthorize(HAS_UPDATE_TARGET_AND_READ_ROLLOUT)
|
|
||||||
Slice<Target> findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
|
||||||
final long rolloutId, @NotNull String rsql, @NotNull DistributionSetType distributionSetType, @NotNull Pageable pageable);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finds all targets of the provided {@link RolloutGroup} that have no Action for the RolloutGroup.
|
|
||||||
*
|
|
||||||
* @param group the {@link RolloutGroup}
|
|
||||||
* @param pageable the pageable to enhance the query for paging and sorting
|
|
||||||
* @return the found {@link Target}s
|
|
||||||
* @throws EntityNotFoundException if rollout group with given ID does not exist
|
|
||||||
*/
|
|
||||||
@PreAuthorize(HAS_READ_REPOSITORY)
|
|
||||||
Slice<Target> findByInRolloutGroupWithoutAction(long group, @NotNull Pageable pageable);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves {@link Target}s by the assigned {@link DistributionSet}.
|
* Retrieves {@link Target}s by the assigned {@link DistributionSet}.
|
||||||
*
|
*
|
||||||
@@ -299,33 +255,6 @@ public interface TargetManagement<T extends Target>
|
|||||||
@PreAuthorize(HAS_UPDATE_TARGET_AND_READ_DISTRIBUTION_SET)
|
@PreAuthorize(HAS_UPDATE_TARGET_AND_READ_DISTRIBUTION_SET)
|
||||||
long countByRsqlAndNonDsAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsql);
|
long countByRsqlAndNonDsAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsql);
|
||||||
|
|
||||||
/**
|
|
||||||
* Counts all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s
|
|
||||||
* and are compatible with the passed {@link DistributionSetType}.
|
|
||||||
*
|
|
||||||
* @param rsql filter definition in RSQL syntax
|
|
||||||
* @param groups the list of {@link RolloutGroup}s
|
|
||||||
* @param distributionSetType type of the {@link DistributionSet} the targets must be compatible with
|
|
||||||
* @return count of the found {@link Target}s
|
|
||||||
*/
|
|
||||||
@PreAuthorize(HAS_UPDATE_TARGET_AND_READ_ROLLOUT)
|
|
||||||
long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
|
||||||
@NotNull String rsql, @NotEmpty Collection<Long> groups, @NotNull DistributionSetType distributionSetType);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Counts all targets with failed actions for specific Rollout and that are not assigned to one of the {@link RolloutGroup}s and are
|
|
||||||
* compatible with the passed {@link DistributionSetType}.
|
|
||||||
*
|
|
||||||
* @param rolloutId rolloutId of the rollout to be retried.
|
|
||||||
* @param groups the list of {@link RolloutGroup}s
|
|
||||||
* @return count of the found {@link Target}s
|
|
||||||
*/
|
|
||||||
@PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT)
|
|
||||||
long countByFailedRolloutAndNotInRolloutGroups(@NotNull String rolloutId, @NotEmpty Collection<Long> groups);
|
|
||||||
|
|
||||||
@PreAuthorize(HAS_READ_TARGET_AND_READ_ROLLOUT)
|
|
||||||
long countByActionsInRolloutGroup(final long rolloutGroupId);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes target with the given controller ID.
|
* Deletes target with the given controller ID.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import java.util.Optional;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.hawkbit.im.authentication.Hierarchy;
|
import org.eclipse.hawkbit.im.authentication.Hierarchy;
|
||||||
|
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties;
|
import org.eclipse.hawkbit.tenancy.configuration.ControllerPollProperties;
|
||||||
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -46,7 +47,8 @@ public class RepositoryConfiguration {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ConditionalOnMissingBean
|
@ConditionalOnMissingBean
|
||||||
@SuppressWarnings("java:S3358") // java:S3358 better readable this way
|
@SuppressWarnings("java:S3358")
|
||||||
|
// java:S3358 better readable this way
|
||||||
RoleHierarchy roleHierarchy(
|
RoleHierarchy roleHierarchy(
|
||||||
// if configured replaces the hierarchy completely
|
// if configured replaces the hierarchy completely
|
||||||
@Value("${hawkbit.hierarchy:}") final String hierarchy,
|
@Value("${hawkbit.hierarchy:}") final String hierarchy,
|
||||||
@@ -66,15 +68,15 @@ public class RepositoryConfiguration {
|
|||||||
public boolean hasPermission(final Authentication authentication, final Object targetDomainObject, final Object permission) {
|
public boolean hasPermission(final Authentication authentication, final Object targetDomainObject, final Object permission) {
|
||||||
if (targetDomainObject instanceof MethodSecurityExpressionOperations root &&
|
if (targetDomainObject instanceof MethodSecurityExpressionOperations root &&
|
||||||
root.getThis() instanceof PermissionSupport permissionSupport) {
|
root.getThis() instanceof PermissionSupport permissionSupport) {
|
||||||
final String neededPermission = permission + "_" + permissionSupport.permissionGroup();
|
final String neededPermission = String.valueOf(permission)
|
||||||
|
.replace(SpringEvalExpressions.PERMISSION_GROUP_PLACEHOLDER, permissionSupport.permissionGroup());
|
||||||
|
|
||||||
// do permissions check
|
// do permissions check
|
||||||
final boolean hasPermission = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()).stream()
|
final boolean hasPermission = roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities()).stream()
|
||||||
.map(GrantedAuthority::getAuthority)
|
.map(GrantedAuthority::getAuthority)
|
||||||
.anyMatch(authority -> authority.equals(neededPermission));
|
.anyMatch(authority -> authority.equals(neededPermission));
|
||||||
if (!hasPermission) {
|
if (!hasPermission) {
|
||||||
log.debug(
|
log.debug("User {} does not have permission {} for target {}",
|
||||||
"User {} does not have permission {} for target {}",
|
|
||||||
authentication.getName(), neededPermission, targetDomainObject);
|
authentication.getName(), neededPermission, targetDomainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -473,11 +473,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT);
|
final PageRequest pageRequest = PageRequest.of(0, ACTION_PAGE_LIMIT);
|
||||||
final Page<Action> groupScheduledActions;
|
final Page<Action> groupScheduledActions;
|
||||||
if (rolloutGroupParentId == null) {
|
if (rolloutGroupParentId == null) {
|
||||||
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(pageRequest, rolloutId,
|
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIsNullAndStatus(
|
||||||
Action.Status.SCHEDULED);
|
pageRequest, rolloutId, Action.Status.SCHEDULED);
|
||||||
} else {
|
} else {
|
||||||
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(pageRequest, rolloutId,
|
groupScheduledActions = actionRepository.findByRolloutIdAndRolloutGroupParentIdAndStatus(
|
||||||
rolloutGroupParentId, Action.Status.SCHEDULED);
|
pageRequest, rolloutId, rolloutGroupParentId, Action.Status.SCHEDULED);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (groupScheduledActions.getContent().isEmpty()) {
|
if (groupScheduledActions.getContent().isEmpty()) {
|
||||||
@@ -493,8 +493,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
@Override
|
@Override
|
||||||
public void startScheduledActions(final List<Action> rolloutGroupActions) {
|
public void startScheduledActions(final List<Action> rolloutGroupActions) {
|
||||||
// Close actions already assigned and collect pending assignments
|
// Close actions already assigned and collect pending assignments
|
||||||
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream().map(JpaAction.class::cast)
|
final List<JpaAction> pendingTargetAssignments = rolloutGroupActions.stream()
|
||||||
.map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull).toList();
|
.map(JpaAction.class::cast).map(this::closeActionIfSetWasAlreadyAssigned).filter(Objects::nonNull).toList();
|
||||||
if (pendingTargetAssignments.isEmpty()) {
|
if (pendingTargetAssignments.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -987,10 +987,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
final JpaTarget target = action.getTarget();
|
final JpaTarget target = action.getTarget();
|
||||||
if (target.getAssignedDistributionSet() != null && action.getDistributionSet().getId()
|
if (target.getAssignedDistributionSet() != null && action.getDistributionSet().getId()
|
||||||
.equals(target.getAssignedDistributionSet().getId())) {
|
.equals(target.getAssignedDistributionSet().getId())) {
|
||||||
// the target has already the distribution set assigned, we don't
|
// the target has already the distribution set assigned, we don't need to start the scheduled action, just finish it.
|
||||||
// need to start the scheduled action, just finish it.
|
log.debug("Target {} has distribution set {} assigned. Closing action...",
|
||||||
log.debug("Target {} has distribution set {} assigned. Closing action...", target.getControllerId(),
|
target.getControllerId(), action.getDistributionSet().getName());
|
||||||
action.getDistributionSet().getName());
|
|
||||||
action.setStatus(Status.FINISHED);
|
action.setStatus(Status.FINISHED);
|
||||||
action.setActive(false);
|
action.setActive(false);
|
||||||
setSkipActionStatus(action);
|
setSkipActionStatus(action);
|
||||||
@@ -1023,8 +1022,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
|||||||
private List<JpaAction> activateActionsOfRolloutGroup(final List<JpaAction> actions) {
|
private List<JpaAction> activateActionsOfRolloutGroup(final List<JpaAction> actions) {
|
||||||
actions.forEach(action -> {
|
actions.forEach(action -> {
|
||||||
action.setActive(true);
|
action.setActive(true);
|
||||||
final boolean confirmationRequired = action.getRolloutGroup().isConfirmationRequired() && action.getTarget()
|
final boolean confirmationRequired = action.getRolloutGroup().isConfirmationRequired() &&
|
||||||
.getAutoConfirmationStatus() == null;
|
action.getTarget().getAutoConfirmationStatus() == null;
|
||||||
if (isConfirmationFlowEnabled() && confirmationRequired) {
|
if (isConfirmationFlowEnabled() && confirmationRequired) {
|
||||||
action.setStatus(Status.WAIT_FOR_CONFIRMATION);
|
action.setStatus(Status.WAIT_FOR_CONFIRMATION);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -46,15 +46,12 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
|||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.TargetTagRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.TargetTypeRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
import org.eclipse.hawkbit.repository.qfields.TargetFields;
|
import org.eclipse.hawkbit.repository.qfields.TargetFields;
|
||||||
@@ -84,7 +81,6 @@ public class JpaTargetManagement
|
|||||||
private final JpaDistributionSetManagement distributionSetManagement;
|
private final JpaDistributionSetManagement distributionSetManagement;
|
||||||
private final QuotaManagement quotaManagement;
|
private final QuotaManagement quotaManagement;
|
||||||
private final TargetTypeRepository targetTypeRepository;
|
private final TargetTypeRepository targetTypeRepository;
|
||||||
private final RolloutGroupRepository rolloutGroupRepository;
|
|
||||||
private final TargetTagRepository targetTagRepository;
|
private final TargetTagRepository targetTagRepository;
|
||||||
|
|
||||||
@SuppressWarnings("java:S107")
|
@SuppressWarnings("java:S107")
|
||||||
@@ -92,13 +88,11 @@ public class JpaTargetManagement
|
|||||||
final TargetRepository jpaRepository, final EntityManager entityManager,
|
final TargetRepository jpaRepository, final EntityManager entityManager,
|
||||||
final JpaDistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
final JpaDistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
|
||||||
final TargetTypeRepository targetTypeRepository,
|
final TargetTypeRepository targetTypeRepository,
|
||||||
final RolloutGroupRepository rolloutGroupRepository,
|
|
||||||
final TargetTagRepository targetTagRepository) {
|
final TargetTagRepository targetTagRepository) {
|
||||||
super(jpaRepository, entityManager);
|
super(jpaRepository, entityManager);
|
||||||
this.distributionSetManagement = distributionSetManagement;
|
this.distributionSetManagement = distributionSetManagement;
|
||||||
this.quotaManagement = quotaManagement;
|
this.quotaManagement = quotaManagement;
|
||||||
this.targetTypeRepository = targetTypeRepository;
|
this.targetTypeRepository = targetTypeRepository;
|
||||||
this.rolloutGroupRepository = rolloutGroupRepository;
|
|
||||||
this.targetTagRepository = targetTagRepository;
|
this.targetTagRepository = targetTagRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,50 +156,6 @@ public class JpaTargetManagement
|
|||||||
.map(Target.class::cast);
|
.map(Target.class::cast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Slice<Target> findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
|
||||||
final Collection<Long> groups, final String rsql, final DistributionSetType dsType, final Pageable pageable) {
|
|
||||||
return jpaRepository
|
|
||||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
|
||||||
combineWithAnd(List.of(
|
|
||||||
QLSupport.getInstance().buildSpec(rsql, TargetFields.class),
|
|
||||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
|
||||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))),
|
|
||||||
pageable)
|
|
||||||
.map(Target.class::cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Slice<Target> findByFailedRolloutAndNotInRolloutGroups(String rolloutId, Collection<Long> groups, Pageable pageable) {
|
|
||||||
final List<Specification<JpaTarget>> specList = List.of(
|
|
||||||
TargetSpecifications.failedActionsForRollout(rolloutId),
|
|
||||||
TargetSpecifications.isNotInRolloutGroups(groups));
|
|
||||||
return JpaManagementHelper.findAllWithCountBySpec(jpaRepository, specList, pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Slice<Target> findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
|
||||||
final long rolloutId, final String rsql, final DistributionSetType distributionSetType, final Pageable pageable) {
|
|
||||||
return jpaRepository
|
|
||||||
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
|
||||||
combineWithAnd(List.of(
|
|
||||||
QLSupport.getInstance().buildSpec(rsql, TargetFields.class),
|
|
||||||
TargetSpecifications.hasNoOverridingActionsAndNotInRollout(rolloutId),
|
|
||||||
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetType.getId()))),
|
|
||||||
pageable)
|
|
||||||
.map(Target.class::cast);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Slice<Target> findByInRolloutGroupWithoutAction(final long group, final Pageable pageable) {
|
|
||||||
if (!rolloutGroupRepository.existsById(group)) {
|
|
||||||
throw new EntityNotFoundException(RolloutGroup.class, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
return JpaManagementHelper.findAllWithoutCountBySpec(
|
|
||||||
jpaRepository, List.of(TargetSpecifications.hasNoActionInRolloutGroup(group)), pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Page<Target> findByAssignedDistributionSet(final long distributionSetId, final Pageable pageable) {
|
public Page<Target> findByAssignedDistributionSet(final long distributionSetId, final Pageable pageable) {
|
||||||
final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId);
|
final DistributionSet validDistSet = distributionSetManagement.get(distributionSetId);
|
||||||
@@ -289,29 +239,6 @@ public class JpaTargetManagement
|
|||||||
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))));
|
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
|
||||||
final String rsql, final Collection<Long> groups, final DistributionSetType dsType) {
|
|
||||||
return jpaRepository.count(AccessController.Operation.UPDATE,
|
|
||||||
combineWithAnd(List.of(
|
|
||||||
QLSupport.getInstance().buildSpec(rsql, TargetFields.class),
|
|
||||||
TargetSpecifications.isNotInRolloutGroups(groups),
|
|
||||||
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long countByFailedRolloutAndNotInRolloutGroups(String rolloutId, Collection<Long> groups) {
|
|
||||||
final List<Specification<JpaTarget>> specList = List.of(
|
|
||||||
TargetSpecifications.failedActionsForRollout(rolloutId),
|
|
||||||
TargetSpecifications.isNotInRolloutGroups(groups));
|
|
||||||
return JpaManagementHelper.countBySpec(jpaRepository, specList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long countByActionsInRolloutGroup(final long rolloutGroupId) {
|
|
||||||
return jpaRepository.count(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class StartNextGroupRolloutGroupSuccessAction implements RolloutGroupActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note - the exec could be called by JpaRolloutsExecutor and buy JpaRolloutsManagement#triggerNextGroup
|
// Note - the exec could be called by JpaRolloutsExecutor and buy JpaRolloutsManagement#triggerNextGroup
|
||||||
// this means it cold be called by concurrently.
|
// this means it could be called by concurrently.
|
||||||
@Override
|
@Override
|
||||||
public void exec(final Rollout rollout, final RolloutGroup rolloutGroup) {
|
public void exec(final Rollout rollout, final RolloutGroup rolloutGroup) {
|
||||||
systemSecurityContext.runAsSystem(() -> {
|
systemSecurityContext.runAsSystem(() -> {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.scheduler;
|
package org.eclipse.hawkbit.repository.jpa.scheduler;
|
||||||
|
|
||||||
|
import static org.eclipse.hawkbit.repository.jpa.JpaManagementHelper.combineWithAnd;
|
||||||
import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit;
|
import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
@@ -25,6 +26,7 @@ import jakarta.persistence.EntityManager;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.eclipse.hawkbit.ContextAware;
|
import org.eclipse.hawkbit.ContextAware;
|
||||||
|
import org.eclipse.hawkbit.ql.jpa.QLSupport;
|
||||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||||
@@ -33,23 +35,28 @@ import org.eclipse.hawkbit.repository.RolloutExecutor;
|
|||||||
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
import org.eclipse.hawkbit.repository.RolloutGroupManagement;
|
||||||
import org.eclipse.hawkbit.repository.RolloutHelper;
|
import org.eclipse.hawkbit.repository.RolloutHelper;
|
||||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
|
||||||
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
|
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.RolloutStoppedEvent;
|
||||||
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
|
import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
|
||||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||||
import org.eclipse.hawkbit.repository.jpa.management.JpaRolloutManagement;
|
import org.eclipse.hawkbit.repository.jpa.management.JpaRolloutManagement;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaRollout;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaRolloutGroup;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
|
import org.eclipse.hawkbit.repository.jpa.model.RolloutTargetGroup;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.RolloutGroupRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.RolloutRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.repository.RolloutTargetGroupRepository;
|
import org.eclipse.hawkbit.repository.jpa.repository.RolloutTargetGroupRepository;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.EvaluatorNotConfiguredException;
|
import org.eclipse.hawkbit.repository.jpa.rollout.condition.EvaluatorNotConfiguredException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupEvaluationManager;
|
import org.eclipse.hawkbit.repository.jpa.rollout.condition.RolloutGroupEvaluationManager;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.DeploymentHelper;
|
||||||
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
@@ -57,6 +64,7 @@ import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
|||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
import org.eclipse.hawkbit.repository.model.ActionCancellationType;
|
import org.eclipse.hawkbit.repository.model.ActionCancellationType;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
@@ -64,12 +72,16 @@ import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupErrorCondit
|
|||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupSuccessCondition;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.eclipse.hawkbit.repository.qfields.TargetFields;
|
||||||
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
import org.eclipse.hawkbit.security.SpringSecurityAuditorAware;
|
||||||
|
import org.eclipse.hawkbit.security.SystemSecurityContext;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAware;
|
import org.eclipse.hawkbit.tenancy.TenantAware;
|
||||||
import org.springframework.data.domain.PageRequest;
|
import org.springframework.data.domain.PageRequest;
|
||||||
|
import org.springframework.data.domain.Pageable;
|
||||||
import org.springframework.data.domain.Slice;
|
import org.springframework.data.domain.Slice;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.TransactionException;
|
import org.springframework.transaction.TransactionException;
|
||||||
@@ -106,7 +118,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
private final RolloutGroupRepository rolloutGroupRepository;
|
private final RolloutGroupRepository rolloutGroupRepository;
|
||||||
private final RolloutTargetGroupRepository rolloutTargetGroupRepository;
|
private final RolloutTargetGroupRepository rolloutTargetGroupRepository;
|
||||||
private final RolloutRepository rolloutRepository;
|
private final RolloutRepository rolloutRepository;
|
||||||
private final TargetManagement<? extends Target> targetManagement;
|
private final TargetRepository targetRepository;
|
||||||
private final DeploymentManagement deploymentManagement;
|
private final DeploymentManagement deploymentManagement;
|
||||||
private final RolloutGroupManagement rolloutGroupManagement;
|
private final RolloutGroupManagement rolloutGroupManagement;
|
||||||
private final RolloutManagement rolloutManagement;
|
private final RolloutManagement rolloutManagement;
|
||||||
@@ -117,6 +129,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
private final PlatformTransactionManager txManager;
|
private final PlatformTransactionManager txManager;
|
||||||
private final TenantAware tenantAware;
|
private final TenantAware tenantAware;
|
||||||
private final ContextAware contextAware;
|
private final ContextAware contextAware;
|
||||||
|
private final SystemSecurityContext systemSecurityContext;
|
||||||
private final RepositoryProperties repositoryProperties;
|
private final RepositoryProperties repositoryProperties;
|
||||||
private final Map<Long, AtomicLong> lastDynamicGroupFill = new ConcurrentHashMap<>();
|
private final Map<Long, AtomicLong> lastDynamicGroupFill = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -124,17 +137,18 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
public JpaRolloutExecutor(
|
public JpaRolloutExecutor(
|
||||||
final ActionRepository actionRepository, final RolloutGroupRepository rolloutGroupRepository,
|
final ActionRepository actionRepository, final RolloutGroupRepository rolloutGroupRepository,
|
||||||
final RolloutTargetGroupRepository rolloutTargetGroupRepository,
|
final RolloutTargetGroupRepository rolloutTargetGroupRepository,
|
||||||
final RolloutRepository rolloutRepository, final TargetManagement<? extends Target> targetManagement,
|
final RolloutRepository rolloutRepository, final TargetRepository targetRepository,
|
||||||
final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement,
|
final DeploymentManagement deploymentManagement, final RolloutGroupManagement rolloutGroupManagement,
|
||||||
final RolloutManagement rolloutManagement, final QuotaManagement quotaManagement,
|
final RolloutManagement rolloutManagement, final QuotaManagement quotaManagement,
|
||||||
final RolloutGroupEvaluationManager evaluationManager, final RolloutApprovalStrategy rolloutApprovalStrategy,
|
final RolloutGroupEvaluationManager evaluationManager, final RolloutApprovalStrategy rolloutApprovalStrategy,
|
||||||
final EntityManager entityManager, final PlatformTransactionManager txManager,
|
final EntityManager entityManager, final PlatformTransactionManager txManager,
|
||||||
final TenantAware tenantAware, final ContextAware contextAware, final RepositoryProperties repositoryProperties) {
|
final TenantAware tenantAware, final ContextAware contextAware, final SystemSecurityContext systemSecurityContext,
|
||||||
|
final RepositoryProperties repositoryProperties) {
|
||||||
this.actionRepository = actionRepository;
|
this.actionRepository = actionRepository;
|
||||||
this.rolloutGroupRepository = rolloutGroupRepository;
|
this.rolloutGroupRepository = rolloutGroupRepository;
|
||||||
this.rolloutTargetGroupRepository = rolloutTargetGroupRepository;
|
this.rolloutTargetGroupRepository = rolloutTargetGroupRepository;
|
||||||
this.rolloutRepository = rolloutRepository;
|
this.rolloutRepository = rolloutRepository;
|
||||||
this.targetManagement = targetManagement;
|
this.targetRepository = targetRepository;
|
||||||
this.deploymentManagement = deploymentManagement;
|
this.deploymentManagement = deploymentManagement;
|
||||||
this.rolloutGroupManagement = rolloutGroupManagement;
|
this.rolloutGroupManagement = rolloutGroupManagement;
|
||||||
this.rolloutManagement = rolloutManagement;
|
this.rolloutManagement = rolloutManagement;
|
||||||
@@ -145,6 +159,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
this.txManager = txManager;
|
this.txManager = txManager;
|
||||||
this.tenantAware = tenantAware;
|
this.tenantAware = tenantAware;
|
||||||
this.contextAware = contextAware;
|
this.contextAware = contextAware;
|
||||||
|
this.systemSecurityContext = systemSecurityContext;
|
||||||
this.repositoryProperties = repositoryProperties;
|
this.repositoryProperties = repositoryProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -492,7 +507,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
|
|
||||||
private long countTargetsFrom(final JpaRolloutGroup rolloutGroup) {
|
private long countTargetsFrom(final JpaRolloutGroup rolloutGroup) {
|
||||||
if (rolloutGroup.isDynamic()) {
|
if (rolloutGroup.isDynamic()) {
|
||||||
return targetManagement.countByActionsInRolloutGroup(rolloutGroup.getId());
|
return countByActionsInRolloutGroup(rolloutGroup.getId());
|
||||||
} else {
|
} else {
|
||||||
return rolloutGroupManagement.countTargetsOfRolloutsGroup(rolloutGroup.getId());
|
return rolloutGroupManagement.countTargetsOfRolloutsGroup(rolloutGroup.getId());
|
||||||
}
|
}
|
||||||
@@ -589,13 +604,13 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
targetsInGroupFilter = DeploymentHelper.runInNewTransaction(
|
targetsInGroupFilter = DeploymentHelper.runInNewTransaction(
|
||||||
txManager,
|
txManager,
|
||||||
"countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable",
|
"countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable",
|
||||||
count -> targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
count -> countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||||
groupTargetFilter, readyGroups, rollout.getDistributionSet().getType()));
|
groupTargetFilter, readyGroups, rollout.getDistributionSet().getType()));
|
||||||
} else { // if it is a rollout retry
|
} else { // if it is a rollout retry
|
||||||
targetsInGroupFilter = DeploymentHelper.runInNewTransaction(
|
targetsInGroupFilter = DeploymentHelper.runInNewTransaction(
|
||||||
txManager,
|
txManager,
|
||||||
"countByFailedRolloutAndNotInRolloutGroupsAndCompatible",
|
"countByFailedRolloutAndNotInRolloutGroupsAndCompatible",
|
||||||
count -> targetManagement.countByFailedRolloutAndNotInRolloutGroups(
|
count -> countByFailedRolloutAndNotInRolloutGroups(
|
||||||
RolloutHelper.getIdFromRetriedTargetFilter(rollout.getTargetFilterQuery()), readyGroups));
|
RolloutHelper.getIdFromRetriedTargetFilter(rollout.getTargetFilterQuery()), readyGroups));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,10 +655,10 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
rollout.getRolloutGroups(), RolloutGroupStatus.READY, group);
|
rollout.getRolloutGroups(), RolloutGroupStatus.READY, group);
|
||||||
final Slice<Target> targets;
|
final Slice<Target> targets;
|
||||||
if (!RolloutHelper.isRolloutRetried(rollout.getTargetFilterQuery())) {
|
if (!RolloutHelper.isRolloutRetried(rollout.getTargetFilterQuery())) {
|
||||||
targets = targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
targets = findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||||
readyGroups, targetFilter, rollout.getDistributionSet().getType(), pageRequest);
|
readyGroups, targetFilter, rollout.getDistributionSet().getType(), pageRequest);
|
||||||
} else {
|
} else {
|
||||||
targets = targetManagement.findByFailedRolloutAndNotInRolloutGroups(
|
targets = findByFailedRolloutAndNotInRolloutGroups(
|
||||||
RolloutHelper.getIdFromRetriedTargetFilter(rollout.getTargetFilterQuery()), readyGroups, pageRequest);
|
RolloutHelper.getIdFromRetriedTargetFilter(rollout.getTargetFilterQuery()), readyGroups, pageRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -681,7 +696,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
// since it contains condition for device to be created before the rollout
|
// since it contains condition for device to be created before the rollout
|
||||||
rollout.getTargetFilterQuery(), group);
|
rollout.getTargetFilterQuery(), group);
|
||||||
|
|
||||||
final Slice<Target> targets = targetManagement.findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
final Slice<Target> targets = findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||||
rollout.getId(), groupTargetFilter, rollout.getDistributionSet().getType(),
|
rollout.getId(), groupTargetFilter, rollout.getDistributionSet().getType(),
|
||||||
PageRequest.of(0, Math.toIntExact(Math.min(TRANSACTION_TARGETS, targetsLeftToAdd))));
|
PageRequest.of(0, Math.toIntExact(Math.min(TRANSACTION_TARGETS, targetsLeftToAdd))));
|
||||||
if (targets.getNumberOfElements() > 0) {
|
if (targets.getNumberOfElements() > 0) {
|
||||||
@@ -798,7 +813,7 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
|
|
||||||
private Long createActionsForTargetsInNewTransaction(final Rollout rollout, final RolloutGroup group) {
|
private Long createActionsForTargetsInNewTransaction(final Rollout rollout, final RolloutGroup group) {
|
||||||
return DeploymentHelper.runInNewTransaction(txManager, "createActionsForTargets", status -> {
|
return DeploymentHelper.runInNewTransaction(txManager, "createActionsForTargets", status -> {
|
||||||
final Slice<Target> targets = targetManagement.findByInRolloutGroupWithoutAction(
|
final Slice<Target> targets = findByInRolloutGroupWithoutAction(
|
||||||
group.getId(), PageRequest.of(0, JpaRolloutExecutor.TRANSACTION_TARGETS));
|
group.getId(), PageRequest.of(0, JpaRolloutExecutor.TRANSACTION_TARGETS));
|
||||||
|
|
||||||
if (targets.getNumberOfElements() > 0) {
|
if (targets.getNumberOfElements() > 0) {
|
||||||
@@ -858,7 +873,80 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
|||||||
try {
|
try {
|
||||||
QuotaHelper.assertAssignmentQuota(target.getId(), requested, quota, Action.class, Target.class, actionRepository::countByTargetId);
|
QuotaHelper.assertAssignmentQuota(target.getId(), requested, quota, Action.class, Target.class, actionRepository::countByTargetId);
|
||||||
} catch (final AssignmentQuotaExceededException ex) {
|
} catch (final AssignmentQuotaExceededException ex) {
|
||||||
deploymentManagement.handleMaxAssignmentsExceeded(target.getId(), requested, ex);
|
systemSecurityContext.runAsSystem(() -> deploymentManagement.handleMaxAssignmentsExceeded(target.getId(), requested, ex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// target repository access
|
||||||
|
|
||||||
|
// package-private just for testing
|
||||||
|
Slice<Target> findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||||
|
final long rolloutId, final String rsql, final DistributionSetType distributionSetType, final Pageable pageable) {
|
||||||
|
return targetRepository
|
||||||
|
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||||
|
combineWithAnd(List.of(
|
||||||
|
QLSupport.getInstance().buildSpec(rsql, TargetFields.class),
|
||||||
|
TargetSpecifications.hasNoOverridingActionsAndNotInRollout(rolloutId),
|
||||||
|
TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetType.getId()))),
|
||||||
|
pageable)
|
||||||
|
.map(Target.class::cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s
|
||||||
|
// and are compatible with the passed {@link DistributionSetType}
|
||||||
|
private Slice<Target> findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||||
|
final Collection<Long> groups, final String rsql, final DistributionSetType dsType, final Pageable pageable) {
|
||||||
|
return targetRepository
|
||||||
|
.findAllWithoutCount(AccessController.Operation.UPDATE,
|
||||||
|
combineWithAnd(List.of(
|
||||||
|
QLSupport.getInstance().buildSpec(rsql, TargetFields.class),
|
||||||
|
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||||
|
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))),
|
||||||
|
pageable)
|
||||||
|
.map(Target.class::cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds all targets with failed actions for specific Rollout and that are not assigned to one of the retried {@link RolloutGroup}s and
|
||||||
|
// are compatible with the passed {@link DistributionSetType}.
|
||||||
|
private Slice<Target> findByFailedRolloutAndNotInRolloutGroups(
|
||||||
|
final String rolloutId, final Collection<Long> groups, final Pageable pageable) {
|
||||||
|
final List<Specification<JpaTarget>> specList = List.of(
|
||||||
|
TargetSpecifications.failedActionsForRollout(rolloutId),
|
||||||
|
TargetSpecifications.isNotInRolloutGroups(groups));
|
||||||
|
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, specList, pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finds all targets of the provided {@link RolloutGroup} that have no Action for the RolloutGroup
|
||||||
|
private Slice<Target> findByInRolloutGroupWithoutAction(final long group, final Pageable pageable) {
|
||||||
|
if (!rolloutGroupRepository.existsById(group)) {
|
||||||
|
throw new EntityNotFoundException(RolloutGroup.class, group);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JpaManagementHelper.findAllWithoutCountBySpec(
|
||||||
|
targetRepository, List.of(TargetSpecifications.hasNoActionInRolloutGroup(group)), pageable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long countByActionsInRolloutGroup(final long rolloutGroupId) {
|
||||||
|
return targetRepository.count(TargetSpecifications.isInActionRolloutGroup(rolloutGroupId));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Counts all targets for all the given parameter {@link TargetFilterQuery} and that are not assigned to one of the {@link RolloutGroup}s
|
||||||
|
// and are compatible with the passed {@link DistributionSetType}
|
||||||
|
private long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||||
|
final String rsql, final Collection<Long> groups, final DistributionSetType dsType) {
|
||||||
|
return targetRepository.count(AccessController.Operation.UPDATE,
|
||||||
|
combineWithAnd(List.of(
|
||||||
|
QLSupport.getInstance().buildSpec(rsql, TargetFields.class),
|
||||||
|
TargetSpecifications.isNotInRolloutGroups(groups),
|
||||||
|
TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Counts all targets with failed actions for specific Rollout and that are not assigned to one of the {@link RolloutGroup}s and are
|
||||||
|
// compatible with the passed {@link DistributionSetType}
|
||||||
|
private long countByFailedRolloutAndNotInRolloutGroups(final String rolloutId, final Collection<Long> groups) {
|
||||||
|
final List<Specification<JpaTarget>> specList = List.of(
|
||||||
|
TargetSpecifications.failedActionsForRollout(rolloutId),
|
||||||
|
TargetSpecifications.isNotInRolloutGroups(groups));
|
||||||
|
return JpaManagementHelper.countBySpec(targetRepository, specList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -160,35 +160,18 @@ class TargetManagementTest extends AbstractAccessControllerManagementTest {
|
|||||||
READ_TARGET, UPDATE_TARGET + "/type.id==" + targetType1.getId(),
|
READ_TARGET, UPDATE_TARGET + "/type.id==" + targetType1.getId(),
|
||||||
READ_DISTRIBUTION_SET,
|
READ_DISTRIBUTION_SET,
|
||||||
CREATE_ROLLOUT, READ_ROLLOUT, HANDLE_ROLLOUT), () -> {
|
CREATE_ROLLOUT, READ_ROLLOUT, HANDLE_ROLLOUT), () -> {
|
||||||
assertThat(targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
|
||||||
List.of(1L), "id==*", ds2Type2.getType(), UNPAGED).stream().toList())
|
|
||||||
.containsExactly(target1Type1);
|
|
||||||
assertThat(targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable("id==*", List.of(1L), ds2Type2.getType()))
|
|
||||||
.isEqualTo(1);
|
|
||||||
|
|
||||||
final Rollout rollout = testdataFactory.createRolloutByVariables("testRollout", "testDescription", 3, "id==*", ds2Type2, "50", "5");
|
final Rollout rollout = testdataFactory.createRolloutByVariables("testRollout", "testDescription", 3, "id==*", ds2Type2, "50", "5");
|
||||||
final List<Long> groups = rolloutGroupManagement.findByRollout(rollout.getId(), UNPAGED).getContent().stream().
|
final List<Long> groups = rolloutGroupManagement.findByRollout(rollout.getId(), UNPAGED).getContent().stream().
|
||||||
map(Identifiable::getId).toList();
|
map(Identifiable::getId).toList();
|
||||||
assertThat(groups.stream().flatMap(
|
|
||||||
group -> targetManagement.findByInRolloutGroupWithoutAction(group, UNPAGED).get()).toList())
|
|
||||||
.containsExactly(target1Type1);
|
|
||||||
assertThat(groups.stream().flatMap(
|
assertThat(groups.stream().flatMap(
|
||||||
group -> rolloutGroupManagement.findTargetsOfRolloutGroup(group, UNPAGED).get()).toList())
|
group -> rolloutGroupManagement.findTargetsOfRolloutGroup(group, UNPAGED).get()).toList())
|
||||||
.containsExactly(target1Type1);
|
.containsExactly(target1Type1);
|
||||||
|
|
||||||
assertThat(targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(groups, "id==*", ds2Type2.getType(), UNPAGED))
|
|
||||||
.isEmpty();
|
|
||||||
assertThat(targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable("id==*", groups, ds2Type2.getType()))
|
|
||||||
.isZero();
|
|
||||||
|
|
||||||
// as system in context - doesn't apply scopes
|
// as system in context - doesn't apply scopes
|
||||||
final Rollout runAsSystem = systemSecurityContext.runAsSystem(
|
final Rollout runAsSystem = systemSecurityContext.runAsSystem(
|
||||||
() -> testdataFactory.createRolloutByVariables(
|
() -> testdataFactory.createRolloutByVariables(
|
||||||
"testRolloutAsSystem", "testDescriptionAsSystem", 3, "id==*", ds2Type2, "50", "5"));
|
"testRolloutAsSystem", "testDescriptionAsSystem", 3, "id==*", ds2Type2, "50", "5"));
|
||||||
assertThat(rolloutGroupManagement.findByRollout(runAsSystem.getId(), UNPAGED).getContent().stream()
|
|
||||||
.flatMap(
|
|
||||||
group -> targetManagement.findByInRolloutGroupWithoutAction(group.getId(), UNPAGED).getContent().stream()).toList())
|
|
||||||
.hasSize(3);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -672,8 +672,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
final List<DeploymentRequest> deploymentRequests = createAssignmentRequests(distributionSets, targets, 34);
|
final List<DeploymentRequest> deploymentRequests = createAssignmentRequests(distributionSets, targets, 34);
|
||||||
|
|
||||||
enableMultiAssignments();
|
enableMultiAssignments();
|
||||||
final List<DistributionSetAssignmentResult> results = deploymentManagement
|
final List<DistributionSetAssignmentResult> results = deploymentManagement.assignDistributionSets(deploymentRequests);
|
||||||
.assignDistributionSets(deploymentRequests);
|
|
||||||
|
|
||||||
assertThat(getResultingActionCount(results)).isEqualTo(deploymentRequests.size());
|
assertThat(getResultingActionCount(results)).isEqualTo(deploymentRequests.size());
|
||||||
final List<Long> dsIds = distributionSets.stream().map(DistributionSet::getId).toList();
|
final List<Long> dsIds = distributionSets.stream().map(DistributionSet::getId).toList();
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import io.github.classgraph.ClassInfo;
|
|||||||
import io.github.classgraph.ScanResult;
|
import io.github.classgraph.ScanResult;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
|
||||||
import org.eclipse.hawkbit.repository.PermissionSupport;
|
import org.eclipse.hawkbit.repository.PermissionSupport;
|
||||||
import org.eclipse.hawkbit.repository.TenantStatsManagement;
|
import org.eclipse.hawkbit.repository.TenantStatsManagement;
|
||||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||||
@@ -257,7 +258,8 @@ class ManagementSecurityTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(spelNode.getChild(0) instanceof VariableReference varRef && varRef.toStringAST().equals("#root")).isTrue();
|
assertThat(spelNode.getChild(0) instanceof VariableReference varRef && varRef.toStringAST().equals("#root")).isTrue();
|
||||||
assertThat(spelNode.getChild(1)).isInstanceOf(StringLiteral.class);
|
assertThat(spelNode.getChild(1)).isInstanceOf(StringLiteral.class);
|
||||||
final StringLiteral literal = (StringLiteral) spelNode.getChild(1);
|
final StringLiteral literal = (StringLiteral) spelNode.getChild(1);
|
||||||
preAuthorizedPermissions.add(literal.getLiteralValue().getValue() + "_" + permissionGroup);
|
preAuthorizedPermissions.add(String.valueOf(literal.getLiteralValue().getValue())
|
||||||
|
.replace(SpringEvalExpressions.PERMISSION_GROUP_PLACEHOLDER, permissionGroup));
|
||||||
}
|
}
|
||||||
default -> throw new IllegalStateException("Unexpected MethodReference: " + method);
|
default -> throw new IllegalStateException("Unexpected MethodReference: " + method);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,13 @@
|
|||||||
package org.eclipse.hawkbit.repository.jpa.management;
|
package org.eclipse.hawkbit.repository.jpa.management;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.callAs;
|
||||||
|
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withUser;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
import org.eclipse.hawkbit.repository.OffsetBasedPageRequest;
|
||||||
import org.eclipse.hawkbit.repository.RolloutManagement;
|
import org.eclipse.hawkbit.repository.RolloutManagement;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
@@ -24,8 +27,11 @@ import org.eclipse.hawkbit.repository.model.Rollout;
|
|||||||
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||||
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
import org.eclipse.hawkbit.repository.model.RolloutGroup.RolloutGroupStatus;
|
||||||
|
import org.eclipse.hawkbit.security.SecurityContextSerializer;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.data.domain.Sort.Direction;
|
import org.springframework.data.domain.Sort.Direction;
|
||||||
import org.springframework.test.context.TestPropertySource;
|
import org.springframework.test.context.TestPropertySource;
|
||||||
@@ -39,6 +45,15 @@ import org.springframework.test.context.TestPropertySource;
|
|||||||
@TestPropertySource(properties = { "hawkbit.server.repository.dynamicRolloutsMinInvolvePeriodMS=-1" })
|
@TestPropertySource(properties = { "hawkbit.server.repository.dynamicRolloutsMinInvolvePeriodMS=-1" })
|
||||||
class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class Config {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
SecurityContextSerializer securityContextSerializer() {
|
||||||
|
return SecurityContextSerializer.JSON_SERIALIZATION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void reset() {
|
void reset() {
|
||||||
this.approvalStrategy.setApprovalNeeded(false);
|
this.approvalStrategy.setApprovalNeeded(false);
|
||||||
@@ -47,19 +62,21 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
/**
|
/**
|
||||||
* Verifies a simple rollout flow
|
* Verifies a simple rollout flow
|
||||||
*/
|
*/
|
||||||
|
@SneakyThrows
|
||||||
@Test
|
@Test
|
||||||
void rolloutFlow() {
|
void rolloutFlow() {
|
||||||
final String rolloutName = "rollout-std";
|
final String rolloutName = "rollout-std";
|
||||||
final int amountGroups = 5; // static only
|
final int amountGroups = 5; // static only
|
||||||
final String targetPrefix = "controller-rollout-std-";
|
final String targetPrefix = "controller-rollout-std-";
|
||||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
final DistributionSet distributionSet = testdataFactory.createDistributionSetLocked("dsFor" + rolloutName);
|
||||||
|
|
||||||
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
||||||
final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
final Rollout rollout = callAs(
|
||||||
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30", false, false);
|
withUser("rolloutFlowUser", "READ_DISTRIBUTION_SET", "READ_TARGET", "READ_ROLLOUT", "CREATE_ROLLOUT"),
|
||||||
|
() -> testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
||||||
|
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30", false, false));
|
||||||
final List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
final List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
|
|
||||||
// add 2 targets not to be included
|
// add 2 targets not to be included
|
||||||
testdataFactory.createTargets(targetPrefix, amountGroups * 3, 2);
|
testdataFactory.createTargets(targetPrefix, amountGroups * 3, 2);
|
||||||
@@ -89,22 +106,24 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
/**
|
/**
|
||||||
* Verifies a simple dynamic rollout flow
|
* Verifies a simple dynamic rollout flow
|
||||||
*/
|
*/
|
||||||
|
@SneakyThrows
|
||||||
@Test
|
@Test
|
||||||
void dynamicRolloutFlow() {
|
void dynamicRolloutFlow() {
|
||||||
final String rolloutName = "dynamic-rollout-std";
|
final String rolloutName = "dynamic-rollout-std";
|
||||||
final int amountGroups = 2; // static only
|
final int amountGroups = 2; // static only
|
||||||
final String targetPrefix = "controller-dynamic-rollout-std-";
|
final String targetPrefix = "controller-dynamic-rollout-std-";
|
||||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
final DistributionSet distributionSet = testdataFactory.createDistributionSetLocked("dsFor" + rolloutName);
|
||||||
|
|
||||||
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
||||||
final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
final Rollout rollout = callAs(
|
||||||
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30", false, true);
|
withUser("dynamicRolloutFlow", "READ_DISTRIBUTION_SET", "READ_TARGET", "READ_ROLLOUT", "CREATE_ROLLOUT"),
|
||||||
|
() -> testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
||||||
|
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30", false, true));
|
||||||
|
|
||||||
// rollout is READY
|
// rollout is READY
|
||||||
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3);
|
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3);
|
||||||
List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
final RolloutGroup dynamic1 = groups.get(amountGroups);
|
final RolloutGroup dynamic1 = groups.get(amountGroups);
|
||||||
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3); // + dynamic
|
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3); // + dynamic
|
||||||
for (int i = 0; i < amountGroups; i++) {
|
for (int i = 0; i < amountGroups; i++) {
|
||||||
@@ -139,8 +158,7 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
assertRollout(rollout, true, RolloutStatus.RUNNING, amountGroups + 2, amountGroups * 3 + 3);
|
assertRollout(rollout, true, RolloutStatus.RUNNING, amountGroups + 2, amountGroups * 3 + 3);
|
||||||
assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 3);
|
assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 3);
|
||||||
groups = rolloutGroupManagement.findByRollout(
|
groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
final RolloutGroup dynamic2 = groups.get(amountGroups + 1);
|
final RolloutGroup dynamic2 = groups.get(amountGroups + 1);
|
||||||
assertGroup(dynamic2, true, RolloutGroupStatus.SCHEDULED, 0);
|
assertGroup(dynamic2, true, RolloutGroupStatus.SCHEDULED, 0);
|
||||||
|
|
||||||
@@ -205,25 +223,27 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
/**
|
/**
|
||||||
* Verifies a simple dynamic rollout flow with a dynamic group template
|
* Verifies a simple dynamic rollout flow with a dynamic group template
|
||||||
*/
|
*/
|
||||||
|
@SneakyThrows
|
||||||
@Test
|
@Test
|
||||||
void dynamicRolloutTemplateFlow() {
|
void dynamicRolloutTemplateFlow() {
|
||||||
final String rolloutName = "dynamic-template-rollout-std";
|
final String rolloutName = "dynamic-template-rollout-std";
|
||||||
final int amountGroups = 3; // static only
|
final int amountGroups = 3; // static only
|
||||||
final String targetPrefix = "controller-template-dynamic-rollout-std-";
|
final String targetPrefix = "controller-template-dynamic-rollout-std-";
|
||||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
final DistributionSet distributionSet = testdataFactory.createDistributionSetLocked("dsFor" + rolloutName);
|
||||||
|
|
||||||
// create rollout with amountGroups static groups * 3 targets and dynamic group template with 6 targets
|
// create rollout with amountGroups static groups * 3 targets and dynamic group template with 6 targets
|
||||||
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
||||||
final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
final Rollout rollout = callAs(
|
||||||
|
withUser("dynamicRolloutTemplateFlow", "READ_DISTRIBUTION_SET", "READ_TARGET", "READ_ROLLOUT", "CREATE_ROLLOUT"),
|
||||||
|
() -> testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
||||||
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30",
|
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30",
|
||||||
Action.ActionType.FORCED, 1000, false, true,
|
Action.ActionType.FORCED, 1000, false, true,
|
||||||
RolloutManagement.DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build());
|
RolloutManagement.DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build()));
|
||||||
|
|
||||||
// rollout is READY, amountGroups + 1 (dynamic) rollout groups and amountGroups * 3 targets in static groups
|
// rollout is READY, amountGroups + 1 (dynamic) rollout groups and amountGroups * 3 targets in static groups
|
||||||
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3);
|
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3);
|
||||||
List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
final RolloutGroup dynamic1 = groups.get(amountGroups);
|
final RolloutGroup dynamic1 = groups.get(amountGroups);
|
||||||
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3); // + dynamic
|
assertRollout(rollout, true, RolloutStatus.READY, amountGroups + 1, amountGroups * 3); // + dynamic
|
||||||
for (int i = 0; i < amountGroups; i++) {
|
for (int i = 0; i < amountGroups; i++) {
|
||||||
@@ -258,8 +278,7 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
assertRollout(rollout, true, RolloutStatus.RUNNING, amountGroups + 2, amountGroups * 3 + 6);
|
assertRollout(rollout, true, RolloutStatus.RUNNING, amountGroups + 2, amountGroups * 3 + 6);
|
||||||
assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 6);
|
assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 6);
|
||||||
groups = rolloutGroupManagement.findByRollout(
|
groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
final RolloutGroup dynamic2 = groups.get(amountGroups + 1);
|
final RolloutGroup dynamic2 = groups.get(amountGroups + 1);
|
||||||
assertGroup(dynamic2, true, RolloutGroupStatus.SCHEDULED, 0);
|
assertGroup(dynamic2, true, RolloutGroupStatus.SCHEDULED, 0);
|
||||||
|
|
||||||
@@ -305,16 +324,19 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
/**
|
/**
|
||||||
* Verifies a simple pure (no static groups) dynamic rollout flow with a dynamic group template
|
* Verifies a simple pure (no static groups) dynamic rollout flow with a dynamic group template
|
||||||
*/
|
*/
|
||||||
|
@SneakyThrows
|
||||||
@Test
|
@Test
|
||||||
void dynamicRolloutPureFlow() {
|
void dynamicRolloutPureFlow() {
|
||||||
final String rolloutName = "pure-dynamic-rollout-std";
|
final String rolloutName = "pure-dynamic-rollout-std";
|
||||||
final String targetPrefix = "controller-pure-dynamic-rollout-std-";
|
final String targetPrefix = "controller-pure-dynamic-rollout-std-";
|
||||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
final DistributionSet distributionSet = testdataFactory.createDistributionSetLocked("dsFor" + rolloutName);
|
||||||
|
|
||||||
final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, 0,
|
final Rollout rollout = callAs(
|
||||||
|
withUser("dynamicRolloutPureFlow", "READ_DISTRIBUTION_SET", "READ_TARGET", "READ_ROLLOUT", "CREATE_ROLLOUT"),
|
||||||
|
() -> testdataFactory.createRolloutByVariables(rolloutName, rolloutName, 0,
|
||||||
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30",
|
"controllerid==" + targetPrefix + "*", distributionSet, "60", "30",
|
||||||
Action.ActionType.FORCED, 1000, false, true,
|
Action.ActionType.FORCED, 1000, false, true,
|
||||||
RolloutManagement.DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build());
|
RolloutManagement.DynamicRolloutGroupTemplate.builder().nameSuffix("-dyn").targetCount(6).build()));
|
||||||
|
|
||||||
// rollout is READY, amountGroups + 1 (dynamic) rollout groups and amountGroups * 3 targets in static groups
|
// rollout is READY, amountGroups + 1 (dynamic) rollout groups and amountGroups * 3 targets in static groups
|
||||||
assertRollout(rollout, true, RolloutStatus.READY, 1, 0);
|
assertRollout(rollout, true, RolloutStatus.READY, 1, 0);
|
||||||
@@ -347,8 +369,7 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
assertRollout(rollout, true, RolloutStatus.RUNNING, 2, 6);
|
assertRollout(rollout, true, RolloutStatus.RUNNING, 2, 6);
|
||||||
assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 6);
|
assertGroup(dynamic1, true, RolloutGroupStatus.RUNNING, 6);
|
||||||
groups = rolloutGroupManagement.findByRollout(
|
groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
final RolloutGroup dynamic2 = groups.get(1);
|
final RolloutGroup dynamic2 = groups.get(1);
|
||||||
assertGroup(dynamic2, true, RolloutGroupStatus.SCHEDULED, 0);
|
assertGroup(dynamic2, true, RolloutGroupStatus.SCHEDULED, 0);
|
||||||
|
|
||||||
@@ -388,19 +409,21 @@ class RolloutManagementFlowTest extends AbstractJpaIntegrationTest {
|
|||||||
/**
|
/**
|
||||||
* Verifies a simple rollout flow
|
* Verifies a simple rollout flow
|
||||||
*/
|
*/
|
||||||
|
@SneakyThrows
|
||||||
@Test
|
@Test
|
||||||
void rollout0ThresholdFlow() {
|
void rollout0ThresholdFlow() {
|
||||||
final String rolloutName = "rollout-std-0threshold";
|
final String rolloutName = "rollout-std-0threshold";
|
||||||
final int amountGroups = 5; // static only
|
final int amountGroups = 5; // static only
|
||||||
final String targetPrefix = "controller-rollout-std-0threshold-";
|
final String targetPrefix = "controller-rollout-std-0threshold-";
|
||||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("dsFor" + rolloutName);
|
final DistributionSet distributionSet = testdataFactory.createDistributionSetLocked("dsFor" + rolloutName);
|
||||||
|
|
||||||
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
testdataFactory.createTargets(targetPrefix, 0, amountGroups * 3);
|
||||||
final Rollout rollout = testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
final Rollout rollout = callAs(
|
||||||
"controllerid==" + targetPrefix + "*", distributionSet, "0", "25", false, false);
|
withUser("rollout0ThresholdFlow", "READ_DISTRIBUTION_SET", "READ_TARGET", "READ_ROLLOUT", "CREATE_ROLLOUT"),
|
||||||
|
() -> testdataFactory.createRolloutByVariables(rolloutName, rolloutName, amountGroups,
|
||||||
|
"controllerid==" + targetPrefix + "*", distributionSet, "0", "25", false, false));
|
||||||
final List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
final List<RolloutGroup> groups = rolloutGroupManagement.findByRollout(
|
||||||
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))
|
rollout.getId(), new OffsetBasedPageRequest(0, amountGroups + 10, Sort.by(Direction.ASC, "id"))).getContent();
|
||||||
).getContent();
|
|
||||||
|
|
||||||
// start rollout
|
// start rollout
|
||||||
rolloutManagement.start(rollout.getId());
|
rolloutManagement.start(rollout.getId());
|
||||||
|
|||||||
@@ -57,17 +57,14 @@ import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
|||||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaNamedEntity_;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetTag;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget_;
|
||||||
import org.eclipse.hawkbit.repository.model.Action;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate;
|
import org.eclipse.hawkbit.repository.model.Action.ActionStatusCreate;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
|
||||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
|
||||||
import org.eclipse.hawkbit.repository.model.Tag;
|
import org.eclipse.hawkbit.repository.model.Tag;
|
||||||
import org.eclipse.hawkbit.repository.model.Target;
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||||
@@ -79,7 +76,6 @@ import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
|||||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
import org.springframework.data.domain.Slice;
|
|
||||||
import org.springframework.data.jpa.domain.Specification;
|
import org.springframework.data.jpa.domain.Specification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -729,60 +725,6 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest<
|
|||||||
"notExisting", ds.getId(), "name==*")).isFalse();
|
"notExisting", ds.getId(), "name==*")).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests action based aspects of the dynamic group assignment filters.
|
|
||||||
* Target matches filter no active action with ge weight.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
void findByTargetFilterQueryAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable() {
|
|
||||||
final String targetPrefix = "dyn_action_filter_";
|
|
||||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
|
||||||
final List<Target> targets = testdataFactory.createTargets(targetPrefix, 10);
|
|
||||||
final Rollout rolloutOlder = testdataFactory.createRollout();
|
|
||||||
final Rollout rollout = testdataFactory.createRollout();
|
|
||||||
final Rollout rolloutNewer = testdataFactory.createRollout();
|
|
||||||
|
|
||||||
int target = 0;
|
|
||||||
final List<Integer> expected = new ArrayList<>();
|
|
||||||
// old ro with less weight - match
|
|
||||||
expected.add(target);
|
|
||||||
createAction(targets.get(target++), rolloutOlder, 0, Status.RUNNING, distributionSet);
|
|
||||||
// old ro with equal weight - match
|
|
||||||
expected.add(target);
|
|
||||||
createAction(targets.get(target++), rolloutOlder, 10, Status.RUNNING, distributionSet);
|
|
||||||
// old ro with bigger weight, scheduled - match
|
|
||||||
expected.add(target);
|
|
||||||
createAction(targets.get(target++), rolloutOlder, 11, Status.SCHEDULED, distributionSet);
|
|
||||||
// old ro with bigger weight, running - match
|
|
||||||
expected.add(target);
|
|
||||||
createAction(targets.get(target++), rolloutOlder, 11, Status.RUNNING, distributionSet);
|
|
||||||
// old ro with bigger weight, running - match
|
|
||||||
expected.add(target);
|
|
||||||
createAction(targets.get(target++), rolloutOlder, 11, Status.FINISHED, distributionSet);
|
|
||||||
// same ro - doesn't match
|
|
||||||
createAction(targets.get(target++), rollout, 10, Status.RUNNING, distributionSet);
|
|
||||||
// new ro with less weight - doesn't match
|
|
||||||
createAction(targets.get(target++), rolloutNewer, 0, Status.RUNNING, distributionSet);
|
|
||||||
// new ro with less weight - doesn't match
|
|
||||||
createAction(targets.get(target++), rolloutNewer, 5, Status.WARNING, distributionSet);
|
|
||||||
// NEW ro with EQUAL weight - doesn't match
|
|
||||||
createAction(targets.get(target++), rolloutNewer, 10, Status.RUNNING, distributionSet);
|
|
||||||
// new ro with BIGGER weight - doesn't match
|
|
||||||
createAction(targets.get(target), rolloutNewer, 20, Status.DOWNLOADED, distributionSet);
|
|
||||||
|
|
||||||
final Slice<Target> matching =
|
|
||||||
targetManagement.findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
|
||||||
rollout.getId(), "controllerid==dyn_action_filter_*", distributionSet.getType(), PAGE);
|
|
||||||
|
|
||||||
assertThat(matching.getNumberOfElements()).isEqualTo(expected.size());
|
|
||||||
assertThat(matching.stream()
|
|
||||||
.map(Target::getControllerId)
|
|
||||||
.map(s -> s.substring(targetPrefix.length()))
|
|
||||||
.map(Integer::parseInt)
|
|
||||||
.sorted()
|
|
||||||
.toList()).isEqualTo(expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Target matches filter for not existing DS.
|
* Target matches filter for not existing DS.
|
||||||
*/
|
*/
|
||||||
@@ -834,7 +776,6 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest<
|
|||||||
verifyThrownExceptionBy(
|
verifyThrownExceptionBy(
|
||||||
() -> targetManagement.findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(NOT_EXIST_IDL, "name==*", PAGE),
|
() -> targetManagement.findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(NOT_EXIST_IDL, "name==*", PAGE),
|
||||||
"DistributionSet");
|
"DistributionSet");
|
||||||
verifyThrownExceptionBy(() -> targetManagement.findByInRolloutGroupWithoutAction(NOT_EXIST_IDL, PAGE), "RolloutGroup");
|
|
||||||
verifyThrownExceptionBy(() -> targetManagement.findByAssignedDistributionSet(NOT_EXIST_IDL, PAGE), "DistributionSet");
|
verifyThrownExceptionBy(() -> targetManagement.findByAssignedDistributionSet(NOT_EXIST_IDL, PAGE), "DistributionSet");
|
||||||
verifyThrownExceptionBy(
|
verifyThrownExceptionBy(
|
||||||
() -> targetManagement.findByAssignedDistributionSetAndRsql(NOT_EXIST_IDL, "name==*", PAGE), "DistributionSet");
|
() -> targetManagement.findByAssignedDistributionSetAndRsql(NOT_EXIST_IDL, "name==*", PAGE), "DistributionSet");
|
||||||
@@ -1124,24 +1065,6 @@ class TargetManagementTest extends AbstractRepositoryManagementWithMetadataTest<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createAction(final Target target, final Rollout rollout, final Integer weight, final Action.Status status,
|
|
||||||
final DistributionSet distributionSet) {
|
|
||||||
final JpaAction action = new JpaAction();
|
|
||||||
action.setActionType(Action.ActionType.FORCED);
|
|
||||||
action.setTarget(target);
|
|
||||||
action.setInitiatedBy("test");
|
|
||||||
if (rollout != null) {
|
|
||||||
action.setRollout(rollout);
|
|
||||||
}
|
|
||||||
if (weight != null) {
|
|
||||||
action.setWeight(weight);
|
|
||||||
}
|
|
||||||
action.setStatus(status);
|
|
||||||
action.setActive(status != Status.FINISHED && status != Status.ERROR && status != Status.CANCELED);
|
|
||||||
action.setDistributionSet(distributionSet);
|
|
||||||
actionRepository.save(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) {
|
private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) {
|
||||||
final Page<? extends Target> foundTargetsByMetadataAndControllerId = targetManagement.findByRsql(rsqlFilter, PAGE);
|
final Page<? extends Target> foundTargetsByMetadataAndControllerId = targetManagement.findByRsql(rsqlFilter, PAGE);
|
||||||
final long foundTargetsByMetadataAndControllerIdCount = targetManagement.countByRsql(rsqlFilter);
|
final long foundTargetsByMetadataAndControllerIdCount = targetManagement.countByRsql(rsqlFilter);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import org.springframework.data.domain.Slice;
|
|||||||
* Story: Auto assign checker
|
* Story: Auto assign checker
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("java:S6813") // constructor injects are not possible for test classes
|
@SuppressWarnings("java:S6813") // constructor injects are not possible for test classes
|
||||||
class JpaAutoAssignExecutorIntTest extends AbstractJpaIntegrationTest {
|
class AutoAssignExecutorIntTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
private static final String SPACE_AND_DESCRIPTION = " description";
|
private static final String SPACE_AND_DESCRIPTION = " description";
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ import org.springframework.transaction.PlatformTransactionManager;
|
|||||||
* Story: Auto assign checker
|
* Story: Auto assign checker
|
||||||
*/
|
*/
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class JpaAutoAssignExecutorTest {
|
class AutoAssignExecutorTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement;
|
private TargetFilterQueryManagement<? extends TargetFilterQuery> targetFilterQueryManagement;
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.repository.jpa.scheduler;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Action;
|
||||||
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
|
import org.eclipse.hawkbit.repository.model.Target;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.domain.Slice;
|
||||||
|
|
||||||
|
public class RolloutExecutorTest extends AbstractJpaIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JpaRolloutExecutor jpaRolloutExecutor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests action based aspects of the dynamic group assignment filters.
|
||||||
|
* Target matches filter no active action with ge weight.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
void findByTargetFilterQueryAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable() {
|
||||||
|
final String targetPrefix = "dyn_action_filter_";
|
||||||
|
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||||
|
final List<Target> targets = testdataFactory.createTargets(targetPrefix, 10);
|
||||||
|
final Rollout rolloutOlder = testdataFactory.createRollout();
|
||||||
|
final Rollout rollout = testdataFactory.createRollout();
|
||||||
|
final Rollout rolloutNewer = testdataFactory.createRollout();
|
||||||
|
|
||||||
|
int target = 0;
|
||||||
|
final List<Integer> expected = new ArrayList<>();
|
||||||
|
// old ro with less weight - match
|
||||||
|
expected.add(target);
|
||||||
|
createAction(targets.get(target++), rolloutOlder, 0, Action.Status.RUNNING, distributionSet);
|
||||||
|
// old ro with equal weight - match
|
||||||
|
expected.add(target);
|
||||||
|
createAction(targets.get(target++), rolloutOlder, 10, Action.Status.RUNNING, distributionSet);
|
||||||
|
// old ro with bigger weight, scheduled - match
|
||||||
|
expected.add(target);
|
||||||
|
createAction(targets.get(target++), rolloutOlder, 11, Action.Status.SCHEDULED, distributionSet);
|
||||||
|
// old ro with bigger weight, running - match
|
||||||
|
expected.add(target);
|
||||||
|
createAction(targets.get(target++), rolloutOlder, 11, Action.Status.RUNNING, distributionSet);
|
||||||
|
// old ro with bigger weight, running - match
|
||||||
|
expected.add(target);
|
||||||
|
createAction(targets.get(target++), rolloutOlder, 11, Action.Status.FINISHED, distributionSet);
|
||||||
|
// same ro - doesn't match
|
||||||
|
createAction(targets.get(target++), rollout, 10, Action.Status.RUNNING, distributionSet);
|
||||||
|
// new ro with less weight - doesn't match
|
||||||
|
createAction(targets.get(target++), rolloutNewer, 0, Action.Status.RUNNING, distributionSet);
|
||||||
|
// new ro with less weight - doesn't match
|
||||||
|
createAction(targets.get(target++), rolloutNewer, 5, Action.Status.WARNING, distributionSet);
|
||||||
|
// NEW ro with EQUAL weight - doesn't match
|
||||||
|
createAction(targets.get(target++), rolloutNewer, 10, Action.Status.RUNNING, distributionSet);
|
||||||
|
// new ro with BIGGER weight - doesn't match
|
||||||
|
createAction(targets.get(target), rolloutNewer, 20, Action.Status.DOWNLOADED, distributionSet);
|
||||||
|
|
||||||
|
final Slice<Target> matching =
|
||||||
|
jpaRolloutExecutor.findByRsqlAndNoOverridingActionsAndNotInRolloutAndCompatibleAndUpdatable(
|
||||||
|
rollout.getId(), "controllerid==dyn_action_filter_*", distributionSet.getType(), PAGE);
|
||||||
|
|
||||||
|
assertThat(matching.getNumberOfElements()).isEqualTo(expected.size());
|
||||||
|
assertThat(matching.stream()
|
||||||
|
.map(Target::getControllerId)
|
||||||
|
.map(s -> s.substring(targetPrefix.length()))
|
||||||
|
.map(Integer::parseInt)
|
||||||
|
.sorted()
|
||||||
|
.toList()).isEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAction(
|
||||||
|
final Target target, final Rollout rollout, final Integer weight, final Action.Status status, final DistributionSet distributionSet) {
|
||||||
|
final JpaAction action = new JpaAction();
|
||||||
|
action.setActionType(Action.ActionType.FORCED);
|
||||||
|
action.setTarget(target);
|
||||||
|
action.setInitiatedBy("test");
|
||||||
|
if (rollout != null) {
|
||||||
|
action.setRollout(rollout);
|
||||||
|
}
|
||||||
|
if (weight != null) {
|
||||||
|
action.setWeight(weight);
|
||||||
|
}
|
||||||
|
action.setStatus(status);
|
||||||
|
action.setActive(status != Action.Status.FINISHED && status != Action.Status.ERROR && status != Action.Status.CANCELED);
|
||||||
|
action.setDistributionSet(distributionSet);
|
||||||
|
actionRepository.save(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -39,11 +39,12 @@ public final class SpringEvalExpressions {
|
|||||||
public static final String IS_SYSTEM_CODE = "hasAuthority('ROLE_SYSTEM_CODE')";
|
public static final String IS_SYSTEM_CODE = "hasAuthority('ROLE_SYSTEM_CODE')";
|
||||||
public static final String HAS_AUTH_SYSTEM_ADMIN = "hasAuthority('SYSTEM_ADMIN')";
|
public static final String HAS_AUTH_SYSTEM_ADMIN = "hasAuthority('SYSTEM_ADMIN')";
|
||||||
|
|
||||||
// evaluated to <permission>_<permissionGroup> (e.g. DISTRIBUTION_SET_CREATE)
|
public static final String PERMISSION_GROUP_PLACEHOLDER = "${permissionGroup}";
|
||||||
public static final String HAS_CREATE_REPOSITORY = "hasPermission(#root, 'CREATE')";
|
// evaluated to <permission>_<permissionGroup> (e.g. CREATE_DISTRIBUTION_SET)
|
||||||
public static final String HAS_READ_REPOSITORY = "hasPermission(#root, 'READ')";
|
public static final String HAS_CREATE_REPOSITORY = "hasPermission(#root, 'CREATE_${permissionGroup}')";
|
||||||
public static final String HAS_UPDATE_REPOSITORY = "hasPermission(#root, 'UPDATE')";
|
public static final String HAS_READ_REPOSITORY = "hasPermission(#root, 'READ_${permissionGroup}')";
|
||||||
public static final String HAS_DELETE_REPOSITORY = "hasPermission(#root, 'DELETE')";
|
public static final String HAS_UPDATE_REPOSITORY = "hasPermission(#root, 'UPDATE_${permissionGroup}')";
|
||||||
|
public static final String HAS_DELETE_REPOSITORY = "hasPermission(#root, 'DELETE_${permissionGroup}')";
|
||||||
|
|
||||||
public static final String IS_CONTROLLER = "hasAnyRole('" + SpRole.CONTROLLER_ROLE_ANONYMOUS + "', '" + SpRole.CONTROLLER_ROLE + "')";
|
public static final String IS_CONTROLLER = "hasAnyRole('" + SpRole.CONTROLLER_ROLE_ANONYMOUS + "', '" + SpRole.CONTROLLER_ROLE + "')";
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user