Skip to content

Commit

Permalink
🐈 Task: Refactor ersilia clear command #1266 (#1301)
Browse files Browse the repository at this point in the history
* Added Docker image cleanup method to SimpleDocker class

* Rename Clearer Class -> Uninstaller| Added Docker Image CleanUp

* Feat: Remove Ersillia installation

* Refactor: Changed clear command to uninstall

* Feat: Removed Docker Images/ Extra Dependecies

* Corrected uninstall_cmd docstring | Cmd help

* Changed Print statements to logger.debug()

* Added log statement to cleanup_ersilia_images

* Renamed cl variable to ui

* Initialized  Logger instance for Simple Docker Class

---------

Co-authored-by: Dhanshree Arora <DhanshreeA@users.noreply.github.com>
  • Loading branch information
KimFarida and DhanshreeA authored Oct 13, 2024
1 parent c5b2651 commit a9de77c
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 53 deletions.
6 changes: 3 additions & 3 deletions ersilia/cli/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ def catalog(self):
m = importlib.import_module("ersilia.cli.commands.catalog")
m.catalog_cmd()

def clear(self):
m = importlib.import_module("ersilia.cli.commands.clear")
m.clear_cmd()
def uninstall(self):
m = importlib.import_module("ersilia.cli.commands.uninstall")
m.uninstall_cmd()

def close(self):
m = importlib.import_module("ersilia.cli.commands.close")
Expand Down
15 changes: 0 additions & 15 deletions ersilia/cli/commands/clear.py

This file was deleted.

15 changes: 15 additions & 0 deletions ersilia/cli/commands/uninstall.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from . import ersilia_cli
from ...utils.uninstall import Uninstaller


def uninstall_cmd():
"""Uninstalls all Ersilia artifacts present locally on the user's system"""

# Example usage: ersilia setup
@ersilia_cli.command(
short_help="Uninstall ersilia",
help="Uninstalls all Ersilia artifacts present locally on the user's system.",
)
def uninstall():
ui = Uninstaller()
ui.uninstall()
2 changes: 1 addition & 1 deletion ersilia/cli/create_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def create_ersilia_cli():

cmd.auth()
cmd.catalog()
cmd.clear()
cmd.uninstall()
cmd.close()
cmd.delete()
cmd.example()
Expand Down
29 changes: 0 additions & 29 deletions ersilia/utils/clear.py

This file was deleted.

34 changes: 29 additions & 5 deletions ersilia/utils/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def is_udocker_installed():
class SimpleDocker(object):
def __init__(self, use_udocker=None):
self.identifier = LongIdentifier()
self.logger = logger
if use_udocker is None:
self._with_udocker = self._use_udocker()
else:
Expand Down Expand Up @@ -303,24 +304,47 @@ def container_peak(self, model_id):
if peak_memory is not None:
return peak_memory
else:
logger.debug(
self.logger.debug(
f"Could not compute container peak memory for model {model_id}"
)
return
else:
logger.debug(f"No container found for model {model_id}")
self.logger.debug(f"No container found for model {model_id}")
return

except docker.errors.NotFound as e:
print(f"Container {container.name} not found: {e}")
self.logger.debug(f"Container {container.name} not found: {e}")
return None
except docker.errors.APIError as e:
print(f"Docker API error: {e}")
logger.debug(f"Docker API error: {e}")
return None
except Exception as e:
print(f"An error occurred: {e}")
self.logger.debug(f"An error occurred: {e}")
return None

def cleanup_ersilia_images(self):
"""Remove all Ersilia-related Docker images"""
if self._with_udocker:
self.logger.warning("Docker cleanup not supported with udocker")
return

try:
images_dict = self.images()

if not images_dict:
logger.info("No Docker images found")
return

for image_name, image_id in images_dict.items():
if DOCKERHUB_ORG in image_name:
try:
logger.info(f"Removing Docker image: {image_name}")
self.delete(*self._splitter(image_name))
except Exception as e:
logger.error(f"Failed to remove Docker image {image_name}: {e}")

except Exception as e:
self.logger.error(f"Failed to cleanup Docker images: {e}")

class SimpleDockerfileParser(DockerfileParser):
def __init__(self, path):
Expand Down
76 changes: 76 additions & 0 deletions ersilia/utils/uninstall.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import os
import shutil
import subprocess

from .conda import SimpleConda
from .docker import SimpleDocker
from ..default import EOS, BENTOML_PATH
from .logging import logger


class Uninstaller(object):
def __init__(self):
self.docker_cleaner = SimpleDocker()

def _uninstall_ersilia_package(self):
"""Uninstall the Ersilia package if installed via pip."""
try:
logger.info("Uninstalling Ersilia package...")
subprocess.run(["pip", "uninstall", "-y", "ersilia"], check=True)
logger.info("Ersilia package uninstalled successfully.")
except subprocess.CalledProcessError as e:
logger.error(f"Failed to uninstall Ersilia package: {e}")

def _directories(self):
"""Remove additional directories."""
dirs_to_remove = [EOS, BENTOML_PATH]
for dir in dirs_to_remove:
if os.path.exists(dir):
try:
logger.info(f"Removing directory: {dir}...")
shutil.rmtree(dir)
logger.info(f"Directory {dir} removed successfully.")
except Exception as e:
logger.error(f"Failed to remove directory {dir}: {e}")

def _conda(self):
sc = SimpleConda()

for env in sc._env_list():
if env.startswith("#"):
continue
if not env.startswith("eos"):
continue
env = env.split(" ")[0]
if len(env.split("-")[0]) == 7:
try:
logger.info(f"Removing conda environment: {env}")
sc.delete(env)
except Exception as e:
logger.error(f"Failed to remove conda environment {env}: {e}")


env_name = "ersilia"

try:
logger.info(f"Removing Conda environment: {env_name}...")
sc.delete(env_name)
logger.info(f"Conda environment {env_name} removed successfully.")
except Exception as e:
logger.error(f"Failed to remove Conda environment {env_name}: {e}")

def uninstall(self):
"""Main uninstallation method"""

try:
logger.info("Starting Ersillia uninstallation...")

self.docker_cleaner.cleanup_ersilia_images()
self._uninstall_ersilia_package()
self._conda()
self._directories()

logger.info("Ersilia uninstallation completed")
except Exception as e:
logger.error(f"Uninstallation failed: {e}")
raise

0 comments on commit a9de77c

Please sign in to comment.