Feature mass cancel running actions on ds invalidation (#1177)

* Extend DS invalidation dialog to include mass-cancellation of actions

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

add component id for cancelation type radio buttons

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* add infos about ds invalidation to UI documentation;
update UI images; add screenshot about ds invalidation

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* fix review findings

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* add link property to invalidation docu

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* Put invalidation counts into one object

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* add hint to invalidation dialog, that invalidation is unrepeatable

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* disable invalidate button if insufficient permission

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* fix auto assignment error with insufficient permission

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* implement permissions check for invalidation dialog

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>

* add update_target permission to api doc description

Signed-off-by: Natalia Kislicyn <natalia.kislicyn@bosch.io>
This commit is contained in:
Natalia Kislicyn
2021-10-05 14:15:43 +02:00
committed by GitHub
parent aaa023732e
commit 70d0fe879e
25 changed files with 279 additions and 45 deletions

View File

@@ -8,6 +8,7 @@ Software update operations in large scale IoT scenarios with hundreds of thousan
<!--more-->
That includes:
- _Technical Scalability_ by means of horizontal scale of the hawkBit server cluster in the cloud.
- _Global_ artifact _content delivery_ capacities.
- _Functional Scalability_ by means of:
@@ -20,6 +21,7 @@ That includes:
Eclipse hawkBit sees these capabilities under the term Rollout Management.
The following capabilities are currently supported by the _Rollout Management_:
- Create, update and start of rollouts.
- Selection of targets as input for the rollout based on _target filter_ functionality.
- Selection of a _DistributionSet_.

View File

@@ -31,12 +31,12 @@ Target status overview, target management and manual deployments.
- Start roll out by drag and drop targets on a DS.
- Target list supports CTRL-A for "select all".
- Delete sets, tags or targets by dragging them on delete icon.
- Select _Target_ to see _Action_ History.
- Bulk target upload: create bulk targets by upload.
- DS invalidation allows to mark broken updates and avoid the distribution of such
Hints for bulk upload:
- Expected file type : csv.
- Expected file format : Each line with two values (ControllerID,Target Name). ControllerID is mandatory.
- Example:
@@ -47,6 +47,20 @@ Controller_id_2,targetName2
![Deployment Management view](../images/ui/deployment_mgmt.png)
### Distribution set invalidation
It is possible to mark broken updates and avoid the distribution of such by invalidating the corresponding distribution
set in the Distributions list of the Deployment view.
Invalidating a distribution set removes all auto-assignments that reference this distribution set. Optionally, all
rollouts that reference the distribution set can be stopped and existing update actions are removed, either by a
soft-cancel or a forced-cancel.
Invalidated distribution sets cannot be valid again, but remain invalid. They cannot be assigned to targets, neither
through a rollout, auto-assignment nor a single assignment.
![Distribution set invalidation](../images/ui/deployment_ds_invalidation.png)
## Distribution Management
### Purpose
@@ -148,4 +162,4 @@ In order to activate the auto-assignment, one should first click on _Auto assign
As long as the auto-assignment stays active, the scheduler will try to assign selected distribution set to corresponding custom filter targets, that have never seen it before.
![Auto assignment](../images/ui/target_filter_auto_assignment.png)
![Auto assignment](../images/ui/target_filter_auto_assignment.png)

BIN
docs/static/images/ui/artifact_mgmt.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

BIN
docs/static/images/ui/deployment_mgmt.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 190 KiB

BIN
docs/static/images/ui/distribution_mgmt.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 114 KiB

BIN
docs/static/images/ui/rollout_groups.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 105 KiB

BIN
docs/static/images/ui/rollout_mgmt.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 74 KiB

BIN
docs/static/images/ui/target_filter.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 309 KiB

BIN
docs/static/images/ui/target_filter_auto_assignment.png vendored Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 152 KiB

View File

@@ -65,7 +65,7 @@ public class DistributionSetInvalidation {
* distribution set
*/
public enum CancelationType {
FORCE, SOFT, NONE;
FORCE, SOFT, NONE
}
}

View File

@@ -38,4 +38,4 @@ public class DistributionSetInvalidationCount {
return actionCount;
}
}
}

View File

@@ -835,7 +835,12 @@ include::../errors/429.adoc[]
=== Implementation Notes
Invalidate a distribution set. Once a distribution set is invalidated, it can not be valid again. An invalidated distribution set cannot be assigned to targets anymore. The distribution set that is going to be invalidated will be removed from all auto assignments. Furthermore, the user can choose to cancel all rollouts and (force) cancel all actions connected to this distribution set. Required permission: UPDATE_REPOSITORY
Invalidate a distribution set.
Once a distribution set is invalidated, it can not be valid again.
An invalidated distribution set cannot be assigned to targets anymore.
The distribution set that is going to be invalidated will be removed from all auto assignments.
Furthermore, the user can choose to cancel all rollouts and (force) cancel all actions connected to this distribution set.
Required permission: UPDATE_REPOSITORY, UPDATE_TARGET
=== Invalidate a distribution set

View File

@@ -168,4 +168,22 @@ public class SpPermissionChecker implements Serializable {
public boolean hasRolloutApprovalPermission() {
return hasRolloutReadPermission() && permissionService.hasPermission(SpPermission.APPROVE_ROLLOUT);
}
/**
*
* @return <code>true</code> if auto assignment can be added/updated to target filter
*/
public boolean hasAutoAssignmentUpdatePermission() {
return hasUpdateTargetPermission() && hasReadRepositoryPermission();
}
/**
*
* @return <code>true</code> if default invalidation of distribution set is
* allowed
*/
public boolean hasDistributionSetInvalidatePermission() {
return hasUpdateRepositoryPermission() && hasUpdateTargetPermission();
}
}

View File

@@ -279,8 +279,16 @@ public class UiProperties implements Serializable {
*/
private String rolloutView = "";
/**
* Link to documentation of state machine
*/
private String provisioningStateMachine = "";
/**
* Link to documentation of distribution set invalidation
*/
private String distributionSetInvalidation = "";
/**
* @return Link to documentation of deployment view
*/
@@ -352,6 +360,13 @@ public class UiProperties implements Serializable {
return provisioningStateMachine;
}
/**
* @return Link to documentation of distribution set invalidation
*/
public String getDistributionSetInvalidation() {
return distributionSetInvalidation;
}
public void setDeploymentView(final String deploymentView) {
this.deploymentView = deploymentView;
}
@@ -414,6 +429,15 @@ public class UiProperties implements Serializable {
this.provisioningStateMachine = provisioningStateMachine;
}
/**
* Sets the link to the distribution set invalidation documentation
*
* @param distributionSetInvalidation
* Link
*/
public void setDistributionSetInvalidation(String distributionSetInvalidation) {
this.distributionSetInvalidation = distributionSetInvalidation;
}
}
private final Documentation documentation = new Documentation();

View File

@@ -229,8 +229,8 @@ public class DragAndDropSupport<T extends ProxyIdentifiableEntity> {
final List<String> requiredPermissions = assignmentStrategy.getMissingPermissionsForDrop();
if (!CollectionUtils.isEmpty(requiredPermissions)) {
notification
.displayValidationError(i18n.getMessage("message.permission.insufficient", requiredPermissions));
notification.displayValidationError(
i18n.getMessage(UIMessageIdProvider.MESSAGE_ERROR_PERMISSION_INSUFFICIENT, requiredPermissions));
return false;
}

View File

@@ -183,7 +183,7 @@ public class TargetFilterGrid extends AbstractGrid<ProxyTargetFilterQuery, Strin
}
final Button link = GridComponentBuilder.buildLink(targetFilter, "distSetButton", caption,
permissionChecker.hasReadRepositoryPermission(),
permissionChecker.hasAutoAssignmentUpdatePermission(),
clickEvent -> onClickOfAutoAssignmentLink(targetFilter));
final String description = i18n.getMessage(UIMessageIdProvider.BUTTON_AUTO_ASSIGNMENT_DESCRIPTION);
@@ -202,8 +202,8 @@ public class TargetFilterGrid extends AbstractGrid<ProxyTargetFilterQuery, Strin
UI.getCurrent().addWindow(autoAssignmentWindow);
autoAssignmentWindow.setVisible(Boolean.TRUE);
} else {
notification.displayValidationError(
i18n.getMessage("message.permission.insufficient", SpPermission.READ_REPOSITORY));
notification.displayValidationError(i18n.getMessage(
UIMessageIdProvider.MESSAGE_ERROR_PERMISSION_INSUFFICIENT, SpPermission.READ_REPOSITORY));
}
}
}

View File

@@ -138,8 +138,8 @@ public class DistributionGrid extends AbstractDsGrid<DsManagementFilterParams> {
DsManagementFilterParams::new, getSelectionSupport()::deselectAll));
initFilterMappings();
getFilterSupport().setFilter(new DsManagementFilterParams());
this.invalidateDistributionSetSupport = new InvalidateDistributionSetSupport(this, i18n, notification,
dsInvalidationManagement);
this.invalidateDistributionSetSupport = new InvalidateDistributionSetSupport(this, i18n, uiProperties,
notification, permissionChecker, dsInvalidationManagement);
initStyleGenerator();
init();
@@ -239,7 +239,7 @@ public class DistributionGrid extends AbstractDsGrid<DsManagementFilterParams> {
i18n, clickEvent -> invalidateDistributionSetSupport.openConsequencesWindowOnInvalidateAction(ds),
VaadinIcons.BAN, UIMessageIdProvider.TOOLTIP_INVALIDATE_DISTRIBUTIONSET,
SPUIStyleDefinitions.STATUS_ICON_NEUTRAL, UIComponentIdProvider.DIST_INVALIDATE_ICON + "." + ds.getId(),
ds.getIsValid());
ds.getIsValid() && permissionChecker.hasDistributionSetInvalidatePermission());
return GridComponentBuilder.addIconColumn(this, buttonProvider, DS_INVALIDATE_BUTTON_ID, null);
}

View File

@@ -12,10 +12,13 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
import org.eclipse.hawkbit.ui.SpPermissionChecker;
import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet;
import org.eclipse.hawkbit.ui.utils.UIMessageIdProvider;
import org.eclipse.hawkbit.ui.utils.UINotification;
@@ -35,7 +38,10 @@ public class InvalidateDistributionSetSupport {
private static final Logger LOG = LoggerFactory.getLogger(InvalidateDistributionSetSupport.class);
private final VaadinMessageSource i18n;
private final UiProperties uiProperties;
private final UINotification notification;
private final SpPermissionChecker permissionChecker;
private final DistributionGrid grid;
private final DistributionSetInvalidationManagement dsInvalidationManagement;
@@ -55,10 +61,14 @@ public class InvalidateDistributionSetSupport {
* {@link DistributionSetInvalidationManagement}
*/
public InvalidateDistributionSetSupport(final DistributionGrid grid, final VaadinMessageSource i18n,
final UINotification notification, final DistributionSetInvalidationManagement dsInvalidationManagement) {
final UiProperties uiProperties, final UINotification notification,
final SpPermissionChecker permissionChecker,
final DistributionSetInvalidationManagement dsInvalidationManagement) {
this.grid = grid;
this.i18n = i18n;
this.uiProperties = uiProperties;
this.notification = notification;
this.permissionChecker = permissionChecker;
this.dsInvalidationManagement = dsInvalidationManagement;
}
@@ -72,11 +82,12 @@ public class InvalidateDistributionSetSupport {
final List<ProxyDistributionSet> allDistributionSetsForInvalidation = getDistributionSetsForInvalidation(
clickedDistributionSet);
consequencesDialog = new InvalidateDsConsequencesDialog(allDistributionSetsForInvalidation, i18n, ok -> {
if (ok) {
openAffectedEntitiesWindowOnInvalidateAction(allDistributionSetsForInvalidation);
}
});
consequencesDialog = new InvalidateDsConsequencesDialog(allDistributionSetsForInvalidation, i18n, uiProperties,
ok -> {
if (Boolean.TRUE.equals(ok) && hasSufficientPermission()) {
openAffectedEntitiesWindowOnInvalidateAction(allDistributionSetsForInvalidation);
}
});
consequencesDialog.getWindow().setWidth(40.0F, Sizeable.Unit.PERCENTAGE);
UI.getCurrent().addWindow(consequencesDialog.getWindow());
@@ -89,15 +100,15 @@ public class InvalidateDistributionSetSupport {
final DistributionSetInvalidationCount entitiesForInvalidationCount = dsInvalidationManagement
.countEntitiesForInvalidation(
getDistributionSetInvalidation(consequencesDialog.isStopRolloutsSelected(),
getDistributionSetIds(allDistributionSetsForInvalidation), CancelationType.NONE));
getDistributionSetIds(allDistributionSetsForInvalidation),
consequencesDialog.getCancelationType()));
final InvalidateDsAffectedEntitiesDialog affectedEntitiesDialog = new InvalidateDsAffectedEntitiesDialog(
allDistributionSetsForInvalidation, i18n, ok -> {
if (ok) {
if (Boolean.TRUE.equals(ok) && hasSufficientPermission()) {
handleOkForInvalidateDistributionSet(allDistributionSetsForInvalidation);
}
}, entitiesForInvalidationCount.getRolloutsCount(),
entitiesForInvalidationCount.getAutoAssignmentCount());
}, entitiesForInvalidationCount);
affectedEntitiesDialog.getWindow().setWidth(40.0F, Sizeable.Unit.PERCENTAGE);
UI.getCurrent().addWindow(affectedEntitiesDialog.getWindow());
@@ -106,11 +117,11 @@ public class InvalidateDistributionSetSupport {
private void handleOkForInvalidateDistributionSet(
final List<ProxyDistributionSet> allDistributionSetsForInvalidation) {
try {
dsInvalidationManagement.invalidateDistributionSet(
getDistributionSetInvalidation(consequencesDialog.isStopRolloutsSelected(),
getDistributionSetIds(allDistributionSetsForInvalidation), CancelationType.NONE));
getDistributionSetIds(allDistributionSetsForInvalidation),
consequencesDialog.getCancelationType()));
notification.displaySuccess(createSuccessNotificationText(allDistributionSetsForInvalidation));
grid.refreshAll();
} catch (final RuntimeException ex) {
@@ -121,6 +132,21 @@ public class InvalidateDistributionSetSupport {
}
}
private boolean hasSufficientPermission() {
if (consequencesDialog.isStopRolloutsSelected() && !permissionChecker.hasRolloutUpdatePermission()) {
notification.displayValidationError(i18n.getMessage(
UIMessageIdProvider.MESSAGE_ERROR_PERMISSION_INSUFFICIENT, SpPermission.UPDATE_ROLLOUT));
return false;
}
if (consequencesDialog.getCancelationType() != CancelationType.NONE
&& !permissionChecker.hasUpdateTargetPermission()) {
notification.displayValidationError(i18n
.getMessage(UIMessageIdProvider.MESSAGE_ERROR_PERMISSION_INSUFFICIENT, SpPermission.UPDATE_TARGET));
return false;
}
return true;
}
private DistributionSetInvalidation getDistributionSetInvalidation(final boolean stopRollouts,
final List<Long> distSetIds, final CancelationType cancelationType) {
return new DistributionSetInvalidation(distSetIds, cancelationType, stopRollouts);

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.ui.management.dstable;
import java.util.List;
import java.util.function.Consumer;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Rollout;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow.ConfirmStyle;
@@ -44,20 +46,19 @@ public class InvalidateDsAffectedEntitiesDialog {
* Constructor for {@link InvalidateDsAffectedEntitiesDialog}
*
* @param allDistributionSetsForInvalidation
* {@link List} of {@link ProxyDistributionSet} that are selected
* for invalidation
* {@link List} of {@link ProxyDistributionSet} that are selected for
* invalidation
* @param i18n
* {@link VaadinMessageSource}
* @param callback
* callback for dialog result
* @param affectedRollouts
* number of affected {@link Rollout}s
* @param affectedAutoAssignments
* number of affected auto assignments
* @param affectedEntities
* number of affected {@link Rollout}s, {@link Action}s and
* auto-assignments
*/
public InvalidateDsAffectedEntitiesDialog(final List<ProxyDistributionSet> allDistributionSetsForInvalidation,
final VaadinMessageSource i18n, final Consumer<Boolean> callback, final long affectedRollouts,
final long affectedAutoAssignments) {
final VaadinMessageSource i18n, final Consumer<Boolean> callback,
final DistributionSetInvalidationCount affectedEntities) {
this.i18n = i18n;
@@ -69,14 +70,21 @@ public class InvalidateDsAffectedEntitiesDialog {
consequencesLabel.setWidthFull();
content.addComponent(consequencesLabel);
final Label stoppedRolloutsLabel = new Label(i18n.getMessage(
UIMessageIdProvider.MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_ROLLOUTS, affectedRollouts));
final Label stoppedSingleAssignmentsLabel = new Label(
i18n.getMessage(UIMessageIdProvider.MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_ACTIONS,
affectedEntities.getActionCount()));
stoppedSingleAssignmentsLabel.setId(UIComponentIdProvider.INVALIDATE_DS_AFFECTED_ENTITIES_ACTIONS);
content.addComponent(stoppedSingleAssignmentsLabel);
final Label stoppedRolloutsLabel = new Label(
i18n.getMessage(UIMessageIdProvider.MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_ROLLOUTS,
affectedEntities.getRolloutsCount()));
stoppedRolloutsLabel.setId(UIComponentIdProvider.INVALIDATE_DS_AFFECTED_ENTITIES_ROLLOUTS);
content.addComponent(stoppedRolloutsLabel);
final Label stoppedAutoAssignmentsLabel = new Label(i18n.getMessage(
UIMessageIdProvider.MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_AUTOASSIGNMENTS,
affectedAutoAssignments));
affectedEntities.getAutoAssignmentCount()));
stoppedAutoAssignmentsLabel.setId(UIComponentIdProvider.INVALIDATE_DS_AFFECTED_ENTITIES_AUTOASSIGNMENTS);
content.addComponent(stoppedAutoAssignmentsLabel);

View File

@@ -11,11 +11,18 @@ package org.eclipse.hawkbit.ui.management.dstable;
import java.util.List;
import java.util.function.Consumer;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Link;
import com.vaadin.ui.RadioButtonGroup;
import com.vaadin.ui.themes.ValoTheme;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
import org.eclipse.hawkbit.ui.UiProperties;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow.ConfirmStyle;
import org.eclipse.hawkbit.ui.common.CommonDialogWindow.SaveDialogCloseListener;
import org.eclipse.hawkbit.ui.common.builder.WindowBuilder;
import org.eclipse.hawkbit.ui.common.data.proxies.ProxyDistributionSet;
import org.eclipse.hawkbit.ui.components.SPUIComponentProvider;
import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleTiny;
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
@@ -35,27 +42,35 @@ public class InvalidateDsConsequencesDialog {
private final Consumer<Boolean> callback;
private final VaadinMessageSource i18n;
private final UiProperties uiProperties;
private final CommonDialogWindow window;
private final CheckBox stopRolloutsCheckBox;
private final VaadinMessageSource i18n;
private final RadioButtonGroup<CancelationType> cancelationTypeGroup;
/**
* Constructor for {@link InvalidateDsConsequencesDialog}
*
* @param allDistributionSetsForInvalidation
* {@link List} of {@link ProxyDistributionSet} that are selected
* for invalidation
* {@link List} of {@link ProxyDistributionSet} that are selected for
* invalidation
* @param i18n
* {@link VaadinMessageSource}
* @param callback
* callback for dialog result
*/
public InvalidateDsConsequencesDialog(final List<ProxyDistributionSet> allDistributionSetsForInvalidation,
final VaadinMessageSource i18n, final Consumer<Boolean> callback) {
final VaadinMessageSource i18n, final UiProperties uiProperties, final Consumer<Boolean> callback) {
this.i18n = i18n;
this.uiProperties = uiProperties;
this.cancelationTypeGroup = createCancelationTypeOptionGroup();
this.stopRolloutsCheckBox = createStopRolloutsCheckbox();
final VerticalLayout content = new VerticalLayout();
content.setSpacing(true);
content.setMargin(true);
@@ -64,10 +79,11 @@ public class InvalidateDsConsequencesDialog {
consequencesLabel.setWidthFull();
content.addComponent(consequencesLabel);
stopRolloutsCheckBox = new CheckBox();
stopRolloutsCheckBox.setId(UIComponentIdProvider.INVALIDATE_DS_STOP_ROLLOUTS);
stopRolloutsCheckBox.setCaption(i18n.getMessage(UIMessageIdProvider.LABEL_INVALIDATE_DS_STOP_ROLLOUTS));
content.addComponent(createCancelationTypeInfo());
content.addComponent(cancelationTypeGroup);
content.addComponent(stopRolloutsCheckBox);
content.addComponent(createConsequencesHint());
addValueChangeListeners();
final WindowBuilder windowBuilder = new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW)
.id(UIComponentIdProvider.INVALIDATE_DS_CONSEQUENCES)
@@ -118,6 +134,48 @@ public class InvalidateDsConsequencesDialog {
}
}
private CheckBox createStopRolloutsCheckbox() {
final CheckBox checkBox = new CheckBox();
checkBox.setId(UIComponentIdProvider.INVALIDATE_DS_STOP_ROLLOUTS);
checkBox.setCaption(i18n.getMessage(UIMessageIdProvider.LABEL_INVALIDATE_DS_STOP_ROLLOUTS));
return checkBox;
}
private HorizontalLayout createCancelationTypeInfo() {
final HorizontalLayout horizontalLabelInfo = new HorizontalLayout();
final Label typeLabel = new Label(
i18n.getMessage(UIMessageIdProvider.LABEL_INVALIDATE_DS_TYPE_OF_CANCELLATION));
final Link linkToInvalidationHelp = SPUIComponentProvider.getHelpLink(i18n,
uiProperties.getLinks().getDocumentation().getDistributionSetInvalidation());
horizontalLabelInfo.addComponent(typeLabel);
horizontalLabelInfo.addComponent(linkToInvalidationHelp);
return horizontalLabelInfo;
}
private RadioButtonGroup<CancelationType> createCancelationTypeOptionGroup() {
final RadioButtonGroup<CancelationType> cancellationTypeOptions = new RadioButtonGroup<>();
cancellationTypeOptions.setId(UIComponentIdProvider.INVALIDATE_DS_CANCELATION_TYPE);
cancellationTypeOptions.addStyleName(ValoTheme.OPTIONGROUP_HORIZONTAL);
cancellationTypeOptions.setSizeUndefined();
cancellationTypeOptions.setItems(CancelationType.values());
cancellationTypeOptions.setItemCaptionGenerator(this::getCancelationTypeCaptionMessageId);
cancellationTypeOptions.setItemDescriptionGenerator(this::getCancelationTypeToolTipMessageId);
// default shall be "None"
cancellationTypeOptions.setSelectedItem(CancelationType.NONE);
return cancellationTypeOptions;
}
private Label createConsequencesHint() {
String hint = i18n.getMessage(UIMessageIdProvider.MESSAGE_INVALIDATE_DISTRIBUTIONSET_UNREPEATABLE_HINT);
final Label hintLabel = new Label(hint);
hintLabel.setWidthFull();
hintLabel.setStyleName(ValoTheme.LABEL_TINY);
return hintLabel;
}
/**
* Returns the user selection stop rollouts
*
@@ -127,10 +185,52 @@ public class InvalidateDsConsequencesDialog {
return stopRolloutsCheckBox.getValue();
}
CancelationType getCancelationType() {
return cancelationTypeGroup.getValue();
}
private void addValueChangeListeners() {
cancelationTypeGroup.addValueChangeListener(event -> {
if (event.getValue() == CancelationType.NONE) {
stopRolloutsCheckBox.setValue(false);
stopRolloutsCheckBox.setEnabled(true);
} else {
stopRolloutsCheckBox.setValue(true);
stopRolloutsCheckBox.setEnabled(false);
}
});
}
/**
* @return confirmation window
*/
public Window getWindow() {
return window;
}
private String getCancelationTypeCaptionMessageId(CancelationType item) {
switch (item) {
case FORCE:
return i18n.getMessage(UIMessageIdProvider.LABEL_CANCEL_ACTION_FORCE);
case SOFT:
return i18n.getMessage(UIMessageIdProvider.LABEL_CANCEL_ACTION_SOFT);
case NONE:
return i18n.getMessage(UIMessageIdProvider.LABEL_CANCEL_ACTION_NONE);
default:
return null;
}
}
private String getCancelationTypeToolTipMessageId(CancelationType item) {
switch (item) {
case FORCE:
return i18n.getMessage(UIMessageIdProvider.TOOLTIP_DISTRIBUTIONSET_INVALIDATE_FORCED);
case SOFT:
return i18n.getMessage(UIMessageIdProvider.TOOLTIP_DISTRIBUTIONSET_INVALIDATE_SOFT);
case NONE:
return i18n.getMessage(UIMessageIdProvider.TOOLTIP_DISTRIBUTIONSET_INVALIDATE_NONE);
default:
return null;
}
}
}

View File

@@ -1373,6 +1373,10 @@ public final class UIComponentIdProvider {
* Distribution set invalidate affected entities window id
*/
public static final String INVALIDATE_DS_AFFECTED_ENTITIES = "invalidate.distributionset.affectedentities.window";
/**
* Distribution set invalidate affected actions label id
*/
public static final String INVALIDATE_DS_AFFECTED_ENTITIES_ACTIONS = "invalidate.distributionset.affectedentities.actions";
/**
* Distribution set invalidate affected rollouts label id
*/
@@ -1385,7 +1389,10 @@ public final class UIComponentIdProvider {
* Distribution set invalidate consequences window, stop rollouts checkbox
*/
public static final String INVALIDATE_DS_STOP_ROLLOUTS = "invalidate.distributionset.consequences.stop.rollouts.checkbox";
/**
* Distribution set invalidate consequences window, cancelation type radio button group
*/
public static final String INVALIDATE_DS_CANCELATION_TYPE = "invalidate.distributionset.consequences.cancelation.type.radio";
/**
* Id of the unread notification button
*/

View File

@@ -105,6 +105,14 @@ public final class UIMessageIdProvider {
public static final String LABEL_INVALIDATE_DS_STOP_ROLLOUTS = "label.invalidate.distributionset.stop.rollouts";
public static final String LABEL_INVALIDATE_DS_TYPE_OF_CANCELLATION = "label.invalidate.ds.cancelation.type";
public static final String LABEL_CANCEL_ACTION_NONE = "label.cancel.action.none";
public static final String LABEL_CANCEL_ACTION_FORCE = "label.cancel.action.force";
public static final String LABEL_CANCEL_ACTION_SOFT = "label.cancel.action.soft";
public static final String MESSAGE_NO_DATA = "message.no.data";
public static final String MESSAGE_DATA_AVAILABLE = "message.data.available";
@@ -143,6 +151,8 @@ public final class UIMessageIdProvider {
public static final String MESSAGE_ERROR_ENTITY_READONLY = "message.entity.error.readonly";
public static final String MESSAGE_ERROR_PERMISSION_INSUFFICIENT = "message.permission.insufficient";
public static final String CRON_VALIDATION_ERROR = "message.maintenancewindow.schedule.validation.error";
public static final String TOOLTIP_OVERDUE = "tooltip.overdue";
@@ -195,6 +205,12 @@ public final class UIMessageIdProvider {
public static final String TOOLTIP_DISTRIBUTIONSET_INCOMPLETE = "tooltip.distributionset.incomplete";
public static final String TOOLTIP_DISTRIBUTIONSET_INVALIDATE_FORCED = "tooltip.distributionset.invalidate.forced";
public static final String TOOLTIP_DISTRIBUTIONSET_INVALIDATE_SOFT = "tooltip.distributionset.invalidate.soft";
public static final String TOOLTIP_DISTRIBUTIONSET_INVALIDATE_NONE = "tooltip.distributionset.invalidate.none";
public static final String TOOLTIP_TIMEFORCED_ITEM = "tooltip.timeforced.item";
public static final String TOOLTIP_TIMEFORCED_FORCED_IN = "tooltip.timeforced.forced.in";
@@ -275,6 +291,8 @@ public final class UIMessageIdProvider {
public static final String MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_INTRO_PLURAL = "message.invalidate.distributionset.affected.entities.intro.plural";
public static final String MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_ACTIONS = "message.invalidate.distributionset.affected.entities.actions";
public static final String MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_ROLLOUTS = "message.invalidate.distributionset.affected.entities.rollouts";
public static final String MESSAGE_INVALIDATE_DISTRIBUTIONSET_AFFECTED_ENTITIES_AUTOASSIGNMENTS = "message.invalidate.distributionset.affected.entities.autoassignments";
@@ -287,6 +305,8 @@ public final class UIMessageIdProvider {
public static final String MESSAGE_INVALIDATE_DISTRIBUTIONSET_FAIL_PLURAL = "message.invalidate.distributionset.fail.plural";
public static final String MESSAGE_INVALIDATE_DISTRIBUTIONSET_UNREPEATABLE_HINT = "message.invalidate.distributionset.unrepeatable.hint";
public static final String VAADIN_SYSTEM_SESSIONEXPIRED_CAPTION = "vaadin.system.sessionexpired.caption";
public static final String VAADIN_SYSTEM_SESSIONEXPIRED_MESSAGE = "vaadin.system.sessionexpired.message";

View File

@@ -25,6 +25,7 @@ hawkbit.server.ui.links.documentation.system-configuration-view=https://www.ecli
hawkbit.server.ui.links.documentation.targetfilter-view=https://www.eclipse.org/hawkbit/ui/#target-filter-management
hawkbit.server.ui.links.documentation.upload-view=https://www.eclipse.org/hawkbit/ui/#artifact-management
hawkbit.server.ui.links.documentation.maintenance-window-view=http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html
hawkbit.server.ui.links.documentation.distribution-set-invalidation=https://www.eclipse.org/hawkbit/ui/#distribution-set-invalidation
# UI Favicon disabled to use our Eclipse icon
spring.mvc.favicon.enabled=false

View File

@@ -255,6 +255,10 @@ label.drop.area.upload = Drop Files to upload
label.errorthreshold.option.percent = %
label.errorthreshold.option.count = Count
label.invalidate.distributionset.stop.rollouts = Stop rollouts
label.invalidate.ds.cancelation.type = Type of cancelation:
label.cancel.action.none = None
label.cancel.action.force = Forced
label.cancel.action.soft = Soft
# TextFields prefix with - textfield
textfield.name = Name
@@ -378,6 +382,9 @@ tooltip.distribution.set.pin = Pin distribution set
tooltip.invalidate.distributionset = Invalidate distribution set..
tooltip.distributionset.invalid = invalid
tooltip.distributionset.incomplete = incomplete
tooltip.distributionset.invalidate.forced = Open actions will be canceled and force quit
tooltip.distributionset.invalidate.soft = Open actions will be canceled
tooltip.distributionset.invalidate.none = Open actions will not be canceled
tooltip.in.time = In Time
# Notification messages prefix with - message
@@ -517,8 +524,10 @@ message.invalidate.distributionset.fail.singular = Distribution set {0} invalida
message.invalidate.distributionset.fail.plural = Invalidation failed for {0} distribution sets
message.invalidate.distributionset.consequences.singular = By invalidating this distribution set it can no longer be used in any assignment. All active auto assignments and optionally all active rollouts of the distribution set can be stopped as well as all existing update actions will be canceled. A summary of affected entities will be shown on the next page.
message.invalidate.distributionset.consequences.plural = By invalidating this {0} distribution sets they can no longer be used in any assignment. All active auto assignments and optionally all active rollouts of the distribution sets can be stopped as well as all existing update actions will be canceled. A summary of affected entities will be shown on the next page.
message.invalidate.distributionset.unrepeatable.hint = Note: If no cancelation type is selected, mass-cancel of actions will not be possible at a later point in time.
message.invalidate.distributionset.affected.entities.intro.singular = When you confirm the invalidation of distribution set {0} the following actions will be taken:
message.invalidate.distributionset.affected.entities.intro.plural = When you confirm the invalidation of {0} distribution sets the following actions will be taken:
message.invalidate.distributionset.affected.entities.actions = {0} action(s) will be canceled
message.invalidate.distributionset.affected.entities.rollouts = {0} rollout(s) will be stopped
message.invalidate.distributionset.affected.entities.autoassignments = {0} auto assignment(s) will be stopped