Improved typing, refactored code, fixed some issues
This commit is contained in:
parent
06cece6242
commit
d3e5d4ae56
16 changed files with 59 additions and 72 deletions
dockge_cli/client
0
dockge_cli/client/__init__.py
Normal file
0
dockge_cli/client/__init__.py
Normal file
0
dockge_cli/client/commandprovider/__init__.py
Normal file
0
dockge_cli/client/commandprovider/__init__.py
Normal file
102
dockge_cli/client/commandprovider/bindings.py
Normal file
102
dockge_cli/client/commandprovider/bindings.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
from urllib.parse import urlparse
|
||||
from getpass import getpass
|
||||
|
||||
from ...models.parser import Credentials
|
||||
from ...service import storage
|
||||
from ..utils import stack_formatter, status_formatter, generic_formatter, get_credential_parser
|
||||
from ...service.communicate import DockgeConnection
|
||||
|
||||
class ExecutionCommands():
|
||||
@staticmethod
|
||||
def __setup():
|
||||
con = DockgeConnection()
|
||||
con.connect_and_login()
|
||||
return con
|
||||
|
||||
@staticmethod
|
||||
def host(extra_args):
|
||||
if len(extra_args) > 0:
|
||||
res = urlparse(extra_args[0])
|
||||
if all([res.scheme, res.netloc]):
|
||||
host = extra_args[0].rstrip("/").replace("https://", "").replace("wss://", "")
|
||||
storage.put("host", host)
|
||||
else:
|
||||
raise ValueError(f"Malformed URL {extra_args[0]}")
|
||||
print(storage.get("host"))
|
||||
|
||||
@staticmethod
|
||||
def login(extra_args):
|
||||
if len(extra_args) > 0:
|
||||
credentials = get_credential_parser().parse_args(extra_args, namespace=Credentials)
|
||||
storage.put("username", credentials.username, encoded=True)
|
||||
storage.put("password", credentials.password, encoded=True)
|
||||
return
|
||||
storage.put("username", input("Username: "), encoded=True)
|
||||
storage.put("password", getpass("Password: "), encoded=True)
|
||||
|
||||
@staticmethod
|
||||
def logout(_):
|
||||
storage.remove("username")
|
||||
storage.remove("password")
|
||||
|
||||
@staticmethod
|
||||
def exit(_):
|
||||
storage.clear()
|
||||
|
||||
@staticmethod
|
||||
def list(_):
|
||||
con = ExecutionCommands.__setup()
|
||||
stack_formatter(con.list_stacks())
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def status(extra_args):
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
status_formatter(con.list_stack(extra_args[0]))
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def restart(extra_args):
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
generic_formatter(con.restart(extra_args[0]))
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def update(extra_args):
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
generic_formatter(con.update(extra_args[0]))
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def stop(extra_args):
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
generic_formatter(con.stop(extra_args[0]))
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def start(extra_args):
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
generic_formatter(con.start(extra_args[0]))
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def down(extra_args):
|
||||
if extra_args is None:
|
||||
raise ValueError
|
||||
con = ExecutionCommands.__setup()
|
||||
generic_formatter(con.down(extra_args[0]))
|
||||
con.disconnect()
|
||||
|
||||
@staticmethod
|
||||
def help():
|
||||
print("WTF")
|
88
dockge_cli/client/commandprovider/descriptors.py
Normal file
88
dockge_cli/client/commandprovider/descriptors.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
from .bindings import ExecutionCommands
|
||||
|
||||
command_mappings = [
|
||||
{
|
||||
"command": "host",
|
||||
"description": "Sets and gets the URI of the dockge instance. Remove any unnecessary subdomains/protocols from the URI",
|
||||
"args": 1,
|
||||
"optional": True,
|
||||
"binding": ExecutionCommands.host
|
||||
},
|
||||
{
|
||||
"command": "login",
|
||||
"description": "Logs into a given dockge account, either with an interactive dialogue or by passing --user and --password",
|
||||
"args": 2,
|
||||
"optional": True,
|
||||
"binding": ExecutionCommands.login
|
||||
},
|
||||
{
|
||||
"command": "logout",
|
||||
"description": "Removes the credentials from the local storage.",
|
||||
"args": 0,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.logout
|
||||
},
|
||||
{
|
||||
"command": "list",
|
||||
"description": "Lists all available stacks with their status",
|
||||
"args": 0,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.list
|
||||
},
|
||||
{
|
||||
"command": "status",
|
||||
"description": "Returns the status of one stack",
|
||||
"args": 1,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.status
|
||||
},
|
||||
{
|
||||
"command": "restart",
|
||||
"description": "Restarts a given stack",
|
||||
"args": 1,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.restart
|
||||
},
|
||||
{
|
||||
"command": "start",
|
||||
"description": "Starts a given stack",
|
||||
"args": 1,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.start
|
||||
},
|
||||
{
|
||||
"command": "stop",
|
||||
"description": "Stops a given stack",
|
||||
"args": 1,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.stop
|
||||
},
|
||||
{
|
||||
"command": "down",
|
||||
"description": "Stop & Downs a given stack",
|
||||
"args": 1,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.down
|
||||
},
|
||||
{
|
||||
"command": "update",
|
||||
"description": "Updates a stack",
|
||||
"args": 1,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.update
|
||||
},
|
||||
{
|
||||
"command": "exit",
|
||||
"description": "Exits the CLI - this will reset all settings, including credentials and host",
|
||||
"args": 0,
|
||||
"optional": False,
|
||||
"binding": ExecutionCommands.exit
|
||||
},
|
||||
{
|
||||
"command": "help",
|
||||
"description": "Displays helping hints for commands",
|
||||
"args": 1,
|
||||
"optional": True,
|
||||
"binding": ExecutionCommands.help
|
||||
}
|
||||
]
|
17
dockge_cli/client/commandprovider/factory.py
Normal file
17
dockge_cli/client/commandprovider/factory.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from typing import List, Callable
|
||||
from pydantic import BaseModel
|
||||
from .descriptors import command_mappings
|
||||
|
||||
class Command(BaseModel):
|
||||
command: str
|
||||
description: str
|
||||
args: int
|
||||
optional: bool
|
||||
binding: Callable
|
||||
|
||||
commands: dict[str, Command] = {}
|
||||
descriptors: List[dict[str, object]] = command_mappings
|
||||
|
||||
for descriptor in descriptors:
|
||||
c = Command(**descriptor) # type: ignore
|
||||
commands.update({ c.command: c })
|
18
dockge_cli/client/parser.py
Normal file
18
dockge_cli/client/parser.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
from .. import __version__
|
||||
from ..models.parser import Arguments
|
||||
from .commandprovider.factory import commands
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(
|
||||
prog="dockge_cli",
|
||||
description="CLI interface for interacting with Dockge",)
|
||||
|
||||
parser.add_argument("command", choices=list(commands.keys()), action="store", type=str, default=None)
|
||||
parser.add_argument("--version", action="version", version=f"dockge_cli {__version__}")
|
||||
|
||||
args = Arguments()
|
||||
args, extra_args = parser.parse_known_args(sys.argv[1:], namespace=args)
|
||||
return args, extra_args
|
28
dockge_cli/client/run.py
Normal file
28
dockge_cli/client/run.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
from .commandprovider.factory import commands
|
||||
|
||||
def display_help(extra_args):
|
||||
if not extra_args:
|
||||
print(f"{commands['help'].description}")
|
||||
return
|
||||
if len(extra_args) > 1:
|
||||
raise ValueError("Invalid arguments for help command")
|
||||
if extra_args[0] not in commands:
|
||||
raise ValueError("Unknown command")
|
||||
print(f"{commands[extra_args[0]].description}")
|
||||
|
||||
def run(command, args):
|
||||
if command not in commands:
|
||||
raise ValueError("Invalid Command")
|
||||
|
||||
c = commands[command]
|
||||
|
||||
if args and c.args > len(args):
|
||||
raise ValueError("Too many arguments")
|
||||
if args and c.args < len(args) and not c.optional:
|
||||
raise ValueError("Missing arguments")
|
||||
|
||||
if command == "help":
|
||||
display_help(args)
|
||||
return
|
||||
|
||||
c.binding(args)
|
32
dockge_cli/client/utils.py
Normal file
32
dockge_cli/client/utils.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import argparse
|
||||
from tabulate import tabulate
|
||||
from ..models import StackStatus
|
||||
|
||||
def get_credential_parser():
|
||||
credentialparser = argparse.ArgumentParser(
|
||||
prog="login",
|
||||
description="Subparser for login credentials provided by CI"
|
||||
)
|
||||
credentialparser.add_argument("--username", action="store", type=str, required=True)
|
||||
credentialparser.add_argument("--password", action="store", type=str, required=True)
|
||||
return credentialparser
|
||||
|
||||
def stack_formatter(stacks):
|
||||
if not stacks["ok"]:
|
||||
raise RuntimeError("Stack GET didn't work")
|
||||
|
||||
table, headers = [], ["Stackname", "Status"]
|
||||
for key, val in stacks["stackList"].items():
|
||||
table.append([key, StackStatus(val['status']).name])
|
||||
|
||||
print(tabulate(table, headers=headers, tablefmt="github"), "\n")
|
||||
|
||||
def status_formatter(status):
|
||||
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):
|
||||
print(f"Is Ok? {'Yes' if status['ok'] else 'No'}")
|
||||
print(f"Stack status: {status['msg']}")
|
Loading…
Add table
Add a link
Reference in a new issue