Deleted rollouts are immutable (#475)
* Update throws read only exception if rollout is in deleting or deleted state. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com> * Fix typo. Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
|||||||
import org.eclipse.hawkbit.repository.builder.RolloutUpdate;
|
import org.eclipse.hawkbit.repository.builder.RolloutUpdate;
|
||||||
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
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.exception.RolloutIllegalStateException;
|
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||||
@@ -371,6 +372,9 @@ public interface RolloutManagement {
|
|||||||
*
|
*
|
||||||
* @throws EntityNotFoundException
|
* @throws EntityNotFoundException
|
||||||
* if rollout or DS with given IDs do not exist
|
* if rollout or DS with given IDs do not exist
|
||||||
|
* @throws EntityReadOnlyException
|
||||||
|
* if rollout is in soft deleted state, i.e. only kept as
|
||||||
|
* reference
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
|
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_WRITE)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.RolloutUpdatedEvent;
|
|||||||
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||||
@@ -895,6 +896,8 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
final GenericRolloutUpdate update = (GenericRolloutUpdate) u;
|
final GenericRolloutUpdate update = (GenericRolloutUpdate) u;
|
||||||
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(update.getId());
|
final JpaRollout rollout = getRolloutAndThrowExceptionIfNotFound(update.getId());
|
||||||
|
|
||||||
|
checkIfDeleted(update.getId(), rollout.getStatus());
|
||||||
|
|
||||||
update.getName().ifPresent(rollout::setName);
|
update.getName().ifPresent(rollout::setName);
|
||||||
update.getDescription().ifPresent(rollout::setDescription);
|
update.getDescription().ifPresent(rollout::setDescription);
|
||||||
update.getActionType().ifPresent(rollout::setActionType);
|
update.getActionType().ifPresent(rollout::setActionType);
|
||||||
@@ -910,6 +913,12 @@ public class JpaRolloutManagement extends AbstractRolloutManagement {
|
|||||||
return rolloutRepository.save(rollout);
|
return rolloutRepository.save(rollout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void checkIfDeleted(final Long rolloutId, final RolloutStatus status) {
|
||||||
|
if (RolloutStatus.DELETING.equals(status) || RolloutStatus.DELETED.equals(status)) {
|
||||||
|
throw new EntityReadOnlyException("Rollout " + rolloutId + " is soft deleted and cannot be changed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private JpaRollout getRolloutAndThrowExceptionIfNotFound(final Long rolloutId) {
|
private JpaRollout getRolloutAndThrowExceptionIfNotFound(final Long rolloutId) {
|
||||||
return rolloutRepository.findById(rolloutId)
|
return rolloutRepository.findById(rolloutId)
|
||||||
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
.orElseThrow(() -> new EntityNotFoundException(Rollout.class, rolloutId));
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
package org.eclipse.hawkbit.repository.jpa;
|
package org.eclipse.hawkbit.repository.jpa;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -36,6 +37,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
|||||||
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
import org.eclipse.hawkbit.repository.exception.ConstraintViolationException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||||
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
import org.eclipse.hawkbit.repository.exception.RolloutIllegalStateException;
|
||||||
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;
|
||||||
@@ -1519,7 +1521,13 @@ public class RolloutManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
// verify
|
// verify
|
||||||
final JpaRollout deletedRollout = rolloutRepository.findOne(createdRollout.getId());
|
final JpaRollout deletedRollout = rolloutRepository.findOne(createdRollout.getId());
|
||||||
assertThat(deletedRollout).isNotNull();
|
assertThat(deletedRollout).isNotNull();
|
||||||
|
|
||||||
assertThat(deletedRollout.getStatus()).isEqualTo(RolloutStatus.DELETED);
|
assertThat(deletedRollout.getStatus()).isEqualTo(RolloutStatus.DELETED);
|
||||||
|
assertThatExceptionOfType(EntityReadOnlyException.class)
|
||||||
|
.isThrownBy(() -> rolloutManagement
|
||||||
|
.updateRollout(entityFactory.rollout().update(createdRollout.getId()).description("test")))
|
||||||
|
.withMessageContaining("" + createdRollout.getId());
|
||||||
|
|
||||||
assertThat(rolloutManagement.findAll(pageReq, true).getContent()).hasSize(1);
|
assertThat(rolloutManagement.findAll(pageReq, true).getContent()).hasSize(1);
|
||||||
assertThat(rolloutManagement.findAll(pageReq, false).getContent()).hasSize(0);
|
assertThat(rolloutManagement.findAll(pageReq, false).getContent()).hasSize(0);
|
||||||
assertThat(rolloutGroupManagement.findAllRolloutGroupsWithDetailedStatus(createdRollout.getId(), pageReq)
|
assertThat(rolloutGroupManagement.findAllRolloutGroupsWithDetailedStatus(createdRollout.getId(), pageReq)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.builder.RolloutCreate;
|
|||||||
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
import org.eclipse.hawkbit.repository.builder.RolloutGroupCreate;
|
||||||
import org.eclipse.hawkbit.repository.builder.RolloutUpdate;
|
import org.eclipse.hawkbit.repository.builder.RolloutUpdate;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
|
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
|
||||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||||
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
import org.eclipse.hawkbit.repository.model.RepositoryModelConstants;
|
||||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||||
@@ -51,13 +52,13 @@ import org.eclipse.hawkbit.ui.management.footer.ActionTypeOptionGroupLayout.Acti
|
|||||||
import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent;
|
import org.eclipse.hawkbit.ui.rollout.event.RolloutEvent;
|
||||||
import org.eclipse.hawkbit.ui.rollout.groupschart.GroupsPieChart;
|
import org.eclipse.hawkbit.ui.rollout.groupschart.GroupsPieChart;
|
||||||
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
import org.eclipse.hawkbit.ui.utils.HawkbitCommonUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
|
||||||
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
import org.eclipse.hawkbit.ui.utils.SPDateTimeUtil;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUILabelDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
import org.eclipse.hawkbit.ui.utils.SPUIStyleDefinitions;
|
||||||
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider;
|
||||||
import org.eclipse.hawkbit.ui.utils.UINotification;
|
import org.eclipse.hawkbit.ui.utils.UINotification;
|
||||||
|
import org.eclipse.hawkbit.ui.utils.VaadinMessageSource;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
@@ -161,7 +162,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
|
|
||||||
AddUpdateRolloutWindowLayout(final RolloutManagement rolloutManagement, final TargetManagement targetManagement,
|
AddUpdateRolloutWindowLayout(final RolloutManagement rolloutManagement, final TargetManagement targetManagement,
|
||||||
final UINotification uiNotification, final UiProperties uiProperties, final EntityFactory entityFactory,
|
final UINotification uiNotification, final UiProperties uiProperties, final EntityFactory entityFactory,
|
||||||
final VaadinMessageSource i18n, final UIEventBus eventBus, final TargetFilterQueryManagement targetFilterQueryManagement) {
|
final VaadinMessageSource i18n, final UIEventBus eventBus,
|
||||||
|
final TargetFilterQueryManagement targetFilterQueryManagement) {
|
||||||
actionTypeOptionGroupLayout = new ActionTypeOptionGroupLayout(i18n);
|
actionTypeOptionGroupLayout = new ActionTypeOptionGroupLayout(i18n);
|
||||||
autoStartOptionGroupLayout = new AutoStartOptionGroupLayout(i18n);
|
autoStartOptionGroupLayout = new AutoStartOptionGroupLayout(i18n);
|
||||||
this.rolloutManagement = rolloutManagement;
|
this.rolloutManagement = rolloutManagement;
|
||||||
@@ -215,7 +217,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
|
|
||||||
private boolean duplicateCheck() {
|
private boolean duplicateCheck() {
|
||||||
if (rolloutManagement.findRolloutByName(getRolloutName()).isPresent()) {
|
if (rolloutManagement.findRolloutByName(getRolloutName()).isPresent()) {
|
||||||
uiNotification.displayValidationError(i18n.getMessage("message.rollout.duplicate.check", getRolloutName()));
|
uiNotification
|
||||||
|
.displayValidationError(i18n.getMessage("message.rollout.duplicate.check", getRolloutName()));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -242,7 +245,7 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
Rollout updatedRollout;
|
Rollout updatedRollout;
|
||||||
try {
|
try {
|
||||||
updatedRollout = rolloutManagement.updateRollout(rolloutUpdate);
|
updatedRollout = rolloutManagement.updateRollout(rolloutUpdate);
|
||||||
} catch (final EntityNotFoundException e) {
|
} catch (final EntityNotFoundException | EntityReadOnlyException e) {
|
||||||
LOGGER.warn("Rollout was deleted. Redirect to Rollouts overview.", e);
|
LOGGER.warn("Rollout was deleted. Redirect to Rollouts overview.", e);
|
||||||
uiNotification.displayWarning(
|
uiNotification.displayWarning(
|
||||||
"Rollout with name " + rolloutName.getValue() + " was deleted. Update is not poosible");
|
"Rollout with name " + rolloutName.getValue() + " was deleted. Update is not poosible");
|
||||||
@@ -258,7 +261,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
final String rolloutNameVal = getRolloutName();
|
final String rolloutNameVal = getRolloutName();
|
||||||
if (!rollout.getName().equals(rolloutNameVal)
|
if (!rollout.getName().equals(rolloutNameVal)
|
||||||
&& rolloutManagement.findRolloutByName(rolloutNameVal).isPresent()) {
|
&& rolloutManagement.findRolloutByName(rolloutNameVal).isPresent()) {
|
||||||
uiNotification.displayValidationError(i18n.getMessage("message.rollout.duplicate.check", rolloutNameVal));
|
uiNotification
|
||||||
|
.displayValidationError(i18n.getMessage("message.rollout.duplicate.check", rolloutNameVal));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -342,8 +346,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CommonDialogWindow createWindow() {
|
private CommonDialogWindow createWindow() {
|
||||||
return new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW).caption(i18n.getMessage("caption.configure.rollout"))
|
return new WindowBuilder(SPUIDefinitions.CREATE_UPDATE_WINDOW)
|
||||||
.content(this).layout(this).i18n(i18n)
|
.caption(i18n.getMessage("caption.configure.rollout")).content(this).layout(this).i18n(i18n)
|
||||||
.helpLink(uiProperties.getLinks().getDocumentation().getRolloutView())
|
.helpLink(uiProperties.getLinks().getDocumentation().getRolloutView())
|
||||||
.saveDialogCloseListener(new SaveOnDialogCloseListener()).buildCommonDialogWindow();
|
.saveDialogCloseListener(new SaveOnDialogCloseListener()).buildCommonDialogWindow();
|
||||||
}
|
}
|
||||||
@@ -533,7 +537,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
i18n.getMessage("caption.rollout.tabs.simple"));
|
i18n.getMessage("caption.rollout.tabs.simple"));
|
||||||
simpleTab.setId(UIComponentIdProvider.ROLLOUT_SIMPLE_TAB);
|
simpleTab.setId(UIComponentIdProvider.ROLLOUT_SIMPLE_TAB);
|
||||||
|
|
||||||
final TabSheet.Tab advancedTab = tabSheet.addTab(defineGroupsLayout, i18n.getMessage("caption.rollout.tabs.advanced"));
|
final TabSheet.Tab advancedTab = tabSheet.addTab(defineGroupsLayout,
|
||||||
|
i18n.getMessage("caption.rollout.tabs.advanced"));
|
||||||
advancedTab.setId(UIComponentIdProvider.ROLLOUT_ADVANCED_TAB);
|
advancedTab.setId(UIComponentIdProvider.ROLLOUT_ADVANCED_TAB);
|
||||||
|
|
||||||
tabSheet.addSelectedTabChangeListener(event -> validateGroups());
|
tabSheet.addSelectedTabChangeListener(event -> validateGroups());
|
||||||
@@ -693,8 +698,8 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
|
|
||||||
private ComboBox createTargetFilterQueryCombo() {
|
private ComboBox createTargetFilterQueryCombo() {
|
||||||
return new ComboBoxBuilder().setValueChangeListener(this::onTargetFilterChange)
|
return new ComboBoxBuilder().setValueChangeListener(this::onTargetFilterChange)
|
||||||
.setPrompt(i18n.getMessage("prompt.target.filter")).setId(UIComponentIdProvider.ROLLOUT_TARGET_FILTER_COMBO_ID)
|
.setPrompt(i18n.getMessage("prompt.target.filter"))
|
||||||
.buildCombBox();
|
.setId(UIComponentIdProvider.ROLLOUT_TARGET_FILTER_COMBO_ID).buildCombBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onTargetFilterChange(final ValueChangeEvent event) {
|
private void onTargetFilterChange(final ValueChangeEvent event) {
|
||||||
@@ -833,12 +838,13 @@ public class AddUpdateRolloutWindowLayout extends GridLayout {
|
|||||||
@Override
|
@Override
|
||||||
public void validate(final Object value) {
|
public void validate(final Object value) {
|
||||||
if (isNoOfGroupsOrTargetFilterEmpty()) {
|
if (isNoOfGroupsOrTargetFilterEmpty()) {
|
||||||
uiNotification.displayValidationError(i18n.getMessage("message.rollout.noofgroups.or.targetfilter.missing"));
|
uiNotification
|
||||||
|
.displayValidationError(i18n.getMessage("message.rollout.noofgroups.or.targetfilter.missing"));
|
||||||
} else {
|
} else {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
final int groupSize = getGroupSize();
|
final int groupSize = getGroupSize();
|
||||||
new IntegerRangeValidator(i18n.getMessage(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0, groupSize)
|
new IntegerRangeValidator(i18n.getMessage(MESSAGE_ROLLOUT_FIELD_VALUE_RANGE, 0, groupSize), 0,
|
||||||
.validate(Integer.valueOf(value.toString()));
|
groupSize).validate(Integer.valueOf(value.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user