diff --git a/src/tui/managers/container_manager.py b/src/tui/managers/container_manager.py index 15d89114..1f46ff09 100644 --- a/src/tui/managers/container_manager.py +++ b/src/tui/managers/container_manager.py @@ -1127,6 +1127,39 @@ class ContainerManager: else: yield False, "Some errors occurred during service restart", False + async def clear_directory_with_container(self, path: Path) -> tuple[bool, str]: + """Clear a directory using a container to handle container-owned files. + + Args: + path: The directory to clear (contents will be deleted, directory recreated) + + Returns: + Tuple of (success, message) + """ + if not self.is_available(): + return False, "No container runtime available" + + if not path.exists(): + return True, "Directory does not exist, nothing to clear" + + path = path.absolute() + + # Use alpine container to delete files owned by container user + cmd = [ + "run", "--rm", + "-v", f"{path}:/work:Z", + "alpine", + "sh", "-c", + "rm -rf /work/* /work/.[!.]* 2>/dev/null; echo done" + ] + + success, stdout, stderr = await self._run_runtime_command(cmd) + + if success and "done" in stdout: + return True, f"Cleared {path}" + else: + return False, f"Failed to clear {path}: {stderr or 'Unknown error'}" + async def clear_opensearch_data_volume(self) -> AsyncIterator[tuple[bool, str]]: """Clear opensearch data using a temporary container with proper permissions.""" if not self.is_available(): diff --git a/src/tui/screens/monitor.py b/src/tui/screens/monitor.py index d21bbd13..570679d8 100644 --- a/src/tui/screens/monitor.py +++ b/src/tui/screens/monitor.py @@ -494,14 +494,22 @@ class MonitorScreen(Screen): flows_backup_path = flows_path / "backup" if config_path.exists(): - shutil.rmtree(config_path) + # Use container to handle files owned by container user + success, msg = await self.container_manager.clear_directory_with_container(config_path) + if not success: + # Fallback to regular rmtree if container method fails + shutil.rmtree(config_path) # Recreate empty config directory config_path.mkdir(parents=True, exist_ok=True) # Delete flow backups only if user chose to (and they actually exist) if self._check_flow_backups(): if delete_backups: - shutil.rmtree(flows_backup_path) + # Use container to handle files owned by container user + success, msg = await self.container_manager.clear_directory_with_container(flows_backup_path) + if not success: + # Fallback to regular rmtree if container method fails + shutil.rmtree(flows_backup_path) # Recreate empty backup directory flows_backup_path.mkdir(parents=True, exist_ok=True) self.notify("Flow backups deleted", severity="information")