From 6e96d77a7f93a65cd8568551b4a1e7b4d604614b Mon Sep 17 00:00:00 2001 From: Shreyas Damle <57351398+shreyas-damle@users.noreply.github.com> Date: Mon, 22 Jul 2024 17:45:49 +0530 Subject: [PATCH] Add Delete App (#416) * Delete Application API Integrated * Added Unit test cases for delete app * Ruff fixes and UT fixes. * Incorporated review comments. --- pebblo/app/api/local_ui_api.py | 6 +++++ pebblo/app/routers/local_ui_routers.py | 3 +++ pebblo/app/service/local_ui_service.py | 21 ++++++++++++++++ pebblo/app/utils/utils.py | 35 ++++++++++++++++++++++++++ tests/app/test_utils.py | 30 +++++++++++++++++++++- 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/pebblo/app/api/local_ui_api.py b/pebblo/app/api/local_ui_api.py index 224294b5..ad46afad 100644 --- a/pebblo/app/api/local_ui_api.py +++ b/pebblo/app/api/local_ui_api.py @@ -61,6 +61,12 @@ def get_report(app_name: str): # Return the FileResponse object return response + @staticmethod + def delete_app(request: Request, app_name: str): + app_data = AppData() + result = app_data.delete_application(app_name) + return result + @staticmethod def page_not_found(request: Request): return templates.TemplateResponse( diff --git a/pebblo/app/routers/local_ui_routers.py b/pebblo/app/routers/local_ui_routers.py index ea21e80d..825e627d 100644 --- a/pebblo/app/routers/local_ui_routers.py +++ b/pebblo/app/routers/local_ui_routers.py @@ -27,3 +27,6 @@ local_ui_router_instance.router.add_api_route( "/not-found/", App.page_not_found, methods=["GET"], response_class=HTMLResponse ) +local_ui_router_instance.router.add_api_route( + "/app/delete/", App.delete_app, methods=["DELETE"] +) diff --git a/pebblo/app/service/local_ui_service.py b/pebblo/app/service/local_ui_service.py index 0f88b8bb..b24adae5 100644 --- a/pebblo/app/service/local_ui_service.py +++ b/pebblo/app/service/local_ui_service.py @@ -6,6 +6,7 @@ import os from dateutil import parser +from fastapi import status from pebblo.app.enums.enums import CacheDir from pebblo.app.libs.logger import logger @@ -17,6 +18,7 @@ RetrievalAppListDetails, ) from pebblo.app.utils.utils import ( + delete_directory, get_document_with_findings_data, get_full_path, get_pebblo_server_version, @@ -322,6 +324,25 @@ def get_app_details(self, app_dir): except Exception as ex: logger.error(f"Error in app detail. Error: {ex}") + @staticmethod + def delete_application(app_name): + """ + Delete an app + """ + try: + # Path to application directory + app_dir_path = f"{CacheDir.HOME_DIR.value}/{app_name}" + logger.debug(f"App directory path: {app_dir_path}") + response = delete_directory(app_dir_path, app_name) + return response + except Exception as ex: + error_message = f"Error in delete application. Error: {ex}" + logger.error(error_message) + return { + "message": error_message, + "status_code": status.HTTP_500_INTERNAL_SERVER_ERROR, + } + @staticmethod def get_latest_load_id(load_ids, app_dir): """ diff --git a/pebblo/app/utils/utils.py b/pebblo/app/utils/utils.py index 7e185449..c9361d71 100644 --- a/pebblo/app/utils/utils.py +++ b/pebblo/app/utils/utils.py @@ -2,6 +2,9 @@ import time from json import JSONEncoder, dump from os import getcwd, makedirs, path, remove +from shutil import rmtree + +from fastapi import status from pebblo.app.libs.logger import logger @@ -245,3 +248,35 @@ def release_lock(lock_file_path: str): logger.debug(f"Lock Released. {full_lock_file_path}") except FileNotFoundError: pass # The lock file doesn't exist, nothing to release + + +def delete_directory(app_path, app_name=None): + message = "" + result = {} + try: + full_path = get_full_path(app_path) + logger.info(f"DirPath: {full_path}") + rmtree(full_path) + message = f"Application {app_name} has been deleted." + logger.info(message) + result = {"message": message, "status_code": status.HTTP_200_OK} + except FileNotFoundError: + message = f"Application {app_name} does not exist." + result = {"message": message, "status_code": status.HTTP_404_NOT_FOUND} + logger.exception(message) + except PermissionError: + message = f"Permission denied: Unable to delete application {app_name}." + result = { + "message": message, + "status_code": status.HTTP_422_UNPROCESSABLE_ENTITY, + } + logger.exception(message) + except Exception as e: + message = f"Unable to delete application {app_name}, Error: {e}" + result = { + "message": message, + "status_code": status.HTTP_500_INTERNAL_SERVER_ERROR, + } + logger.exception(message) + finally: + return result diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py index 07701654..0c1565b5 100644 --- a/tests/app/test_utils.py +++ b/tests/app/test_utils.py @@ -1,6 +1,12 @@ +import tempfile + import toml -from pebblo.app.utils.utils import get_pebblo_server_version +from pebblo.app.utils.utils import ( + delete_directory, + get_full_path, + get_pebblo_server_version, +) def test_get_pebblo_server_version(): @@ -10,3 +16,25 @@ def test_get_pebblo_server_version(): pebblo_server_version = get_pebblo_server_version() assert pebblo_version == pebblo_server_version + + +def test_delete_directory(): + # make sample directory + dir_path = tempfile.mkdtemp() + full_path = get_full_path(dir_path) + response = delete_directory(full_path, dir_path) + assert response == { + "message": f"Application {dir_path} has been deleted.", + "status_code": 200, + } + + +def test_delete_directory_dir_not_exist(): + app_name = "test_dir" + dir_path = ".pebblo/test_dir" + full_path = get_full_path(dir_path) + response = delete_directory(full_path, app_name) + assert response == { + "message": f"Application {app_name} does not exist.", + "status_code": 404, + }