diff --git a/basic_management.py b/basic_management.py new file mode 100644 index 0000000..f916d24 --- /dev/null +++ b/basic_management.py @@ -0,0 +1,197 @@ +from docker_wrapper import Docker, NoContainersError +from typing import Dict, List +import sys +from dataclasses import dataclass +from enum import Enum, auto + + +class MenuOption(Enum): + VIEW = auto() + START = auto() + STOP = auto() + REMOVE = auto() + MENU = auto() + QUIT = auto() + + +@dataclass +class ContainerInfo: + container_id: str + image: str + command: str + created: str + status: str + ports: str + names: str + + def __str__(self) -> str: + return ( + f"Container Information:\n" + f" CONTAINER ID: {self.container_id}\n" + f" IMAGE: {self.image}\n" + f" COMMAND: {self.command}\n" + f" CREATED: {self.created}\n" + f" STATUS: {self.status}\n" + f" PORTS: {self.ports}\n" + f" NAMES: {self.names}" + ) + + +class DockerManager: + def __init__(self): + self.docker = Docker + self._menu_options = { + 'view': (MenuOption.VIEW, 'View container info'), + 'start': (MenuOption.START, 'Starts the container'), + 'stop': (MenuOption.STOP, 'Stops the container'), + 'rm': (MenuOption.REMOVE, 'Deletes the container'), + 'menu': (MenuOption.MENU, 'Back to the main menu'), + 'q': (MenuOption.QUIT, 'Quit the application') + } + + def get_container_info(self, container: str) -> ContainerInfo: + """ + Retrieves and formats container information. + + Args: + container: Name of the container + + Returns: + ContainerInfo: Structured container information + """ + info = self.docker.container_info(container) + return ContainerInfo( + container_id=info["CONTAINER ID"], + image=info["IMAGE"], + command=info["COMMAND"], + created=info["CREATED"], + status=info["STATUS"], + ports=info["PORTS"], + names=info["NAMES"] + ) + + def display_main_menu(self, containers: List[str]) -> None: + """Displays the main container selection menu.""" + print('\nSelect the container to manage:') + for idx, container in enumerate(containers): + print(f' {idx} - {container}') + print(' q - Quit') + + def display_container_menu(self, container: str) -> None: + """Displays the container management menu.""" + print(f'\nContainer: {container}\nAvailable actions:') + for cmd, (_, description) in self._menu_options.items(): + if cmd not in ['q']: # Exclude quit option from container menu + print(f' {cmd} - {description}') + + def handle_container_removal(self, container: str) -> bool: + """ + Handles the container removal process with confirmation. + + Returns: + bool: True if container was removed, False otherwise + """ + while True: + confirmation = input( + f'\nWARNING! This will DELETE {container}!\n' + f'Are you absolutely sure you want to delete {container}? (y/N): ' + ).lower() + + if confirmation in ['y', 'yes']: + print('Stopping container...') + self.docker.stop(container) + print('Deleting container...') + self.docker.rm(container) + print('Container deleted successfully') + return True + elif confirmation in ['n', 'no', '']: + print(f'Operation cancelled, returning to {container} menu...') + return False + else: + print('Invalid input. Please enter y/N') + + def validate_container_selection(self, selection: str, containers: List[str]) -> int: + """ + Validates the container selection input. + + Returns: + int: Valid container index + + Raises: + ValueError: If selection is invalid + """ + try: + index = int(selection) + if 0 <= index < len(containers): + return index + raise ValueError + except ValueError: + raise ValueError("Invalid container selection") + + def run(self) -> None: + """Main application loop.""" + try: + while True: + if not self.docker.containers_exist(): + raise NoContainersError('No containers exist! Please create a container and try again.') + + containers = self.docker.containers() + self.display_main_menu(containers) + + selection = input().strip() + if selection == 'q': + print("\nExiting application...") + sys.exit(0) + + try: + container_index = self.validate_container_selection(selection, containers) + except ValueError: + print("Invalid selection. Please try again.") + continue + + container = containers[container_index] + + while True: + self.display_container_menu(container) + action = input().strip().lower() + + if action not in self._menu_options: + print('Invalid selection. Please try again.') + continue + + option = self._menu_options[action][0] + + if option == MenuOption.MENU: + break + elif option == MenuOption.VIEW: + print(self.get_container_info(container)) + elif option == MenuOption.START: + print('Starting container...') + self.docker.start(container) + print('Container started successfully') + elif option == MenuOption.STOP: + print('Stopping container...') + self.docker.stop(container) + print('Container stopped successfully') + elif option == MenuOption.REMOVE: + if self.handle_container_removal(container): + break + elif option == MenuOption.QUIT: + print("\nExiting application...") + sys.exit(0) + + except NoContainersError as e: + print(f'Error: {e}') + print('No containers found. Exiting...') + sys.exit(1) + except KeyboardInterrupt: + print("\nOperation cancelled by user. Exiting...") + sys.exit(0) + except Exception as e: + print(f"An unexpected error occurred: {e}") + sys.exit(1) + + +if __name__ == "__main__": + manager = DockerManager() + manager.run() \ No newline at end of file