maestro/basic_management.py
2024-12-05 23:39:17 +05:30

198 lines
No EOL
6.7 KiB
Python

#!/usr/bin/env python3
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()