diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java index a9424cf0c3..13e1e2421d 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutManagement.java @@ -478,4 +478,19 @@ Slice findByFiltersWithDetailedStatus(@NotNull Pageable pageable, @NotE */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_HANDLE) void triggerNextGroup(long rolloutId); + + /** + * Retrieves a page of {@link RolloutGroup}s filtered by a given + * {@link Rollout}. + * + * @param rolloutId + * the ID of the rollout to filter the {@link RolloutGroup}s + * @param groupStatus + * the group status to filter the {@link RolloutGroup}s + * @return a page of found {@link RolloutGroup}s + */ + + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ) + long countGroupsByRolloutAndStatus(long rolloutId, RolloutGroup.RolloutGroupStatus groupStatus); + } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java index 5bd9ecccd9..50bb8a4db0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutManagement.java @@ -761,10 +761,20 @@ public void triggerNextGroup(final long rolloutId) { + "but current state is " + rollout.getStatus().name().toLowerCase()); } + if (countGroupsByRolloutAndStatus(rolloutId, RolloutGroupStatus.SCHEDULED) == 0) { + throw new RolloutIllegalStateException("No group is scheduled for running"); + } + final List rolloutGroupsRunning = rolloutGroupRepository.findByRolloutAndStatusOrderByIdDesc(rollout, RolloutGroupStatus.RUNNING); JpaRolloutGroup jpaRolloutGroup = rolloutGroupsRunning.get(0); startNextRolloutGroupAction.eval(rollout, jpaRolloutGroup, jpaRolloutGroup.getSuccessActionExp()); } + + @Override + public long countGroupsByRolloutAndStatus(final long rolloutId, RolloutGroup.RolloutGroupStatus groupStatus) { + return rolloutGroupRepository.countByRolloutIdAndStatusOrStatus(rolloutId, groupStatus, groupStatus); + } + } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutGrid.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutGrid.java index d0ce9eaf65..6fd4edf21e 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutGrid.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/rollout/RolloutGrid.java @@ -21,6 +21,7 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.model.Rollout; import org.eclipse.hawkbit.repository.model.Rollout.RolloutStatus; +import org.eclipse.hawkbit.repository.model.RolloutGroup; import org.eclipse.hawkbit.repository.model.TotalTargetCountStatus.Status; import org.eclipse.hawkbit.security.SystemSecurityContext; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; @@ -88,6 +89,7 @@ public class RolloutGrid extends AbstractGrid { private static final String APPROVE_BUTTON_ID = "approve"; private static final String RUN_BUTTON_ID = "run"; private static final String PAUSE_BUTTON_ID = "pause"; + private static final String TRIGGER_NEXT_GROUP_BUTTON_ID = "triggerNextGroup"; private static final String UPDATE_BUTTON_ID = "update"; private static final String COPY_BUTTON_ID = "copy"; private static final String DELETE_BUTTON_ID = "delete"; @@ -226,6 +228,12 @@ private static boolean isPausingAllowed(final RolloutStatus status) { return RolloutStatus.RUNNING == status; } + private static boolean isTriggerNextGroupAllowed(final ProxyRollout rollout, RolloutManagement rolloutManagement) { + return RolloutStatus.RUNNING == rollout.getStatus() && + rolloutManagement.countGroupsByRolloutAndStatus(rollout.getId(), + RolloutGroup.RolloutGroupStatus.SCHEDULED) > 0; + } + private static boolean isApprovingAllowed(final RolloutStatus status) { return RolloutStatus.WAITING_FOR_APPROVAL == status; } @@ -335,6 +343,15 @@ private void addActionColumns() { permissionChecker.hasRolloutHandlePermission() && isPausingAllowed(rollout.getStatus())); actionColumns.add(GridComponentBuilder.addIconColumn(this, pauseButton, PAUSE_BUTTON_ID, null)); + final ValueProvider triggerNextGroupButton = rollout -> + GridComponentBuilder.buildActionButton(i18n, clickEvent -> triggerNextRolloutGroup(rollout.getId(), + rollout.getName(), rollout.getStatus()), VaadinIcons.STEP_FORWARD, + UIMessageIdProvider.TOOLTIP_ROLLOUT_TRIGGER_NEXT_GROUP, SPUIStyleDefinitions.STATUS_ICON_NEUTRAL, + UIComponentIdProvider.ROLLOUT_TRIGGER_NEXT_GROUP_BUTTON_ID + "." + rollout.getId(), + permissionChecker.hasRolloutHandlePermission() && isTriggerNextGroupAllowed(rollout, rolloutManagement)); + actionColumns.add(GridComponentBuilder.addIconColumn(this, triggerNextGroupButton, + TRIGGER_NEXT_GROUP_BUTTON_ID, null)); + final ValueProvider updateButton = rollout -> GridComponentBuilder.buildActionButton(i18n, clickEvent -> updateRollout(rollout), VaadinIcons.EDIT, UIMessageIdProvider.TOOLTIP_ROLLOUT_UPDATE, SPUIStyleDefinitions.STATUS_ICON_NEUTRAL, @@ -488,4 +505,16 @@ protected String createDSTooltipText(final ProxyRollout rollout) { } return tooltipText.toString(); } + + private void triggerNextRolloutGroup(final Long rolloutId, final String rolloutName, + final RolloutStatus rolloutStatus) { + if (RolloutStatus.RUNNING != rolloutStatus + || rolloutManagement.countGroupsByRolloutAndStatus(rolloutId, RolloutGroup.RolloutGroupStatus.SCHEDULED) + == 0) { + return; + } + + rolloutManagement.triggerNextGroup(rolloutId); + uiNotification.displaySuccess(i18n.getMessage("message.rollout.trigger.next.group", rolloutName)); + } } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java index 9aaba44391..6d10baf721 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java @@ -1154,6 +1154,11 @@ public final class UIComponentIdProvider { */ public static final String ROLLOUT_PAUSE_BUTTON_ID = ROLLOUT_ACTION_ID + ".7"; + /** + * Rollout trigger next group button id. + */ + public static final String ROLLOUT_TRIGGER_NEXT_GROUP_BUTTON_ID = ROLLOUT_ACTION_ID + ".13"; + /** * Rollout update button id. */ diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java index 041fe199f8..7144f2a903 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIMessageIdProvider.java @@ -351,6 +351,8 @@ public final class UIMessageIdProvider { public static final String TOOLTIP_UPLOAD_STATUS_PREFIX = "tooltip.upload.status."; + public static final String TOOLTIP_ROLLOUT_TRIGGER_NEXT_GROUP = "tooltip.rollout.triggernextgroup"; + /** * Private Constructor. */ diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index 0a39b1f6dc..fb8067af74 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -335,6 +335,7 @@ tooltip.active.action.status.inactiveerror=In-active Error tooltip.rollout.run = Run tooltip.rollout.approve = Approve tooltip.rollout.pause = Pause +tooltip.rollout.triggernextgroup = Trigger next group tooltip.rollout.update = Edit.. tooltip.rollout.copy = Copy.. tooltip.delete = Delete.. @@ -772,6 +773,7 @@ message.rollout.max.group.size.exceeded.advanced = The maximum size of {0} targe message.rollout.approval.required = You should approve or reject the Rollout message.rollout.started = Rollout {0} started successfully message.rollout.paused = Rollout {0} paused successfully +message.rollout.trigger.next.group = Next group successfully triggered message.rollout.resumed = Rollout {0} resumed successfully message.rollout.deleted = Rollout {0} deleted successfully message.rollout.noofgroups.or.targetfilter.missing = Please enter number of groups and select target filter