From 58aea47921d8f5f7a156ec8f4c2125bd9b93d9fe Mon Sep 17 00:00:00 2001 From: Firq Date: Sat, 6 Jul 2024 00:16:41 +0200 Subject: [PATCH] Refactored code to be more concise --- dockge_cli/client/commandprovider/__init__.py | 0 dockge_cli/client/commandprovider/factory.py | 7 ----- dockge_cli/client/commands/__init__.py | 4 +++ .../bindings.py => commands/functions.py} | 23 +++++++++------- .../descriptors.py => commands/mappings.py} | 26 +++++++++---------- dockge_cli/client/parser.py | 2 +- dockge_cli/client/run.py | 4 +-- dockge_cli/client/utils.py | 4 +-- dockge_cli/models/__init__.py | 2 +- dockge_cli/models/codes.py | 9 +++---- dockge_cli/models/{commands.py => command.py} | 2 +- dockge_cli/service/communicate.py | 14 +++++++--- dockge_cli/service/storage.py | 13 ++++++++++ 13 files changed, 64 insertions(+), 46 deletions(-) delete mode 100644 dockge_cli/client/commandprovider/__init__.py delete mode 100644 dockge_cli/client/commandprovider/factory.py create mode 100644 dockge_cli/client/commands/__init__.py rename dockge_cli/client/{commandprovider/bindings.py => commands/functions.py} (87%) rename dockge_cli/client/{commandprovider/descriptors.py => commands/mappings.py} (79%) rename dockge_cli/models/{commands.py => command.py} (92%) diff --git a/dockge_cli/client/commandprovider/__init__.py b/dockge_cli/client/commandprovider/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/dockge_cli/client/commandprovider/factory.py b/dockge_cli/client/commandprovider/factory.py deleted file mode 100644 index 6bb2fbe..0000000 --- a/dockge_cli/client/commandprovider/factory.py +++ /dev/null @@ -1,7 +0,0 @@ -from ...models import Command -from .descriptors import mapping - -commands: dict[str, Command] = {} - -for descriptor in mapping: - commands.update({ descriptor.cmd: descriptor }) diff --git a/dockge_cli/client/commands/__init__.py b/dockge_cli/client/commands/__init__.py new file mode 100644 index 0000000..61eb6fc --- /dev/null +++ b/dockge_cli/client/commands/__init__.py @@ -0,0 +1,4 @@ +from ...models import Command +from .mappings import mapping + +commands: dict[str, Command] = { c.cmd: c for c in mapping } diff --git a/dockge_cli/client/commandprovider/bindings.py b/dockge_cli/client/commands/functions.py similarity index 87% rename from dockge_cli/client/commandprovider/bindings.py rename to dockge_cli/client/commands/functions.py index c29c3ab..daa0ed2 100644 --- a/dockge_cli/client/commandprovider/bindings.py +++ b/dockge_cli/client/commands/functions.py @@ -4,15 +4,18 @@ from getpass import getpass from ...models import Credentials from ...service import storage from ...service.communicate import DockgeConnection -from ..utils import stack_formatter, status_formatter, generic_formatter, get_credential_parser +from ..utils import stack_formatter, status_formatter, generic_formatter, credential_parser_factory -class ExecutionCommands(): +class FunctionBindings(): """ Helper class that provides all the static methods in an organized way This is an abstraction layer of the CLI, as those functions only do little preprocessing before calling the actural DockgeConnection """ @staticmethod def __setup(): + """ + Creates a connection and logs into Dockge + """ con = DockgeConnection() con.connect_and_login() return con @@ -37,7 +40,7 @@ class ExecutionCommands(): login command binding """ if len(extra_args) > 0: - credentials = get_credential_parser().parse_args(extra_args, namespace=Credentials) + credentials = credential_parser_factory().parse_args(extra_args, namespace=Credentials) storage.put("username", credentials.username, encoded=True) storage.put("password", credentials.password, encoded=True) return @@ -64,7 +67,7 @@ class ExecutionCommands(): """ list command binding """ - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() stack_formatter(con.list_stacks()) con.disconnect() @@ -75,7 +78,7 @@ class ExecutionCommands(): """ if extra_args is None: raise ValueError - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() status_formatter(con.list_stack(extra_args[0])) con.disconnect() @@ -86,7 +89,7 @@ class ExecutionCommands(): """ if extra_args is None: raise ValueError - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() generic_formatter(con.restart(extra_args[0])) con.disconnect() @@ -97,7 +100,7 @@ class ExecutionCommands(): """ if extra_args is None: raise ValueError - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() generic_formatter(con.update(extra_args[0])) con.disconnect() @@ -108,7 +111,7 @@ class ExecutionCommands(): """ if extra_args is None: raise ValueError - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() generic_formatter(con.stop(extra_args[0])) con.disconnect() @@ -119,7 +122,7 @@ class ExecutionCommands(): """ if extra_args is None: raise ValueError - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() generic_formatter(con.start(extra_args[0])) con.disconnect() @@ -130,7 +133,7 @@ class ExecutionCommands(): """ if extra_args is None: raise ValueError - con = ExecutionCommands.__setup() + con = FunctionBindings.__setup() generic_formatter(con.down(extra_args[0])) con.disconnect() diff --git a/dockge_cli/client/commandprovider/descriptors.py b/dockge_cli/client/commands/mappings.py similarity index 79% rename from dockge_cli/client/commandprovider/descriptors.py rename to dockge_cli/client/commands/mappings.py index 10e60f3..a6ca52f 100644 --- a/dockge_cli/client/commandprovider/descriptors.py +++ b/dockge_cli/client/commands/mappings.py @@ -1,6 +1,6 @@ from typing import List from ...models import Command -from .bindings import ExecutionCommands +from .functions import FunctionBindings mapping: List[Command] = [ Command( @@ -8,83 +8,83 @@ mapping: List[Command] = [ description="Sets and gets the URI of the dockge instance. Remove any unnecessary subdomains/protocols from the URI", args=1, optional=True, - bind=ExecutionCommands.host + func=FunctionBindings.host ), Command( cmd="login", description="Logs into a given dockge account, either with an interactive dialogue or by passing --user and --password", args=2, optional=True, - bind=ExecutionCommands.login + func=FunctionBindings.login ), Command( cmd="logout", description="Removes the credentials from the local storage.", args=0, optional=False, - bind=ExecutionCommands.logout + func=FunctionBindings.logout ), Command( cmd="list", description="Lists all available stacks with their status", args=0, optional=False, - bind=ExecutionCommands.list + func=FunctionBindings.list ), Command( cmd="status", description="Returns the status of one stack", args=1, optional=False, - bind=ExecutionCommands.status + func=FunctionBindings.status ), Command( cmd="restart", description="Restarts a given stack", args=1, optional=False, - bind=ExecutionCommands.restart + func=FunctionBindings.restart ), Command( cmd="start", description="Starts a given stack", args=1, optional=False, - bind=ExecutionCommands.start + func=FunctionBindings.start ), Command( cmd="stop", description="Stops a given stack", args=1, optional=False, - bind=ExecutionCommands.stop + func=FunctionBindings.stop ), Command( cmd="down", description="Stop & Downs a given stack", args=1, optional=False, - bind=ExecutionCommands.down + func=FunctionBindings.down ), Command( cmd="update", description="Updates a stack", args=1, optional=False, - bind=ExecutionCommands.update + func=FunctionBindings.update ), Command( cmd="exit", description="Exits the CLI - this will reset all settings, including credentials and host", args=0, optional=False, - bind=ExecutionCommands.exit + func=FunctionBindings.exit ), Command( cmd="help", description="Displays helping hints for commands", args=1, optional=True, - bind=ExecutionCommands.help + func=FunctionBindings.help ) ] diff --git a/dockge_cli/client/parser.py b/dockge_cli/client/parser.py index 9e68f3e..f84628b 100644 --- a/dockge_cli/client/parser.py +++ b/dockge_cli/client/parser.py @@ -3,7 +3,7 @@ import sys from .. import __version__ from ..models import Arguments -from .commandprovider.factory import commands +from .commands import commands def parse_arguments(): """ diff --git a/dockge_cli/client/run.py b/dockge_cli/client/run.py index bd5e7d8..22d0a2a 100644 --- a/dockge_cli/client/run.py +++ b/dockge_cli/client/run.py @@ -1,4 +1,4 @@ -from .commandprovider.factory import commands +from .commands import commands def display_help(extra_args): """ @@ -32,4 +32,4 @@ def run(command, args): display_help(args) return - c.bind(args) + c.func(args) diff --git a/dockge_cli/client/utils.py b/dockge_cli/client/utils.py index 9ac97bc..ebddf26 100644 --- a/dockge_cli/client/utils.py +++ b/dockge_cli/client/utils.py @@ -2,7 +2,7 @@ import argparse from tabulate import tabulate from ..models import StackStatus -def get_credential_parser(): +def credential_parser_factory(): """ Creates a new parser for login credentials """ @@ -23,7 +23,7 @@ def stack_formatter(stacks): table, headers = [], ["Stackname", "Status"] for key, val in stacks["stackList"].items(): - table.append([key, StackStatus(val['status']).name]) + table.append([key, StackStatus(val['status']).name.lower()]) print(tabulate(table, headers=headers, tablefmt="github"), "\n") diff --git a/dockge_cli/models/__init__.py b/dockge_cli/models/__init__.py index e412edf..ac7af80 100644 --- a/dockge_cli/models/__init__.py +++ b/dockge_cli/models/__init__.py @@ -1,3 +1,3 @@ from .codes import StackStatus -from .commands import Command +from .command import Command from .parser import Arguments, Credentials diff --git a/dockge_cli/models/codes.py b/dockge_cli/models/codes.py index 4c3799b..569ce1d 100644 --- a/dockge_cli/models/codes.py +++ b/dockge_cli/models/codes.py @@ -2,9 +2,8 @@ from enum import Enum class StackStatus(Enum): """ - mapping codes for status vs text + mapping for plaintext vs statuscode """ - # pylint: disable=invalid-name - inactive = 1 - running = 3 - exited = 4 + INACTIVE = 1 + RUNNING = 3 + EXITED = 4 diff --git a/dockge_cli/models/commands.py b/dockge_cli/models/command.py similarity index 92% rename from dockge_cli/models/commands.py rename to dockge_cli/models/command.py index d7a8123..61a13b3 100644 --- a/dockge_cli/models/commands.py +++ b/dockge_cli/models/command.py @@ -6,7 +6,7 @@ class Command(BaseModel): Basic command structure for the CLI to automatically generate valid commands """ cmd: str - bind: Callable + func: Callable args: int optional: bool description: str diff --git a/dockge_cli/service/communicate.py b/dockge_cli/service/communicate.py index b534174..9fb063b 100644 --- a/dockge_cli/service/communicate.py +++ b/dockge_cli/service/communicate.py @@ -32,7 +32,7 @@ class DockgeConnection: def _init_events(self): @self._sio.event def connect(): - self.connect() + self.login() print("Connected!") @self._sio.event @@ -70,10 +70,11 @@ class DockgeConnection: """ Connect to the websocket """ + # Dockge uses Socket.io for the websockets, so this URI and params are always the same self._sio.connect(f"https://{self._host}/socket.io/", transports=['websocket']) - self.connect() + self.login() - def connect(self): + def login(self): """ Log into dockge using basicauth Retries 5 times when timeouts occur @@ -84,6 +85,11 @@ class DockgeConnection: data = None retry, count = True, 0 + if not storage.exists("username"): + raise ValueError("Missing username") + if not storage.exists("password"): + raise ValueError("Missing password") + while retry and count < 5: try: data = self._sio.call( @@ -91,7 +97,7 @@ class DockgeConnection: { "username": storage.get("username", encoded=True), "password": storage.get("password", encoded=True), - "token":"" + "token": "" }, timeout=5 ) diff --git a/dockge_cli/service/storage.py b/dockge_cli/service/storage.py index 20ffb85..f9230fa 100644 --- a/dockge_cli/service/storage.py +++ b/dockge_cli/service/storage.py @@ -16,6 +16,19 @@ def fileexists(): with open(_file, 'a', encoding="utf-8"): os.utime(_file, None) +def exists(key: str) -> bool: + """ + Checks if a given key exists in the storage file + """ + if not _file.exists(): + return False + + with open(_file, "r", encoding="utf-8") as file: + content: dict[str, str] = yaml.load(file, Loader=yaml.SafeLoader) + + return key in content + + def put(key: str, value: str, encoded=False): """ Puts a given value with a given key into the storage file