fix: treat OCI editor cancellation as a neutral outcome

This commit is contained in:
VAIO73
2026-10-21 07:04:41 +00:00
parent c7a134b00a
commit 90f080744a
7 changed files with 190 additions and 10 deletions
+4 -2
View File
@@ -468,7 +468,9 @@ def manage_instance(project, ui, row, action=None, lifecycle_args=(), heading=No
proposal = None
if action == 'modify':
from .recreation import edit_recreation
proposal = edit_recreation(record, ui)
proposal = edit_recreation(record, ui, cancelled_result=CANCELLED)
if proposal is CANCELLED:
return CANCELLED
if proposal is None:
return False
elif not ui.review(translate('If a newer application image is available, the container is stopped and backed up, and the backup integrity is verified. The container is then updated using the new image.\n\nIf the update fails after the container was changed, ProxMenux attempts to restore the previous installation from the backup. If the operation remains incomplete, select the application in OCI management and choose "Recover the previous installation".\n\nHost directories mounted in the container are not restored by the container backup.'),
@@ -717,7 +719,7 @@ class UnattendedUI:
# Exit codes of `manage`, read by ProxMenux Monitor.
EXIT_DONE, EXIT_FAILED, EXIT_NOT_OCI, EXIT_BUSY, EXIT_NEEDS_REVIEW, EXIT_TOO_RECENT = 0, 1, 2, 3, 4, 5
EXIT_CANCELLED = 6 # Interactive update confirmation only; never a successful update.
EXIT_CANCELLED = 6 # Explicit interactive cancellation; never a successful update.
def _image_too_recent(project, vmid, min_age_days):
+3 -3
View File
@@ -212,8 +212,8 @@ def edit_section(candidate, ui, setting):
wizard.close()
def edit_recreation(record, ui):
"""Keep a draft across independently editable settings; apply it once."""
def edit_recreation(record, ui, *, cancelled_result=None):
"""Keep a draft; optionally distinguish cancellation from an unchanged review."""
from .cli import _deployment_summary_text
candidate = copy.deepcopy(record)
selected = 'cores'
@@ -227,7 +227,7 @@ def edit_recreation(record, ui):
title=translate('Modify OCI'), show_tags=False)
if selected is None or selected == 'discard':
if not pending or ui.confirm(translate('Discard unapplied changes?'), False):
return None
return cancelled_result
selected = 'apply'
elif selected == 'apply':
if not pending:
+1 -1
View File
@@ -185,7 +185,7 @@ class ModifyDispatchTests(unittest.TestCase):
patch.object(management, '_run_lifecycle', side_effect=lifecycle):
return management.manage_instance(ROOT, ui or Mock(), row, action='modify')
def test_cancel_does_not_start_a_lifecycle_transaction(self):
def test_legacy_none_result_does_not_start_a_lifecycle_transaction(self):
lifecycle = Mock()
self.assertFalse(self.call_manager(None, lifecycle))
lifecycle.assert_not_called()