Skip to content

Commit 9bd521f

Browse files
committed
fix: restore active stacks with start_stack
1 parent 164b6fe commit 9bd521f

2 files changed

Lines changed: 34 additions & 4 deletions

File tree

apphub/src/services/back_manager.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,7 @@ def restore_backup(self, app_id: str, snapshot_id: str) -> None:
426426
raise CustomException(404, "Not Found", f"Stack {app_id} has no Id")
427427
portainer.up_stack(stack_id, endpoint_id)
428428
else:
429-
stack_id = stack_info.get("Id")
430-
if stack_id is None:
431-
raise CustomException(404, "Not Found", f"Stack {app_id} has no Id")
432-
portainer.up_stack(stack_id, endpoint_id)
429+
portainer.start_stack(app_id, endpoint_id)
433430

434431
self._ensure_restored_app_running(portainer, app_id, endpoint_id)
435432
logger.access(f"Started containers for app {app_id} after restore")

apphub/tests/test_backup_restore.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,17 @@ def __init__(self, stack_status, container_sequences):
4242
self.stack_status = stack_status
4343
self.container_sequences = list(container_sequences)
4444
self.up_calls = []
45+
self.start_calls = []
4546

4647
def get_stack_by_name(self, app_id, endpoint_id):
4748
return {"Id": 9, "Name": app_id, "Status": self.stack_status}
4849

4950
def up_stack(self, stack_id, endpoint_id):
5051
self.up_calls.append((stack_id, endpoint_id))
5152

53+
def start_stack(self, app_id, endpoint_id):
54+
self.start_calls.append((app_id, endpoint_id))
55+
5256
def get_containers_by_stack_name(self, app_id, endpoint_id):
5357
if self.container_sequences:
5458
return self.container_sequences.pop(0)
@@ -79,6 +83,35 @@ def test_restore_validation_uses_up_stack_for_inactive_stack(monkeypatch):
7983
portainer.up_stack(stack_info['Id'], 1)
8084

8185
assert portainer.up_calls == [(9, 1)]
86+
assert portainer.start_calls == []
87+
88+
89+
def test_restore_start_uses_start_stack_for_active_stack(monkeypatch):
90+
manager = _build_manager()
91+
portainer = FakePortainer(
92+
stack_status=1,
93+
container_sequences=[[
94+
{"Names": ["/wordpress_demo"], "State": "running"},
95+
]],
96+
)
97+
98+
monkeypatch.setattr(manager, '_check_repository', lambda: True)
99+
monkeypatch.setattr(manager, 'list_snapshots', lambda app_id: [{"id": "snap-1", "short_id": "snap-1"}])
100+
monkeypatch.setattr(manager, '_run_restic_container', lambda command, extra_volumes: '{"message_type":"summary"}')
101+
monkeypatch.setattr(manager, '_ensure_restored_app_running', lambda *args, **kwargs: None)
102+
monkeypatch.setattr(back_manager_module, 'AppManger', lambda: types.SimpleNamespace(
103+
get_app_by_id=lambda app_id: types.SimpleNamespace(
104+
endpointId=1,
105+
volumes=[{"Mountpoint": "/var/lib/docker/volumes/wordpress_demo/_data", "Name": "wordpress_demo"}],
106+
)
107+
))
108+
monkeypatch.setattr(back_manager_module, 'PortainerManager', lambda: portainer)
109+
monkeypatch.setattr(manager, '_resolve_host_path', lambda path: path)
110+
111+
manager.restore_backup('wordpress_demo', 'snap-1')
112+
113+
assert portainer.start_calls == [('wordpress_demo', 1)]
114+
assert portainer.up_calls == []
82115

83116

84117
def test_restore_validation_rejects_only_exited_runtime_containers(monkeypatch):

0 commit comments

Comments
 (0)