From b9def082789ce012b78959d2db27b577477ac992 Mon Sep 17 00:00:00 2001 From: Jhonnye <43444151+jhonnye0@users.noreply.github.com> Date: Thu, 9 May 2024 00:42:17 -0300 Subject: [PATCH] feat: Implement typer as CLI (#117) --- poetry.lock | 4 +- pyproject.toml | 5 +- src/sugar/cli.py | 1816 ++++++++++++++++++++++++++++++++++++-- src/sugar/core.py | 3 - src/sugar/plugins/ext.py | 1 + 5 files changed, 1726 insertions(+), 103 deletions(-) diff --git a/poetry.lock b/poetry.lock index 2b155df..c5c6cf5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "appnope" @@ -2992,4 +2992,4 @@ tui = ["plotille", "rich", "textual"] [metadata] lock-version = "2.0" python-versions = ">=3.8.1,<4" -content-hash = "0655d622e3b2bca68591305faa7cbdffccfe99b6ad4eb3445769ea7df8c1062b" +content-hash = "fed1fc2b7dfb24f689d55091e3a19694307fe8bd34b93ce71247657bc1191059" diff --git a/pyproject.toml b/pyproject.toml index 997e341..03e559e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -24,6 +24,7 @@ sh = ">=2.0.0" pyyaml = ">=6" colorama = ">=0.4.6" python-dotenv = ">=0.21.1" +typer = ">=0.9.0" rich = { version = ">=10.11.0", optional = true } textual = { version = ">=0.48", optional = true } plotille = { version = ">=5", optional = true } @@ -80,7 +81,7 @@ exclude = [ fix = true [tool.ruff.lint] -ignore = ["RUF012"] +ignore = ["RUF012", "PLR0913", "PLR0915"] select = [ "E", # pycodestyle "F", # pyflakes @@ -106,7 +107,7 @@ exclude_dirs = ["tests"] targets = "src/sugar/" [tool.vulture] -exclude = ["tests"] +exclude = ["tests", "src/sugar/cli.py"] ignore_decorators = [] ignore_names = [] make_whitelist = true diff --git a/src/sugar/cli.py b/src/sugar/cli.py index 5c55498..4a24a4c 100644 --- a/src/sugar/cli.py +++ b/src/sugar/cli.py @@ -1,102 +1,27 @@ """Definition of the CLI structure.""" -import argparse +from __future__ import annotations + import os import sys from pathlib import Path -from typing import Tuple +from typing import Any, Dict, Tuple -from sugar.core import Sugar +import typer +from typer import Argument, Option -def _get_args(): - """Define and return the arguments used by the CLI.""" - parser = argparse.ArgumentParser( - prog='sugar', - description=( - 'sugar (or sugar) is a tool that help you to organize' - "and simplify your containers' stack." - ), - epilog=( - 'If you have any problem, open an issue at: ' - 'https://github.com/osl-incubator/sugar' - ), - ) +from sugar.core import Sugar, __version__ - parser.add_argument( - 'plugin', - type=str, - nargs='?', - default='main', - help='Specify the plugin/extension for the command', - ) - parser.add_argument( - 'action', - nargs='?', - default=None, - help='Specify the command to be performed.', - ) - parser.add_argument( - '--verbose', - action='store_true', - help='Show the command executed.', - ) - parser.add_argument( - '--version', - action='store_true', - help='Show the version of sugar.', - ) - parser.add_argument( - '--service-group', - '--group', - dest='service_group', - type=str, - help='Specify the group name of the services you want to use', - ) - parser.add_argument( - '--services', - type=str, - help=( - 'Set the services for the container call. ' - "Use comma to separate the services's name" - ), - ) - parser.add_argument( - '--service', - type=str, - help=('Set the service for the container call.'), - ) - parser.add_argument( - '--all', - action='store_true', - help='Use all services for the command.', - ) - parser.add_argument( - '--config-file', - type=str, - default=str(Path(os.getcwd()) / '.sugar.yaml'), - help='Specify a custom location for the config file.', - ) - parser.add_argument( - '--options', - type=str, - required=False, - help=( - 'Specify the options for docker-compose command. ' - 'E.g.: --options -d' - ), - ) - parser.add_argument( - '--cmd', - type=str, - required=False, - help=( - 'Specify the COMMAND for some docker-compose command. ' - 'E.g.: --cmd python -c "print(1)"' - ), - ) - return parser +flags_state: Dict[str, bool] = { + 'verbose': False, +} + +opt_state: Dict[str, list[Any]] = { + 'options': [], + 'cmd': [], +} def extract_options_and_cmd_args() -> Tuple[list, list]: @@ -156,13 +81,1712 @@ def extract_options_and_cmd_args() -> Tuple[list, list]: return options_args, cmd_args -def app(): - """Run container-sugar app.""" +def create_main_group(sugar_app: typer.Typer): + """ + Create the main plugin command group. + + Also add the commands to sugar app. + """ + # -- Main commands -- + + @sugar_app.command() + def build( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help=( + 'Set the services for the container call.' + " Use comma to separate the services's name" + ), + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help=( + 'Specify the options for docker-compose command. ' + 'E.g.: --options -d' + ), + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help=( + 'Specify the COMMAND for some docker-compose command. ' + 'E.g.: --cmd python -c print(1)' + ), + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'build' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def config( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help=( + 'Set the services for the container call.' + " Use comma to separate the services's name" + ), + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command. \ + E.g.: --options -d', + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command. \ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'config' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def create( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call. \ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command. \ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command. \ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'create' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def down( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call. \ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command. \ + E.g.: --options -d', + ), + rmi: str = Option( + None, + ), + remove_orphans: str = Option( + None, + ), + volumes: str = Option( + None, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'down' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def events( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help=( + 'Set the services for the container call.' + " Use comma to separate the services's name" + ), + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help=( + 'Specify the options for docker-compose command. ' + 'E.g.: --options -d' + ), + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help=( + 'Specify the COMMAND for some docker-compose command. ' + 'E.g.: --cmd python -c print(1)' + ), + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'events' + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command(name='exec') + def exec_command( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command. \ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'exec' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def images( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call. \ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'images' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def kill( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'kill' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def logs( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'logs' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def pause( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Argument( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Argument( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'pause' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def port( + ctx: typer.Context, + service: str = Option( + None, help='Set the service for the container call.' + ), + private_port: str = Argument( + None, help='Specify the service private port' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'port' + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def ps( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'ps' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def pull( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'pull' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def push( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'push' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def restart( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'restart' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def rm( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for rm command: --options [-f | -s]', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'rm' + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def run( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + target: str = Option(None, '-p', help='Specify the target option.'), + volume: str = Option(None, '-v', help='Specify the volume option.'), + env_vars: str = Option( + None, + '-e', + '-l', + help='Specify the environment variables. [-e KEY=VAL...]', + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'run' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def start( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'start' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def stop( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'stop' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def top( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'top' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def unpause( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Argument( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Argument( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'unpause' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def up( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + scale: str = Option( + None, + help='Specify the service scale as an option\ + [--scale SERVICE=NUM...]', + ), + no_color: str = Option( + None, help='Specify the no-color as an option.' + ), + quiet_pull: str = Option( + None, help='Specify the quiet-pull as an option.' + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'up' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @sugar_app.command() + def version( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'main' + args['action'] = 'version' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + +def create_ext_group(sugar_app: typer.Typer): + """ + Create a command group for ext plugin. + + The function also associate the group to sugar app. + """ + ext_group = typer.Typer( + help='Specify the plugin/extension for the command list', + invoke_without_command=True, + ) + + # -- Ext Commands + + @ext_group.command(name='get-ip') + def get_ip( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + ): + args = ctx.params + args['plugin'] = 'ext' + args['action'] = 'get-ip' + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @ext_group.command(name='start') + def ext_start( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'ext' + args['action'] = 'start' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @ext_group.command(name='stop') + def ext_stop( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'ext' + args['action'] = 'stop' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @ext_group.command(name='restart') + def ext_restart( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'ext' + args['action'] = 'restart' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + @ext_group.command() + def wait( + ctx: typer.Context, + service_group: str = Option( + None, + '--service-group', + '--group', + help='Specify the group name of the services you want to use', + ), + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + service: str = Option( + None, help='Set the service for the container call.' + ), + options: str = Option( + None, + help='Specify the options for docker-compose command.\ + E.g.: --options -d', + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + config_file: str = Option( + str(Path(os.getcwd()) / '.sugar.yaml'), + help='Specify a custom location for the config file.', + is_flag=True, + ), + cmd: str = Option( + None, + help='Specify the COMMAND for some docker-compose command.\ + E.g.: --cmd python -c print(1)', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'ext' + args['action'] = 'wait' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + sugar_app.add_typer(ext_group, name='ext') + + +def create_stats_group(sugar_app: typer.Typer): + """Instantiate the stats command group.""" + stats_group = typer.Typer( + help='Specify the plugin/extension for the command list', + invoke_without_command=True, + ) + + # -- Stats Commands -- + + @stats_group.command() + def plot( + ctx: typer.Context, + services: str = Option( + None, + help="Set the services for the container call.\ + Use comma to separate the services's name", + ), + all: bool = Option( + False, + help='Use all services for the command.', + is_flag=True, + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ): + args = ctx.params + args['plugin'] = 'stats' + args['action'] = 'wait' + + if verbose or flags_state['verbose']: + args['verbose'] = True + + cmd_args: list[Any] = opt_state['cmd'] + opts_args: list[Any] = opt_state['options'] + + Sugar(args, options_args=opts_args, cmd_args=cmd_args).run() + + sugar_app.add_typer(stats_group, name='stats') + + +def create_app(): + """Create app function to instantiate the typer app dinamically.""" options_args, cmd_args = extract_options_and_cmd_args() - args_parser = _get_args() - args = args_parser.parse_args() + opt_state['options'] = options_args + opt_state['cmd'] = cmd_args + + sugar_app = typer.Typer( + name='sugar', + help=( + 'sugar (or sugar) is a tool that help you to organize' + "and simplify your containers' stack." + ), + epilog=( + 'If you have any problem, open an issue at: ' + 'https://github.com/osl-incubator/sugar' + ), + short_help="sugar (or sugar) is a tool that help you \ + to organize containers' stack", + ) + + # -- Add typer groups -- + + create_main_group(sugar_app) + create_ext_group(sugar_app) + create_stats_group(sugar_app) + + # -- Callbacks -- + def version_callback(version: bool): + """ + Version callback function. + + This will be called when using the --version flag + """ + if version: + typer.echo(f'Version: {__version__}') + raise typer.Exit() + + @sugar_app.callback(invoke_without_command=True) + def main( + ctx: typer.Context, + version: bool = Option( + None, + '--version', + '-v', + callback=version_callback, + is_flag=True, + is_eager=True, + help='Show the version of sugar.', + ), + verbose: bool = Option( + False, + '--verbose', + is_flag=True, + is_eager=True, + help='Show the command executed.', + ), + ) -> None: + """ + Process commands for specific flags. + + Otherwise, show the help menu. + """ + ctx.ensure_object(dict) + + if verbose: + flags_state['verbose'] = True + + if ctx.invoked_subcommand is None: + typer.echo('Welcome to sugar. For usage, try --help.') + raise typer.Exit() + + return sugar_app + - args_cast = dict(args._get_kwargs()) +app = create_app() - sugar = Sugar(args_cast, options_args, cmd_args) - return sugar.run() +if __name__ == '__main__': + app() diff --git a/src/sugar/core.py b/src/sugar/core.py index 3a241ad..88483de 100644 --- a/src/sugar/core.py +++ b/src/sugar/core.py @@ -89,9 +89,6 @@ def _load_service_names(self): def run(self): """Run sugar command.""" - if self.args['version']: - return self._version() - if not self.args.get('action'): return diff --git a/src/sugar/plugins/ext.py b/src/sugar/plugins/ext.py index 6947677..b74d49d 100644 --- a/src/sugar/plugins/ext.py +++ b/src/sugar/plugins/ext.py @@ -15,6 +15,7 @@ def __init__(self, *args, **kwargs): 'get-ip', 'restart', 'start', + 'stop', 'wait', ]