Pylint settings
This commit is contained in:
parent
be932ea9c4
commit
a99b81b0c7
12 changed files with 140 additions and 3 deletions
2
dockge_cli/__main__.py
Normal file
2
dockge_cli/__main__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from .dockge_cli import cli
|
||||
cli()
|
|
@ -7,6 +7,10 @@ from ...service.communicate import DockgeConnection
|
|||
from ..utils import stack_formatter, status_formatter, generic_formatter, get_credential_parser
|
||||
|
||||
class ExecutionCommands():
|
||||
"""
|
||||
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():
|
||||
con = DockgeConnection()
|
||||
|
@ -15,6 +19,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def host(extra_args):
|
||||
"""
|
||||
host command binding
|
||||
"""
|
||||
if len(extra_args) > 0:
|
||||
res = urlparse(extra_args[0])
|
||||
if all([res.scheme, res.netloc]):
|
||||
|
@ -26,6 +33,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def login(extra_args):
|
||||
"""
|
||||
login command binding
|
||||
"""
|
||||
if len(extra_args) > 0:
|
||||
credentials = get_credential_parser().parse_args(extra_args, namespace=Credentials)
|
||||
storage.put("username", credentials.username, encoded=True)
|
||||
|
@ -36,21 +46,33 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def logout(_):
|
||||
"""
|
||||
logout command binding
|
||||
"""
|
||||
storage.remove("username")
|
||||
storage.remove("password")
|
||||
|
||||
@staticmethod
|
||||
def exit(_):
|
||||
"""
|
||||
exit command binding
|
||||
"""
|
||||
storage.clear()
|
||||
|
||||
@staticmethod
|
||||
def list(_):
|
||||
"""
|
||||
list command binding
|
||||
"""
|
||||
con = ExecutionCommands.__setup()
|
||||
stack_formatter(con.list_stacks())
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def status(extra_args):
|
||||
"""
|
||||
status command binding
|
||||
"""
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
|
@ -59,6 +81,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def restart(extra_args):
|
||||
"""
|
||||
restart command binding
|
||||
"""
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
|
@ -67,6 +92,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def update(extra_args):
|
||||
"""
|
||||
update command binding
|
||||
"""
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
|
@ -75,6 +103,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def stop(extra_args):
|
||||
"""
|
||||
stop command binding
|
||||
"""
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
|
@ -83,6 +114,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def start(extra_args):
|
||||
"""
|
||||
start command binding
|
||||
"""
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
|
@ -91,6 +125,9 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def down(extra_args):
|
||||
"""
|
||||
down command binding
|
||||
"""
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
|
@ -99,4 +136,7 @@ class ExecutionCommands():
|
|||
|
||||
@staticmethod
|
||||
def help():
|
||||
"""
|
||||
exit command binding - This should never be invoked
|
||||
"""
|
||||
print("WTF")
|
||||
|
|
|
@ -6,6 +6,10 @@ from ..models import Arguments
|
|||
from .commandprovider.factory import commands
|
||||
|
||||
def parse_arguments():
|
||||
"""
|
||||
Create a parser and parse the arguments of sys.argv based on the Arguments Namespace
|
||||
Returns arguments and extra arguments separately
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="dockge_cli",
|
||||
description="CLI interface for interacting with Dockge",)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from .commandprovider.factory import commands
|
||||
|
||||
def display_help(extra_args):
|
||||
"""
|
||||
Display help dialogues for each command
|
||||
"""
|
||||
if not extra_args:
|
||||
print(f"{commands['help'].description}")
|
||||
return
|
||||
|
@ -11,6 +14,10 @@ def display_help(extra_args):
|
|||
print(f"{commands[extra_args[0]].description}")
|
||||
|
||||
def run(command, args):
|
||||
"""
|
||||
Runs a given command with the provided args
|
||||
Alsso automatically maps the given command string to the correct Command class
|
||||
"""
|
||||
if command not in commands:
|
||||
raise ValueError("Invalid Command")
|
||||
|
||||
|
@ -25,4 +32,4 @@ def run(command, args):
|
|||
display_help(args)
|
||||
return
|
||||
|
||||
c.binding(args)
|
||||
c.bind(args)
|
||||
|
|
|
@ -3,6 +3,9 @@ from tabulate import tabulate
|
|||
from ..models import StackStatus
|
||||
|
||||
def get_credential_parser():
|
||||
"""
|
||||
Creates a new parser for login credentials
|
||||
"""
|
||||
credentialparser = argparse.ArgumentParser(
|
||||
prog="login",
|
||||
description="Subparser for login credentials provided by CI"
|
||||
|
@ -12,6 +15,9 @@ def get_credential_parser():
|
|||
return credentialparser
|
||||
|
||||
def stack_formatter(stacks):
|
||||
"""
|
||||
Prints a given stack list formatted as a table
|
||||
"""
|
||||
if not stacks["ok"]:
|
||||
raise RuntimeError("Stack GET didn't work")
|
||||
|
||||
|
@ -22,11 +28,17 @@ def stack_formatter(stacks):
|
|||
print(tabulate(table, headers=headers, tablefmt="github"), "\n")
|
||||
|
||||
def status_formatter(status):
|
||||
"""
|
||||
Prints the status for a given stack
|
||||
"""
|
||||
print(f"Is Stack Ok? {'Yes' if status['ok'] else 'No'}")
|
||||
headers = ["Container", "Status"]
|
||||
table = [[k, v] for k, v in status["serviceStatusList"].items()]
|
||||
print(tabulate(table, headers=headers, tablefmt="github"), "\n")
|
||||
|
||||
def generic_formatter(status):
|
||||
"""
|
||||
Prints a generic dockge message
|
||||
"""
|
||||
print(f"Is Ok? {'Yes' if status['ok'] else 'No'}")
|
||||
print(f"Stack status: {status['msg']}")
|
||||
|
|
|
@ -2,5 +2,8 @@ from .client.parser import parse_arguments
|
|||
from .client.run import run
|
||||
|
||||
def cli():
|
||||
"""
|
||||
main function for cli invocation
|
||||
"""
|
||||
command, args= parse_arguments()
|
||||
run(command.command, args)
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from enum import Enum
|
||||
|
||||
class StackStatus(Enum):
|
||||
"""
|
||||
mapping codes for status vs text
|
||||
"""
|
||||
# pylint: disable=invalid-name
|
||||
inactive = 1
|
||||
running = 3
|
||||
|
|
|
@ -2,6 +2,9 @@ from typing import Callable
|
|||
from pydantic import BaseModel
|
||||
|
||||
class Command(BaseModel):
|
||||
"""
|
||||
Basic command structure for the CLI to automatically generate valid commands
|
||||
"""
|
||||
cmd: str
|
||||
bind: Callable
|
||||
args: int
|
||||
|
|
|
@ -2,9 +2,15 @@ import argparse
|
|||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class Arguments(argparse.Namespace):
|
||||
"""
|
||||
Default Arguments when calling the CLI
|
||||
"""
|
||||
command: str
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class Credentials(argparse.Namespace):
|
||||
"""
|
||||
Special Argument Namespace for login credentials of the login commands
|
||||
"""
|
||||
username: str
|
||||
password: str
|
||||
|
|
|
@ -5,8 +5,14 @@ import socketio.exceptions
|
|||
from . import storage
|
||||
|
||||
class DockgeConnection:
|
||||
"""
|
||||
Provider class for Dockge
|
||||
Provides all the functionality for connecting, logging in and executing commands
|
||||
"""
|
||||
class LoginException(BaseException):
|
||||
pass
|
||||
"""
|
||||
Special exception when login fails too often
|
||||
"""
|
||||
|
||||
_sio: socketio.Client
|
||||
_host: str
|
||||
|
@ -61,10 +67,17 @@ class DockgeConnection:
|
|||
|
||||
# Functions
|
||||
def connect_and_login(self):
|
||||
"""
|
||||
Connect to the websocket
|
||||
"""
|
||||
self._sio.connect(f"https://{self._host}/socket.io/", transports=['websocket'])
|
||||
self.connect()
|
||||
|
||||
def connect(self):
|
||||
"""
|
||||
Log into dockge using basicauth
|
||||
Retries 5 times when timeouts occur
|
||||
"""
|
||||
if self._logged_in:
|
||||
return
|
||||
|
||||
|
@ -92,6 +105,9 @@ class DockgeConnection:
|
|||
self._logged_in = True
|
||||
|
||||
def list_stacks(self):
|
||||
"""
|
||||
Requests stack list from dockge, returns list when event was sent
|
||||
"""
|
||||
self._sio.emit("agent", ("", "requestStackList"))
|
||||
while self._stacklist is None:
|
||||
time.sleep(0.5)
|
||||
|
@ -100,29 +116,50 @@ class DockgeConnection:
|
|||
return retval
|
||||
|
||||
def list_stack(self, name: str):
|
||||
"""
|
||||
Lists status for a stack
|
||||
"""
|
||||
ret = self._sio.call("agent", ("", "serviceStatusList", name), timeout=5)
|
||||
return ret
|
||||
|
||||
def restart(self, name):
|
||||
"""
|
||||
Restarts a given stack
|
||||
"""
|
||||
ret = self._sio.call("agent", ("", "restartStack", name), timeout=10)
|
||||
return ret
|
||||
|
||||
def update(self, name):
|
||||
"""
|
||||
Updates a given stack
|
||||
"""
|
||||
ret = self._sio.call("agent", ("", "updateStack", name), timeout=10)
|
||||
return ret
|
||||
|
||||
def stop(self, name):
|
||||
"""
|
||||
Stops a given stack
|
||||
"""
|
||||
ret = self._sio.call("agent", ("", "stopStack", name), timeout=10)
|
||||
return ret
|
||||
|
||||
def start(self, name):
|
||||
"""
|
||||
Starts a given stack
|
||||
"""
|
||||
ret = self._sio.call("agent", ("", "startStack", name), timeout=10)
|
||||
return ret
|
||||
|
||||
def down(self, name):
|
||||
"""
|
||||
Stops and downs a given stack
|
||||
"""
|
||||
ret = self._sio.call("agent", ("", "downStack", name), timeout=10)
|
||||
return ret
|
||||
|
||||
def disconnect(self):
|
||||
"""
|
||||
Logs out of dockge
|
||||
"""
|
||||
self._sio.emit("logout")
|
||||
self._sio.disconnect()
|
||||
|
|
|
@ -9,11 +9,18 @@ _file = _storagepath / "storage.yaml"
|
|||
_storagepath.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
def fileexists():
|
||||
"""
|
||||
Checks if storage file does exist, creates it when necessary
|
||||
"""
|
||||
if not _file.exists():
|
||||
with open(_file, 'a', encoding="utf-8"):
|
||||
os.utime(_file, None)
|
||||
|
||||
def put(key: str, value: str, encoded=False):
|
||||
"""
|
||||
Puts a given value with a given key into the storage file
|
||||
Encodes the data as base64 when encoded is set to true
|
||||
"""
|
||||
fileexists()
|
||||
with open(_file, "r+", encoding="utf-8") as file:
|
||||
content: dict[str, str] = yaml.load(file, Loader=yaml.SafeLoader) or {}
|
||||
|
@ -22,6 +29,9 @@ def put(key: str, value: str, encoded=False):
|
|||
yaml.dump(content, file, Dumper=yaml.SafeDumper)
|
||||
|
||||
def remove(key: str):
|
||||
"""
|
||||
Removed a given key from the storage file
|
||||
"""
|
||||
fileexists()
|
||||
with open(_file, "r", encoding="utf-8") as file:
|
||||
content: dict[str, str] = yaml.load(file, Loader=yaml.SafeLoader) or {}
|
||||
|
@ -30,6 +40,10 @@ def remove(key: str):
|
|||
yaml.dump(content, file, Dumper=yaml.SafeDumper)
|
||||
|
||||
def get(key: str, encoded=False):
|
||||
"""
|
||||
Retrieves a value for a given key from the storage file
|
||||
If the value was encoded, encoded needs to be set True to decode it again
|
||||
"""
|
||||
value: str | None = None
|
||||
if not _file.exists():
|
||||
return None
|
||||
|
@ -41,4 +55,7 @@ def get(key: str, encoded=False):
|
|||
return base64.b64decode(value).decode() if encoded else value
|
||||
|
||||
def clear():
|
||||
"""
|
||||
Deletes the storage file
|
||||
"""
|
||||
_file.unlink()
|
||||
|
|
|
@ -42,7 +42,10 @@ typing = [
|
|||
]
|
||||
|
||||
[tool.pylint."MAIN"]
|
||||
disable = [ "line-too-long", "missing-module-docstring", "missing-function-docstring", "missing-class-docstring" ]
|
||||
disable = [
|
||||
"line-too-long",
|
||||
"missing-module-docstring",
|
||||
]
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.11"
|
||||
|
|
Loading…
Reference in a new issue