wip: shell integration, fixing cli
This commit is contained in:
parent
dcb27eecc1
commit
b8df31f036
26
iam/app.py
26
iam/app.py
@ -12,7 +12,7 @@ from . import exceptions as error
|
|||||||
from .catalog import Catalog
|
from .catalog import Catalog
|
||||||
from .framework import DictItem, scoped_ident
|
from .framework import DictItem, scoped_ident
|
||||||
from .idents import Idents
|
from .idents import Idents
|
||||||
from .lib.utils import import_module, open_yaml
|
from .lib.utils import import_module, open_yaml, get_root_pkg_dir
|
||||||
from .meta import NAME, VERSION
|
from .meta import NAME, VERSION
|
||||||
from .providers import Providers
|
from .providers import Providers
|
||||||
|
|
||||||
@ -181,10 +181,26 @@ class App:
|
|||||||
ret = {svc.name: svc.list_cmds() for svc in self.catalog.services.values()}
|
ret = {svc.name: svc.list_cmds() for svc in self.catalog.services.values()}
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def shell_enable(self):
|
def shell_enable(self, **kwargs):
|
||||||
"Enable shell"
|
"Enable shell"
|
||||||
return self.catalog.shell_enable()
|
return self.catalog.shell_enable(**kwargs)
|
||||||
|
|
||||||
def shell_disable(self):
|
def shell_disable(self, **kwargs):
|
||||||
"Disable shell"
|
"Disable shell"
|
||||||
return self.catalog.shell_disable()
|
return self.catalog.shell_disable(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def shell_install(self, shell="bash"):
|
||||||
|
"Install iam in shell"
|
||||||
|
|
||||||
|
assets_dir = os.path.join(get_root_pkg_dir("iam"), "assets")
|
||||||
|
|
||||||
|
|
||||||
|
if shell == "bash":
|
||||||
|
config_file = ".bashrc"
|
||||||
|
template_file = os.path.join(assets_dir, "init_bash.sh")
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception(f"Unsupported shell: {shell}")
|
||||||
|
|
||||||
|
return f"source {template_file}"
|
||||||
180
iam/assets/init_bash.sh
Normal file
180
iam/assets/init_bash.sh
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
|
||||||
|
# Workllow
|
||||||
|
#
|
||||||
|
# API
|
||||||
|
# i <ident>
|
||||||
|
# i status <ident>
|
||||||
|
# i switch <ident>
|
||||||
|
# i disable <ident>
|
||||||
|
# i help
|
||||||
|
# i FORWARD
|
||||||
|
|
||||||
|
# ${debian_chroot:+($debian_chroot)}\u@\h:\w\$
|
||||||
|
|
||||||
|
|
||||||
|
#IAM_BIN=/home/jez/volumes/data/prj/jez/lab/iam-python/.direnv/python-3.11.3/bin/iam
|
||||||
|
IAM_BIN=$(command -v iam)
|
||||||
|
IAM_IDENT=
|
||||||
|
|
||||||
|
_usage ()
|
||||||
|
{
|
||||||
|
echo "iam shell wrapper"
|
||||||
|
|
||||||
|
cat << EOF
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
i [status] Show shell status
|
||||||
|
i switch IDENT Enable shell identity
|
||||||
|
i disable Disable shell identity
|
||||||
|
i kill Disable and kill shell identity
|
||||||
|
i help Show this help
|
||||||
|
|
||||||
|
Informations:
|
||||||
|
IAM_BIN=${IAM_BIN}
|
||||||
|
SHELL_IDENT=${SHELL_IDENT:-_}
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
i ()
|
||||||
|
{
|
||||||
|
# set -x
|
||||||
|
|
||||||
|
# Get status
|
||||||
|
target_ident=_
|
||||||
|
current_ident=${SHELL_IDENT:-_}
|
||||||
|
available_idents=$($IAM_BIN shell idents -O words)
|
||||||
|
|
||||||
|
# Internal vars
|
||||||
|
remaining_args=
|
||||||
|
idents_pattern=:${available_idents// /:}:
|
||||||
|
index=0
|
||||||
|
action=
|
||||||
|
|
||||||
|
|
||||||
|
while [[ -n "${1-}" ]] ; do
|
||||||
|
local arg=$1
|
||||||
|
|
||||||
|
case "$arg" in
|
||||||
|
status|st)
|
||||||
|
action=status
|
||||||
|
shift 1
|
||||||
|
if [[ -n "${1}" ]]; then
|
||||||
|
target_ident=$1
|
||||||
|
shift 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
switch|enable|en)
|
||||||
|
action=switch
|
||||||
|
shift 1
|
||||||
|
if [[ -n "${1}" ]]; then
|
||||||
|
target_ident=$1
|
||||||
|
shift 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
disable|dis|q)
|
||||||
|
action=disable
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
kill|k)
|
||||||
|
action=kill
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
stop|K)
|
||||||
|
action=kill_all
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
help|--help|-h)
|
||||||
|
action=help
|
||||||
|
shift 1
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if [[ "$idents_pattern" == *":$arg:"* ]]; then
|
||||||
|
action=switch
|
||||||
|
target_ident=$arg
|
||||||
|
shift 1
|
||||||
|
else
|
||||||
|
remaining_args="$remaining_args $arg"
|
||||||
|
shift 1
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
((index++))
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$action" ]]; then
|
||||||
|
action="idents"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# echo "Current Ident: $current_ident"
|
||||||
|
# echo "Target Ident: $target_ident"
|
||||||
|
# echo "Action: $action"
|
||||||
|
|
||||||
|
case "$action" in
|
||||||
|
idents)
|
||||||
|
echo "Iam path: ${IAM_BIN}"
|
||||||
|
echo "Current ident: ${SHELL_IDENT:-<None>}"
|
||||||
|
echo "Available identities: $($IAM_BIN shell idents -O words)"
|
||||||
|
;;
|
||||||
|
|
||||||
|
switch)
|
||||||
|
# if [[ "$current_ident" != '_' ]]; then
|
||||||
|
# eval $IAM_BIN shell disable $current_ident
|
||||||
|
# fi
|
||||||
|
# $IAM_BIN shell switch $target_ident
|
||||||
|
|
||||||
|
if [[ "$target_ident" != '_' ]]; then
|
||||||
|
>&2 echo "DEBUG: eval: $IAM_BIN shell switch $target_ident"
|
||||||
|
eval "$($IAM_BIN shell switch $target_ident)"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
disable)
|
||||||
|
if [[ "$current_ident" != '_' ]]; then
|
||||||
|
>&2 echo "DEBUG: eval: $IAM_BIN shell switch"
|
||||||
|
eval "$($IAM_BIN shell disable)"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
kill)
|
||||||
|
if [[ "$current_ident" != '_' ]]; then
|
||||||
|
>&2 echo "DEBUG: eval: $IAM_BIN shell switch --kill"
|
||||||
|
eval "$($IAM_BIN shell disable --kill)"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
kill_all)
|
||||||
|
eval "$($IAM_BIN shell kill -a)"
|
||||||
|
;;
|
||||||
|
|
||||||
|
status)
|
||||||
|
echo "IAM_BIN=${IAM_BIN}"
|
||||||
|
echo "SHELL_IDENT=${SHELL_IDENT:-_}"
|
||||||
|
|
||||||
|
#echo $IAM_BIN shell status $current_ident
|
||||||
|
;;
|
||||||
|
help)
|
||||||
|
_usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
set +x
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# Source or switch
|
||||||
|
if $source_output; then
|
||||||
|
out=($IAM_BIN $@)
|
||||||
|
echo "SOURCE: $out"
|
||||||
|
else
|
||||||
|
echo $IAM_BIN $@
|
||||||
|
fi
|
||||||
|
|
||||||
|
set +x
|
||||||
|
}
|
||||||
|
|
||||||
|
#i2 $@
|
||||||
254
iam/catalog.py
254
iam/catalog.py
@ -9,6 +9,7 @@ from .idents import Ident
|
|||||||
from .lib.utils import format_render, jinja_render, uniq
|
from .lib.utils import format_render, jinja_render, uniq
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
cli_logger = logging.getLogger("iam.cli")
|
||||||
|
|
||||||
|
|
||||||
IamException = error.IamException
|
IamException = error.IamException
|
||||||
@ -47,7 +48,18 @@ class ServiceCommand(DictItem):
|
|||||||
|
|
||||||
default_attrs = {
|
default_attrs = {
|
||||||
"desc": "Service without description",
|
"desc": "Service without description",
|
||||||
"cmd": "",
|
|
||||||
|
"cmd": "", # Direct commands to launch
|
||||||
|
|
||||||
|
"shell": "", # Will be run in a shell (or specific shell below)
|
||||||
|
"shell_sh": "",
|
||||||
|
"shell_bash": "",
|
||||||
|
"shell_zsh": "",
|
||||||
|
"shell_fish": "",
|
||||||
|
"shell_bash": "",
|
||||||
|
|
||||||
|
"source": False, # True for enable commands !
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Overrides
|
# Overrides
|
||||||
@ -55,12 +67,15 @@ class ServiceCommand(DictItem):
|
|||||||
|
|
||||||
def payload_transform(self, name, kwargs=None):
|
def payload_transform(self, name, kwargs=None):
|
||||||
"Transform short form into long form"
|
"Transform short form into long form"
|
||||||
|
self.service = self.parent
|
||||||
|
|
||||||
payload = self._payload
|
payload = self._payload
|
||||||
if not isinstance(payload, dict):
|
if not isinstance(payload, dict):
|
||||||
payload = {"cmd": payload}
|
payload = {"cmd": payload}
|
||||||
self._payload = payload
|
self._payload = payload
|
||||||
|
|
||||||
|
def cmd_name(self):
|
||||||
|
return self.name.replace("_", " ")
|
||||||
|
|
||||||
class Service(DictItem):
|
class Service(DictItem):
|
||||||
"Hold provider services"
|
"Hold provider services"
|
||||||
@ -83,9 +98,10 @@ class Service(DictItem):
|
|||||||
self.catalog = self.parent.catalog
|
self.catalog = self.parent.catalog
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
|
||||||
ret = {}
|
ret = {}
|
||||||
for cmd_name, cmd in self.commands.items():
|
for cmd_name, cmd in self.commands.items():
|
||||||
ret[cmd_name] = ServiceCommand(cmd_name, cmd)
|
ret[cmd_name] = ServiceCommand(cmd_name, cmd, parent=self)
|
||||||
self.commands = ret
|
self.commands = ret
|
||||||
|
|
||||||
# def require_resolved_deps(func):
|
# def require_resolved_deps(func):
|
||||||
@ -200,7 +216,7 @@ class Service(DictItem):
|
|||||||
out = cmd.format(**env_var)
|
out = cmd.format(**env_var)
|
||||||
except KeyError as err:
|
except KeyError as err:
|
||||||
msg = f"Missing variable: {err} for service: {res.key}"
|
msg = f"Missing variable: {err} for service: {res.key}"
|
||||||
# print (msg)
|
logger.warning (msg)
|
||||||
out = msg
|
out = msg
|
||||||
# raise IamException(msg)
|
# raise IamException(msg)
|
||||||
|
|
||||||
@ -213,6 +229,13 @@ class Service(DictItem):
|
|||||||
|
|
||||||
# def _list_cmds(self):
|
# def _list_cmds(self):
|
||||||
|
|
||||||
|
def get_cmds(self):
|
||||||
|
"Get all services commands objects"
|
||||||
|
|
||||||
|
return [cmd for name, cmd in self.commands.items() if not name.startswith("shell")]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def list_cmds(self):
|
def list_cmds(self):
|
||||||
"List all services commands"
|
"List all services commands"
|
||||||
|
|
||||||
@ -226,11 +249,15 @@ class Service(DictItem):
|
|||||||
|
|
||||||
for cmd_name, conf in self.commands.items():
|
for cmd_name, conf in self.commands.items():
|
||||||
target = ret2["cmds"]
|
target = ret2["cmds"]
|
||||||
|
|
||||||
if cmd_name.startswith(shell_prefix):
|
if cmd_name.startswith(shell_prefix):
|
||||||
target = ret2["shell"]
|
target = ret2["shell"]
|
||||||
cmd_name = cmd_name[len(shell_prefix) :]
|
# cmd_name = cmd_name[len(shell_prefix):]
|
||||||
|
name = f"{cmd_name}_{prefix}"
|
||||||
|
else:
|
||||||
|
|
||||||
|
name = cmd_name.replace("_", " ")
|
||||||
|
|
||||||
name = f"{prefix} {cmd_name}"
|
|
||||||
target[name] = conf.desc
|
target[name] = conf.desc
|
||||||
|
|
||||||
return ret2
|
return ret2
|
||||||
@ -253,9 +280,76 @@ class Services(DictCtrl):
|
|||||||
|
|
||||||
items_class = Service
|
items_class = Service
|
||||||
|
|
||||||
|
RESERVED_CMD_PREFIX=["kind", "res", "svc", "shell", "run"]
|
||||||
|
|
||||||
def prepare(self):
|
def prepare(self):
|
||||||
self.catalog = self.parent
|
self.catalog = self.parent
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_svc_command(self, cmd):
|
||||||
|
"Return the command to be run"
|
||||||
|
|
||||||
|
# Prepare context
|
||||||
|
cmd_parts = cmd
|
||||||
|
if isinstance(cmd, str):
|
||||||
|
cmd_parts = cmd.split(" ")
|
||||||
|
cmd_req = " ".join(cmd_parts)
|
||||||
|
|
||||||
|
# Retrieve command list
|
||||||
|
cmds = self.list_cmds()
|
||||||
|
cmd_names = [cmd.name for cmd in cmds ]
|
||||||
|
|
||||||
|
|
||||||
|
# Find best matching command
|
||||||
|
cmd_split_idx = None
|
||||||
|
cmd = None
|
||||||
|
curr=None
|
||||||
|
for index, part in enumerate(cmd_parts):
|
||||||
|
curr = f"{curr} {part}" if curr is not None else part
|
||||||
|
if curr in cmd_names:
|
||||||
|
cmd_idx = cmd_names.index(curr)
|
||||||
|
cmd = cmds[cmd_idx]
|
||||||
|
cmd_split_idx = index + 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# Validate result
|
||||||
|
if not cmd:
|
||||||
|
_choices = ','.join(cmd_names)
|
||||||
|
_msg = f"No such services command named: {cmd_req}, please choose one of: {_choices}"
|
||||||
|
raise error.UnknownServiceCommand(_msg)
|
||||||
|
|
||||||
|
args = cmd_parts[cmd_split_idx:]
|
||||||
|
|
||||||
|
return cmd, args
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def list_cmds(self):
|
||||||
|
"List all services commands"
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
for name, service in self.items():
|
||||||
|
cmds = service.get_cmds()
|
||||||
|
ret.extend(cmds)
|
||||||
|
|
||||||
|
# Check for invalid configs
|
||||||
|
conf = []
|
||||||
|
for cmd in ret:
|
||||||
|
prefix = cmd.name.split(" ")[0]
|
||||||
|
if prefix in self.RESERVED_CMD_PREFIX:
|
||||||
|
_msg = f'Forbidden prefix! {cmd}'
|
||||||
|
raise Exception (_msg)
|
||||||
|
conf.append(cmd.name )
|
||||||
|
dump = uniq(conf)
|
||||||
|
|
||||||
|
if conf != dump:
|
||||||
|
_msg = f'Duplicates values! {conf}'
|
||||||
|
raise Exception (_msg)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_linked_resources(self):
|
def get_linked_resources(self):
|
||||||
"""
|
"""
|
||||||
Like get method, but only grab enabled services
|
Like get method, but only grab enabled services
|
||||||
@ -798,18 +892,36 @@ class Catalog:
|
|||||||
|
|
||||||
# return self.services.get_loading_order(reverse=reverse)
|
# return self.services.get_loading_order(reverse=reverse)
|
||||||
|
|
||||||
|
|
||||||
# Shell helpers
|
# Shell helpers
|
||||||
# ================
|
# ================
|
||||||
|
|
||||||
def shell_enable(self):
|
def shell_enable(self, run_start=True):
|
||||||
"Enable shell"
|
"Enable shell"
|
||||||
return self._shell_action()
|
|
||||||
|
|
||||||
def shell_disable(self):
|
|
||||||
|
actions = ["shell_enable"]
|
||||||
|
if run_start:
|
||||||
|
actions.insert(0, "shell_start")
|
||||||
|
# logger.warning("Shell Start")
|
||||||
|
# logger.warning("Shell Enable")
|
||||||
|
|
||||||
|
return self._shell_action(actions)
|
||||||
|
|
||||||
|
|
||||||
|
def shell_disable(self, run_stop=False):
|
||||||
"Disable shell"
|
"Disable shell"
|
||||||
return self._shell_action(reverse=True)
|
|
||||||
|
|
||||||
def _shell_action(self, reverse=False):
|
actions = ["shell_disable"]
|
||||||
|
if run_stop:
|
||||||
|
actions.insert(0, "shell_stop")
|
||||||
|
# cli_logger.info("Shell Stop")
|
||||||
|
# cli_logger.info("Shell Disable")
|
||||||
|
|
||||||
|
return self._shell_action(actions)
|
||||||
|
|
||||||
|
|
||||||
|
def _shell_action(self, action_names, reverse=False):
|
||||||
"Run command order"
|
"Run command order"
|
||||||
|
|
||||||
ident = self.ident
|
ident = self.ident
|
||||||
@ -819,12 +931,10 @@ class Catalog:
|
|||||||
order, services = self.services.get_loading_order(reverse=reverse)
|
order, services = self.services.get_loading_order(reverse=reverse)
|
||||||
|
|
||||||
# Prepare context
|
# Prepare context
|
||||||
action_name = "shell_enable"
|
|
||||||
log_action_name = "Enable"
|
log_action_name = "Enable"
|
||||||
if reverse:
|
if reverse:
|
||||||
action_name = "shell_disable"
|
|
||||||
log_action_name = "Disable"
|
log_action_name = "Disable"
|
||||||
logger.info(f"{log_action_name} identity: {ident.name}")
|
cli_logger.info(f"Identity {ident.name} action: {','.join(action_names)}")
|
||||||
|
|
||||||
# Execute on each plugins commands
|
# Execute on each plugins commands
|
||||||
output_code = []
|
output_code = []
|
||||||
@ -833,38 +943,102 @@ class Catalog:
|
|||||||
res = services[srv_name].res
|
res = services[srv_name].res
|
||||||
|
|
||||||
# Load service command
|
# Load service command
|
||||||
command = service.commands.get(action_name, None)
|
for action_name in action_names:
|
||||||
if not command:
|
command = service.commands.get(action_name, None)
|
||||||
continue
|
if not command:
|
||||||
|
continue
|
||||||
|
|
||||||
# Build loop with at least ONE item
|
# Build loop with at least ONE item
|
||||||
cmd = command.cmd
|
cmd = command.cmd
|
||||||
if not cmd:
|
if not cmd:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Create context var dict
|
# Create context var dict
|
||||||
ctx_vars = dict()
|
ctx_vars = dict()
|
||||||
ctx_vars.update(service.input)
|
ctx_vars.update(service.input)
|
||||||
ctx_vars.update(vars)
|
ctx_vars.update(vars)
|
||||||
ctx_vars.update(res.resolve_inputs(vars=ctx_vars))
|
ctx_vars.update(res.resolve_inputs(vars=ctx_vars))
|
||||||
|
|
||||||
loops = res.loop_extend() or [res]
|
loops = res.loop_extend() or [res]
|
||||||
res_vars = [x.resolve_inputs(vars=ctx_vars) for x in loops]
|
res_vars = [x.resolve_inputs(vars=ctx_vars) for x in loops]
|
||||||
|
|
||||||
ctx_vars.update(
|
ctx_vars.update(
|
||||||
{
|
{
|
||||||
"item": res_vars[0],
|
"item": res_vars[0],
|
||||||
"loop": res_vars,
|
"loop": res_vars,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
logger.debug(f"{log_action_name} service: {res.name}")
|
logger.debug(f"{log_action_name} service: {res.name}")
|
||||||
|
|
||||||
# pprint (ctx_vars)
|
# pprint (ctx_vars)
|
||||||
cmd = jinja_render(cmd, ctx_vars)
|
cmd = jinja_render(cmd, ctx_vars)
|
||||||
output_code.append(f"# Loading of {res.name} ({service.name})")
|
output_code.append(f"# Loading: {action_name} {res.name} ({service.name})")
|
||||||
output_code.append(f"# =====================")
|
output_code.append(f"# =====================")
|
||||||
output_code.append(cmd)
|
output_code.append(cmd)
|
||||||
output_code.append("\n")
|
output_code.append("\n")
|
||||||
|
|
||||||
return "\n".join(output_code)
|
return "\n".join(output_code)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def run_svc_cmd(self, cmd):
|
||||||
|
"Run a command against the services"
|
||||||
|
|
||||||
|
cmd, args = self.services.get_svc_command(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# pprint (cmd.cmd)
|
||||||
|
pprint (args)
|
||||||
|
|
||||||
|
service = cmd.service
|
||||||
|
|
||||||
|
pprint (service)
|
||||||
|
pprint (service.__dict__)
|
||||||
|
# pprint (dir(service))
|
||||||
|
res = service.get_linked_resource()
|
||||||
|
# pprint (res)
|
||||||
|
|
||||||
|
vars = self.context.get_vars()
|
||||||
|
|
||||||
|
ctx_vars = dict()
|
||||||
|
ctx_vars.update(vars)
|
||||||
|
ctx_vars.update(service.inputs)
|
||||||
|
|
||||||
|
# ctx_vars.update(res.resolve_inputs(vars=ctx_vars))
|
||||||
|
|
||||||
|
# loops = res.loop_extend() or [res]
|
||||||
|
# res_vars = [x.resolve_inputs(vars=ctx_vars) for x in loops]
|
||||||
|
|
||||||
|
# ctx_vars.update(
|
||||||
|
# {
|
||||||
|
# "item": res_vars[0],
|
||||||
|
# "loop": res_vars,
|
||||||
|
# }
|
||||||
|
# )
|
||||||
|
|
||||||
|
pprint (ctx_vars)
|
||||||
|
|
||||||
|
|
||||||
|
if cmd.cmd:
|
||||||
|
mode = "cmd"
|
||||||
|
payload = cmd.cmd
|
||||||
|
real_cmd = jinja_render(payload, ctx_vars)
|
||||||
|
|
||||||
|
|
||||||
|
elif cmd.shell:
|
||||||
|
mode = "shell"
|
||||||
|
payload = cmd.shell
|
||||||
|
real_cmd = jinja_render(payload, ctx_vars)
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception("MIssing cmd or shell in config !")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print ("RUN CMD", mode, "\n\n\n====\n", real_cmd)
|
||||||
240
iam/cli_click.py
240
iam/cli_click.py
@ -45,7 +45,7 @@ else:
|
|||||||
import rich_click as click
|
import rich_click as click
|
||||||
from rich_click import RichGroup
|
from rich_click import RichGroup
|
||||||
|
|
||||||
from rich import box, print
|
from rich import box #, print
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
# Overrides defaults
|
# Overrides defaults
|
||||||
from rich.pretty import pprint
|
from rich.pretty import pprint
|
||||||
@ -67,6 +67,8 @@ else:
|
|||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
cli_logger = logging.getLogger("iam.cli")
|
||||||
|
|
||||||
|
|
||||||
# Global vars
|
# Global vars
|
||||||
# ======================
|
# ======================
|
||||||
@ -97,7 +99,7 @@ DEFAULT_LOG_LEVEL = 30 # warning
|
|||||||
DEBUG = os.environ.get("IAM_DEBUG", "False")
|
DEBUG = os.environ.get("IAM_DEBUG", "False")
|
||||||
DEFAULT_IDENT = os.environ.get("IAM_IDENT", os.environ.get("SHELL_IDENT", ""))
|
DEFAULT_IDENT = os.environ.get("IAM_IDENT", os.environ.get("SHELL_IDENT", ""))
|
||||||
DEFAULT_FORMAT = os.environ.get("IAM_FORMAT", "table")
|
DEFAULT_FORMAT = os.environ.get("IAM_FORMAT", "table")
|
||||||
|
DEFAULT_HELP_OPTIONS=["-h", "--help"]
|
||||||
|
|
||||||
# list_view.formats_enum
|
# list_view.formats_enum
|
||||||
|
|
||||||
@ -110,7 +112,7 @@ _cmd2_options = [click.option("--cmd2-opt")]
|
|||||||
|
|
||||||
CONTEXT_SETTINGS = dict(
|
CONTEXT_SETTINGS = dict(
|
||||||
show_default=True,
|
show_default=True,
|
||||||
help_option_names=["-h", "--help"],
|
help_option_names=DEFAULT_HELP_OPTIONS,
|
||||||
auto_envvar_prefix=APP_NAME.upper(),
|
auto_envvar_prefix=APP_NAME.upper(),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -219,7 +221,8 @@ def get_var(name, default=None):
|
|||||||
|
|
||||||
|
|
||||||
# @click.group(cls=NestedHelpGroup, context_settings=CONTEXT_SETTINGS)
|
# @click.group(cls=NestedHelpGroup, context_settings=CONTEXT_SETTINGS)
|
||||||
@click.group(cls=NestedHelpGroup)
|
@click.group(cls=NestedHelpGroup
|
||||||
|
)
|
||||||
@global_options
|
@global_options
|
||||||
@format_options
|
@format_options
|
||||||
@click.version_option()
|
@click.version_option()
|
||||||
@ -259,7 +262,7 @@ def cli_app(
|
|||||||
# Define loggers
|
# Define loggers
|
||||||
loggers = {
|
loggers = {
|
||||||
"iam": {"level": log_level},
|
"iam": {"level": log_level},
|
||||||
"iam.cli": {"level": "INFO"},
|
"iam.cli": {"level": "DEBUG", "handlers": ["info"]},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Instanciate logger
|
# Instanciate logger
|
||||||
@ -275,8 +278,6 @@ def cli_app(
|
|||||||
"table_settings": table_box_params,
|
"table_settings": table_box_params,
|
||||||
}
|
}
|
||||||
|
|
||||||
pprint(cli_config)
|
|
||||||
|
|
||||||
render_item = lambda *args, conf={}, **kwargs: item_view.render(
|
render_item = lambda *args, conf={}, **kwargs: item_view.render(
|
||||||
*args, conf={**render_config, **prune(conf)}, **kwargs
|
*args, conf={**render_config, **prune(conf)}, **kwargs
|
||||||
)
|
)
|
||||||
@ -630,7 +631,7 @@ def svc_show(ctx, name, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=N
|
|||||||
def svc_commands(ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=None):
|
def svc_commands(ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=None):
|
||||||
"Show service"
|
"Show service"
|
||||||
|
|
||||||
columns = ["name", "type", "desc"]
|
columns = ["service", "name", "type", "desc"]
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for svc_name, svc in ctx.obj.app.list_services().items():
|
for svc_name, svc in ctx.obj.app.list_services().items():
|
||||||
@ -641,10 +642,7 @@ def svc_commands(ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=Non
|
|||||||
for cmd_name, conf in items.items():
|
for cmd_name, conf in items.items():
|
||||||
# target[cmd_name] = conf
|
# target[cmd_name] = conf
|
||||||
|
|
||||||
data.append([cmd_name, source, conf])
|
data.append([svc_name, cmd_name, source, conf])
|
||||||
|
|
||||||
# pprint(ret)
|
|
||||||
# pprint(ret, expand_all=True)
|
|
||||||
|
|
||||||
# Render data
|
# Render data
|
||||||
ctx.obj.render_list(
|
ctx.obj.render_list(
|
||||||
@ -659,7 +657,7 @@ def svc_commands(ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=Non
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@cli__svc.command("run")
|
@cli__svc.command("run_v1")
|
||||||
@click.argument("name")
|
@click.argument("name")
|
||||||
@click.argument("command")
|
@click.argument("command")
|
||||||
@format_options
|
@format_options
|
||||||
@ -687,23 +685,12 @@ def cli__shell():
|
|||||||
@format_options
|
@format_options
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def shell_idents(
|
def shell_idents(
|
||||||
ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=None, reverse=False
|
ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=None,
|
||||||
):
|
):
|
||||||
"Shell identities"
|
"Shell identities"
|
||||||
columns = ["name"]
|
columns = ["name"]
|
||||||
data = [[x] for x in ctx.obj.app.get_idents()]
|
data = [[x] for x in ctx.obj.app.get_idents()]
|
||||||
|
|
||||||
# print(" ".join(ret))
|
|
||||||
|
|
||||||
# return
|
|
||||||
|
|
||||||
# columns = ["order", "name"]
|
|
||||||
# data = []
|
|
||||||
# services, _ = ctx.obj.app.catalog.services.get_loading_order(reverse=reverse)
|
|
||||||
# for index, name in enumerate(services):
|
|
||||||
# # table.add_row(str(index), name)
|
|
||||||
# data.append([str(index), name])
|
|
||||||
|
|
||||||
# Render data
|
# Render data
|
||||||
ctx.obj.render_list(
|
ctx.obj.render_list(
|
||||||
data,
|
data,
|
||||||
@ -748,44 +735,191 @@ def shell_order(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@cli__shell.command("enable")
|
@cli__shell.command("enable")
|
||||||
@click.argument("ident")
|
@click.option(
|
||||||
# @format_options
|
"skip_start", "--no-start", "-b", is_flag=True, show_default=False, default=False, help="Disable background process start"
|
||||||
|
)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def shell_enable(ctx, ident, verbose=None):
|
def shell_enable(ctx, skip_start=True, verbose=None):
|
||||||
|
"Enable identity in shell"
|
||||||
|
|
||||||
|
app = ctx.obj.app
|
||||||
|
print(app.shell_enable(run_start=not skip_start))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@cli__shell.command("disable")
|
||||||
|
@click.option(
|
||||||
|
"run_stop", "--kill", "-k", is_flag=True, show_default=False, default=False, help="Kill background process on leave"
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def shell_disable(ctx, run_stop=False, verbose=None):
|
||||||
|
"Disable identity in shell"
|
||||||
|
|
||||||
|
ret = ctx.obj.app.shell_disable(run_stop=run_stop)
|
||||||
|
print(ret)
|
||||||
|
|
||||||
|
|
||||||
|
@cli__shell.command("kill")
|
||||||
|
@click.option(
|
||||||
|
"all_idents", "--all", "-a", is_flag=True, show_default=False, default=False, help="Kill on all users"
|
||||||
|
)
|
||||||
|
@click.pass_context
|
||||||
|
def shell_kill(ctx, all_idents=False, verbose=None):
|
||||||
|
"Disable identity in shell"
|
||||||
|
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
app = ctx.obj.app
|
||||||
|
if not all_idents:
|
||||||
|
ret.append(app.shell_enable(run_start=False))
|
||||||
|
ret.append(app.shell_disable(run_stop=True))
|
||||||
|
|
||||||
|
else:
|
||||||
|
for ident in app.idents.names():
|
||||||
|
cli_logger.warning(f"Kill ident {ident}")
|
||||||
|
app.init_ident(ident)
|
||||||
|
ret.append(app.shell_enable(run_start=False))
|
||||||
|
ret.append(app.shell_disable(run_stop=True))
|
||||||
|
|
||||||
|
print('\n'.join(ret))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@cli__shell.command("switch")
|
||||||
|
@click.argument("ident", required=False)
|
||||||
|
# @format_options
|
||||||
|
@click.option(
|
||||||
|
"skip_start", "--no-start", "-b", is_flag=True, show_default=False, default=False, help="Disable background process start"
|
||||||
|
)
|
||||||
|
@click.option(
|
||||||
|
"run_stop", "--kill", "-k", is_flag=True, show_default=False, default=False, help="Kill background process on leave"
|
||||||
|
)
|
||||||
|
|
||||||
|
@click.pass_context
|
||||||
|
def shell_switch(ctx, ident="", run_stop=False, skip_start=True, verbose=None):
|
||||||
"Enable identity in shell"
|
"Enable identity in shell"
|
||||||
|
|
||||||
app = ctx.obj.app
|
app = ctx.obj.app
|
||||||
|
|
||||||
# Disable existing
|
src_ident = app.catalog.ident.name
|
||||||
# logger.info(f"Disabling ident: {app.ident_name}")
|
dst_ident = ident
|
||||||
ret1 = app.shell_disable()
|
|
||||||
print("-- %< --" * 8)
|
|
||||||
print(ret1)
|
|
||||||
print("-- %< --" * 8)
|
|
||||||
|
|
||||||
# Enable new
|
|
||||||
# logger.info(f"Enabling ident: {ident}")
|
|
||||||
app.init_ident(ident)
|
|
||||||
ret2 = app.shell_enable()
|
|
||||||
|
|
||||||
# Output
|
|
||||||
print("-- %< --" * 8)
|
|
||||||
print(ret2)
|
|
||||||
print("-- %< --" * 8)
|
|
||||||
|
|
||||||
|
|
||||||
@cli__shell.command("disable")
|
if src_ident == dst_ident:
|
||||||
# @format_options
|
print (">&2 echo 'No need to change'")
|
||||||
|
else:
|
||||||
|
ret = []
|
||||||
|
|
||||||
|
# Disable existing
|
||||||
|
# logger.info(f"Disabling ident: {app.ident_name}")
|
||||||
|
ret.append(app.shell_disable(run_stop=run_stop))
|
||||||
|
|
||||||
|
# Enable new
|
||||||
|
# logger.info(f"Enabling ident: {ident}")
|
||||||
|
app.init_ident(dst_ident)
|
||||||
|
ret.append(app.shell_enable(run_start=not skip_start))
|
||||||
|
|
||||||
|
# Output
|
||||||
|
print('\n'.join(ret))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TmpGroup(click.Group):
|
||||||
|
def format_help(self, ctx, formatter):
|
||||||
|
|
||||||
|
val = "List of available commands!"
|
||||||
|
formatter.write(val)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@cli_app.command("run",
|
||||||
|
# cls=TmpGroup,
|
||||||
|
context_settings=dict(
|
||||||
|
ignore_unknown_options=True,
|
||||||
|
allow_extra_args=True,
|
||||||
|
help_option_names=[]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@click.argument('cmd_params', nargs=-1, type=click.UNPROCESSED)
|
||||||
@click.pass_context
|
@click.pass_context
|
||||||
def shell_disable(ctx, verbose=None):
|
def cli_app_run(ctx, cmd_params):
|
||||||
"Disable identity in shell"
|
|
||||||
|
|
||||||
ret = ctx.obj.app.shell_disable()
|
print("Will run cmd:", cmd_params)
|
||||||
|
|
||||||
print("-- %< --" * 8)
|
# Check first help parameter only
|
||||||
|
show_help = False
|
||||||
|
show_list = False
|
||||||
|
for idx, param in enumerate(cmd_params):
|
||||||
|
if idx == 0:
|
||||||
|
if param in DEFAULT_HELP_OPTIONS:
|
||||||
|
show_help = True
|
||||||
|
if param in ["list", "ls"]:
|
||||||
|
show_list = True
|
||||||
|
|
||||||
|
if show_help:
|
||||||
|
ctx = click.get_current_context()
|
||||||
|
click.echo(ctx.get_help())
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
# Get instanciated app
|
||||||
|
app = ctx.obj.app
|
||||||
|
|
||||||
|
if show_list:
|
||||||
|
ret = app.catalog.services.list_cmds()
|
||||||
|
data = [[x.name, x.desc] for x in ret]
|
||||||
|
|
||||||
|
|
||||||
|
# Render data
|
||||||
|
ctx.obj.render_list(
|
||||||
|
data,
|
||||||
|
["name", "desc"],
|
||||||
|
conf={
|
||||||
|
"table_title": f"Services commands",
|
||||||
|
# "fmt_name": fmt_name,
|
||||||
|
# "fmt_sort": fmt_sort,
|
||||||
|
# "fmt_fields": fmt_fields,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
# Run the output
|
||||||
|
ret = app.catalog.run_svc_cmd(cmd=cmd_params)
|
||||||
|
pprint (ret, expand_all=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# @cli_app.command("run2",
|
||||||
|
# context_settings=dict(
|
||||||
|
# ignore_unknown_options=True,
|
||||||
|
# allow_extra_args=True,
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# @click.pass_context
|
||||||
|
# def cli_app_run(ctx):
|
||||||
|
# print("Hello world")
|
||||||
|
# pprint (ctx.args)
|
||||||
|
|
||||||
|
# return
|
||||||
|
|
||||||
|
|
||||||
|
@cli__shell.command("install")
|
||||||
|
@click.pass_context
|
||||||
|
def shell_install(ctx, verbose=None):
|
||||||
|
"Install iam in your shell"
|
||||||
|
|
||||||
|
ret = ctx.obj.app.shell_install()
|
||||||
|
|
||||||
|
# print("-- %< --" * 8)
|
||||||
print(ret)
|
print(ret)
|
||||||
print("-- %< --" * 8)
|
# print("-- %< --" * 8)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Exception handler
|
# Exception handler
|
||||||
@ -796,8 +930,8 @@ def clean_terminate(err):
|
|||||||
# Choose dead end way
|
# Choose dead end way
|
||||||
if APP_EXCEPTION is not None and isinstance(err, APP_EXCEPTION):
|
if APP_EXCEPTION is not None and isinstance(err, APP_EXCEPTION):
|
||||||
err_name = err.__class__.__name__
|
err_name = err.__class__.__name__
|
||||||
logger.error(err)
|
# logger.error(err)
|
||||||
logger.critical("MyApp exited with error: %s", err_name)
|
logger.critical("%s: %s" % (err_name, err))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
192
iam/cli_views.py
192
iam/cli_views.py
@ -1,192 +0,0 @@
|
|||||||
import enum
|
|
||||||
import logging
|
|
||||||
from enum import Enum
|
|
||||||
from pprint import pformat, pprint
|
|
||||||
from types import SimpleNamespace
|
|
||||||
|
|
||||||
from iam.framework import (empty, get_app_logger, iterate_any, open_yaml,
|
|
||||||
prune, to_csv, to_json, to_yaml)
|
|
||||||
from rich import box
|
|
||||||
from rich.console import Console
|
|
||||||
from rich.pretty import pprint
|
|
||||||
from rich.prompt import Prompt
|
|
||||||
from rich.table import Table
|
|
||||||
|
|
||||||
from .lib.cli_views import ViewItem, ViewKind, ViewList
|
|
||||||
|
|
||||||
# Iam Implementations
|
|
||||||
# ===============================
|
|
||||||
|
|
||||||
|
|
||||||
MISSING_PKG = []
|
|
||||||
|
|
||||||
try:
|
|
||||||
import hcl2
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
MISSING_PKG.append("hcl2")
|
|
||||||
|
|
||||||
try:
|
|
||||||
import yaml
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
MISSING_PKG.append("yaml")
|
|
||||||
|
|
||||||
|
|
||||||
# Main views
|
|
||||||
# ======================
|
|
||||||
|
|
||||||
|
|
||||||
# def view_list(data, columns, title=None, fmt=None, **kwargs):
|
|
||||||
# "Show list view"
|
|
||||||
|
|
||||||
# fmt = fmt or OutputFormat.DEFAULT
|
|
||||||
# ret = None
|
|
||||||
# _kwargs = {
|
|
||||||
# key[len(fmt.value) + 1 :]: val
|
|
||||||
# for key, val in kwargs.items()
|
|
||||||
# if key.startswith(fmt.value)
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # print ("YOOO", fmt, OutputFormat.YAML)
|
|
||||||
# if fmt == OutputFormat.YAML:
|
|
||||||
# ret = to_yaml(restructure_list_to_dict(data, columns))
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.JSON:
|
|
||||||
# ret = to_json(restructure_list_to_dict(data, columns), nice=True)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.PYTHON:
|
|
||||||
# ret = pformat(restructure_list_to_dict(data, columns), indent=2)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.CSV:
|
|
||||||
# ret = to_csv(restructure_list_to_csv(data, columns))
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.ENV:
|
|
||||||
# ret = to_vars(restructure_list_to_env(data, columns), export=True)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.VARS:
|
|
||||||
# ret = to_vars(restructure_list_to_env(data, columns))
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.RICH_TABLE:
|
|
||||||
# ret = to_rich_table(data, columns=columns, title=title, **_kwargs)
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# raise Exception(f"Unmanagable format: {fmt}")
|
|
||||||
|
|
||||||
# console.print(ret)
|
|
||||||
|
|
||||||
|
|
||||||
# def view_show(data, columns=None, title=None):
|
|
||||||
# "Show single view"
|
|
||||||
|
|
||||||
# ret = None
|
|
||||||
# _kwargs = {
|
|
||||||
# key[len(fmt.value) + 1 :]: val
|
|
||||||
# for key, val in kwargs.items()
|
|
||||||
# if key.startswith(fmt.value)
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # print ("YOOO", fmt, OutputFormat.YAML)
|
|
||||||
# if fmt == OutputFormat.YAML:
|
|
||||||
# ret = to_yaml(data)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.JSON:
|
|
||||||
# ret = to_json(data, indent=2)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.PYTHON:
|
|
||||||
# ret = pformat(data, indent=2)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.CSV:
|
|
||||||
# ret = to_csv(data)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.RICH_TABLE:
|
|
||||||
# data = list(zip(*data))
|
|
||||||
# data.insert(0, ["Field", "Value"])
|
|
||||||
# ret = to_rich_table(data, **_kwargs)
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# raise Exception(f"Unmanagable format: {fmt}")
|
|
||||||
|
|
||||||
# return ret
|
|
||||||
|
|
||||||
|
|
||||||
# # DEPRECATED
|
|
||||||
# # ======================
|
|
||||||
|
|
||||||
|
|
||||||
# def output_list(payload, fmt=None, **kwargs):
|
|
||||||
# "Render output format"
|
|
||||||
# assert False, "DEPRECATED"
|
|
||||||
# fmt = fmt or OutputFormat.YAML
|
|
||||||
|
|
||||||
# # Requested format
|
|
||||||
# # payload = [
|
|
||||||
# # ["Header1", "Header2"], # First line is always headers
|
|
||||||
# # [["val1", "val2"]], # First row
|
|
||||||
# # [["val1", "val2"]], # Second row, etc ...
|
|
||||||
# # ]
|
|
||||||
|
|
||||||
# ret = None
|
|
||||||
# # _kwargs = {key.lstrip(f"{fmt.value}_"): val for key, val in kwargs.items() if key.startswith(fmt.value)}
|
|
||||||
# _kwargs = {
|
|
||||||
# key[len(fmt.value) + 1 :]: val
|
|
||||||
# for key, val in kwargs.items()
|
|
||||||
# if key.startswith(fmt.value)
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # print ("YOOO", fmt, OutputFormat.YAML)
|
|
||||||
# if fmt == OutputFormat.YAML:
|
|
||||||
# ret = to_yaml(payload)
|
|
||||||
# elif fmt == OutputFormat.JSON:
|
|
||||||
# ret = to_json(payload, indent=2)
|
|
||||||
# elif fmt == OutputFormat.PYTHON:
|
|
||||||
# ret = pformat(payload, indent=2)
|
|
||||||
# elif fmt == OutputFormat.CSV:
|
|
||||||
# ret = to_csv(payload)
|
|
||||||
# elif fmt == OutputFormat.RICH_TABLE:
|
|
||||||
# # pprint (kwargs)
|
|
||||||
# # pprint (_kwargs)
|
|
||||||
# return to_rich_table(payload, **_kwargs)
|
|
||||||
# else:
|
|
||||||
# raise Exception(f"Unmanagable format list: {fmt}")
|
|
||||||
|
|
||||||
# assert isinstance(ret, str)
|
|
||||||
# return ret
|
|
||||||
|
|
||||||
|
|
||||||
# def output_show(payload, fmt=None, **kwargs):
|
|
||||||
# "Show one item"
|
|
||||||
# assert False, "DEPRECATED"
|
|
||||||
|
|
||||||
# # Requested format
|
|
||||||
# # payload = [
|
|
||||||
# # ["Header1", "Header2"], # First line is always headers
|
|
||||||
# # [["val1", "val2"]], # First row ONLY
|
|
||||||
# # [["val1", "val2"]], # Second row, etc ...
|
|
||||||
# # ]
|
|
||||||
|
|
||||||
# ret = None
|
|
||||||
# _kwargs = {
|
|
||||||
# key[len(fmt.value) + 1 :]: val
|
|
||||||
# for key, val in kwargs.items()
|
|
||||||
# if key.startswith(fmt.value)
|
|
||||||
# }
|
|
||||||
|
|
||||||
# # print ("YOOO", fmt, OutputFormat.YAML)
|
|
||||||
# if fmt == OutputFormat.YAML:
|
|
||||||
# ret = to_yaml(payload)
|
|
||||||
|
|
||||||
# elif fmt == OutputFormat.JSON:
|
|
||||||
# ret = to_json(payload, indent=2)
|
|
||||||
# elif fmt == OutputFormat.PYTHON:
|
|
||||||
# ret = pformat(payload, indent=2)
|
|
||||||
# elif fmt == OutputFormat.CSV:
|
|
||||||
# ret = to_csv(payload)
|
|
||||||
# elif fmt == OutputFormat.RICH_TABLE:
|
|
||||||
# # Return data
|
|
||||||
# payload = list(zip(*payload))
|
|
||||||
# payload.insert(0, ["Field", "Value"])
|
|
||||||
# ret = to_rich_table(payload, **_kwargs)
|
|
||||||
|
|
||||||
# else:
|
|
||||||
# raise Exception(f"Unmanagable format show: {fmt}")
|
|
||||||
|
|
||||||
# return ret
|
|
||||||
@ -16,3 +16,7 @@ class UnknownResourceKind(IamException):
|
|||||||
|
|
||||||
class MissingConfigFiles(IamException):
|
class MissingConfigFiles(IamException):
|
||||||
"Raised when iam can't find any valid configuration file"
|
"Raised when iam can't find any valid configuration file"
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownServiceCommand(IamException):
|
||||||
|
"Raised when a command is not matched against services"
|
||||||
|
|||||||
@ -42,12 +42,12 @@ def get_app_logger(loggers=None, level="WARNING", colors=False, format="default"
|
|||||||
formatters = {
|
formatters = {
|
||||||
"default": {
|
"default": {
|
||||||
"()": fclass,
|
"()": fclass,
|
||||||
"format": "[%(levelname)s] %(message)s",
|
"format": "[%(levelname)8s] %(message)s",
|
||||||
# 'datefmt': '%Y-%m-%d %H:%M:%S',
|
# 'datefmt': '%Y-%m-%d %H:%M:%S',
|
||||||
},
|
},
|
||||||
"extended": {
|
"extended": {
|
||||||
"()": fclass,
|
"()": fclass,
|
||||||
"format": "[%(levelname)s] %(name)s: %(message)s",
|
"format": "[%(levelname)8s] %(name)s: %(message)s",
|
||||||
"datefmt": "%H:%M:%S",
|
"datefmt": "%H:%M:%S",
|
||||||
},
|
},
|
||||||
"audit": {
|
"audit": {
|
||||||
@ -57,7 +57,7 @@ def get_app_logger(loggers=None, level="WARNING", colors=False, format="default"
|
|||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"()": fclass,
|
"()": fclass,
|
||||||
"format": "%(msecs)03d [%(levelname)s] %(name)s: %(message)s [%(filename)s/%(funcName)s:%(lineno)d]",
|
"format": "%(msecs)03d [%(levelname)8s] %(name)s: %(message)s [%(filename)s/%(funcName)s:%(lineno)d]",
|
||||||
"datefmt": "%H:%M:%S",
|
"datefmt": "%H:%M:%S",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -81,15 +81,24 @@ def get_app_logger(loggers=None, level="WARNING", colors=False, format="default"
|
|||||||
"class": "logging.StreamHandler",
|
"class": "logging.StreamHandler",
|
||||||
"stream": "ext://sys.stderr", # Default is stderr
|
"stream": "ext://sys.stderr", # Default is stderr
|
||||||
},
|
},
|
||||||
|
"info": {
|
||||||
|
"level": "INFO",
|
||||||
|
"formatter": format,
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"stream": "ext://sys.stderr", # Default is stderr
|
||||||
|
},
|
||||||
},
|
},
|
||||||
# Where logs come from
|
# Where logs come from
|
||||||
"loggers": {
|
"loggers": {
|
||||||
|
|
||||||
# Used to catch ALL logs
|
# Used to catch ALL logs
|
||||||
"": { # root logger
|
"": { # root logger
|
||||||
"handlers": ["default"],
|
"handlers": ["default"],
|
||||||
"level": "WARNING",
|
"level": "WARNING",
|
||||||
"propagate": False,
|
"propagate": False,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
# # Used to catch all logs of myapp and sublibs
|
# # Used to catch all logs of myapp and sublibs
|
||||||
# 'myapp': {
|
# 'myapp': {
|
||||||
# 'handlers': ['default'],
|
# 'handlers': ['default'],
|
||||||
@ -297,6 +306,9 @@ class DictCtrl(_DictBase):
|
|||||||
def keys(self):
|
def keys(self):
|
||||||
return self._items.keys()
|
return self._items.keys()
|
||||||
|
|
||||||
|
def names(self):
|
||||||
|
return list(self._items.keys())
|
||||||
|
|
||||||
def has(self, name):
|
def has(self, name):
|
||||||
"Return true or false if an item exists"
|
"Return true or false if an item exists"
|
||||||
return True if name in self._items else False
|
return True if name in self._items else False
|
||||||
|
|||||||
@ -16,6 +16,12 @@ except ModuleNotFoundError:
|
|||||||
MISSING_PKGS.append("Table")
|
MISSING_PKGS.append("Table")
|
||||||
|
|
||||||
|
|
||||||
|
# TODO:
|
||||||
|
# toml/hcl support
|
||||||
|
# duckdb support => https://stackoverflow.com/a/70538527
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# MISSING_PKGS = []
|
# MISSING_PKGS = []
|
||||||
# try:
|
# try:
|
||||||
# from rich.console import Console
|
# from rich.console import Console
|
||||||
@ -311,33 +317,32 @@ class _RootView:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
fmt_ = SimpleNamespace(**fmt_config)
|
fmt_ = SimpleNamespace(**fmt_config)
|
||||||
print("FORMAT CONFIG")
|
# print("FORMAT CONFIG")
|
||||||
pprint(conf)
|
# pprint(conf)
|
||||||
pprint(fmt_)
|
# pprint(fmt_)
|
||||||
|
|
||||||
assert fmt_.name, f"Format name can't be None: {fmt_.name}"
|
assert fmt_.name, f"Format name can't be None: {fmt_.name}"
|
||||||
|
|
||||||
# check module presence
|
# check module presence
|
||||||
pprint(self.formats_modules)
|
|
||||||
mod_spec = self.formats_modules.get(fmt_.name, None)
|
mod_spec = self.formats_modules.get(fmt_.name, None)
|
||||||
print("MOD_NAME", fmt_.name, mod_spec)
|
# if mod_spec:
|
||||||
if mod_spec:
|
# # Extract specs
|
||||||
# Extract specs
|
# mod_package = None
|
||||||
mod_package = None
|
# mod_name = mod_spec
|
||||||
mod_name = mod_spec
|
# if isinstance(mod_spec, (list, set, tuple)):
|
||||||
if isinstance(mod_spec, (list, set, tuple)):
|
# mod_name = mod_spec[0]
|
||||||
mod_name = mod_spec[0]
|
# mod_package = mod_spec[1]
|
||||||
mod_package = mod_spec[1]
|
|
||||||
|
# # Check module presence
|
||||||
|
# # print("CHECKING MODE NAME", mod_name)
|
||||||
|
# ret = is_module_present(mod_name)
|
||||||
|
# if not ret:
|
||||||
|
# _msg = f"Missing python module '{mod_name}' to support '{fmt_.name}' output."
|
||||||
|
# if mod_package:
|
||||||
|
# _msg = f"{_msg} Please first install package: {mod_package}"
|
||||||
|
# logger.warning(_msg)
|
||||||
|
# # raise Exception(_msg)
|
||||||
|
|
||||||
# Check module presence
|
|
||||||
print("CHECKING MODE NAME", mod_name)
|
|
||||||
ret = is_module_present(mod_name)
|
|
||||||
if not ret:
|
|
||||||
_msg = f"Missing python module '{mod_name}' to support '{fmt_.name}' output."
|
|
||||||
if mod_package:
|
|
||||||
_msg = f"{_msg} Please first install package: {mod_package}"
|
|
||||||
logger.warning(_msg)
|
|
||||||
# raise Exception(_msg)
|
|
||||||
|
|
||||||
# Fetch renderer method
|
# Fetch renderer method
|
||||||
# ---------------------------
|
# ---------------------------
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import sys
|
||||||
import importlib
|
import importlib
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -235,9 +236,23 @@ def iterate_any(payload):
|
|||||||
|
|
||||||
# raise Exception(f"Could not iterate over: {payload}")
|
# raise Exception(f"Could not iterate over: {payload}")
|
||||||
|
|
||||||
|
def get_root_pkg_dir(name):
|
||||||
|
"""Return the dir where the actual paasify source code lives"""
|
||||||
|
|
||||||
|
assert not "." in name, "Only resrved for root pacakges"
|
||||||
|
|
||||||
|
# Look into each paths
|
||||||
|
for cand in sys.path:
|
||||||
|
target = os.path.join(cand, name)
|
||||||
|
if os.path.isdir(target):
|
||||||
|
return target
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_pkg_dir(name):
|
def get_pkg_dir(name):
|
||||||
"""Return the dir where the actual paasify source code lives"""
|
"""Return the dir where the actual paasify source code lives, it loads the module !!!"""
|
||||||
|
|
||||||
# pylint: disable=import-outside-toplevel
|
# pylint: disable=import-outside-toplevel
|
||||||
mod = import_module_pkg(name)
|
mod = import_module_pkg(name)
|
||||||
|
|||||||
@ -49,11 +49,11 @@ plugin_base = {
|
|||||||
"desc": "Disable shell ident",
|
"desc": "Disable shell ident",
|
||||||
"cmd": "unset SHELL_IDENT",
|
"cmd": "unset SHELL_IDENT",
|
||||||
},
|
},
|
||||||
"new": {
|
"id new": {
|
||||||
"desc": "Create shell identy",
|
"desc": "Create shell identy",
|
||||||
"cmd": "add_ident {{ param }}",
|
"cmd": "add_ident {{ param }}",
|
||||||
},
|
},
|
||||||
"delete": {
|
"id delete": {
|
||||||
"desc": "Delete shell identy",
|
"desc": "Delete shell identy",
|
||||||
"cmd": "rm_ident {{ param }}",
|
"cmd": "rm_ident {{ param }}",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -134,12 +134,12 @@ providers:
|
|||||||
unset MINIO_ACCESS_KEY MINIO_SECRET_KEY
|
unset MINIO_ACCESS_KEY MINIO_SECRET_KEY
|
||||||
|
|
||||||
|
|
||||||
new_alias:
|
minio new alias:
|
||||||
desc: Create alias
|
desc: Create alias
|
||||||
cmd: |
|
cmd: |
|
||||||
mc alias set {{ident}} {{api_url}} {{minio_user}} {{minio_password}}
|
mc alias set {{ident}} {{api_url}} {{minio_user}} {{minio_password}}
|
||||||
|
|
||||||
rm_alias:
|
minio delete alias:
|
||||||
desc: Remove alias
|
desc: Remove alias
|
||||||
cmd: |
|
cmd: |
|
||||||
mc alias rm {{ident}}
|
mc alias rm {{ident}}
|
||||||
|
|||||||
@ -14,9 +14,10 @@ providers:
|
|||||||
|
|
||||||
commands:
|
commands:
|
||||||
|
|
||||||
new:
|
ssh new:
|
||||||
desc: Create new SSH key
|
desc: Create new SSH key
|
||||||
cmd: |
|
|
||||||
|
shell: |
|
||||||
SSH_KEY_ALG={{ssh_key_alg}}
|
SSH_KEY_ALG={{ssh_key_alg}}
|
||||||
|
|
||||||
SSH_KEY_VERSION="$(date +'%Y%m%d')"
|
SSH_KEY_VERSION="$(date +'%Y%m%d')"
|
||||||
@ -30,7 +31,9 @@ providers:
|
|||||||
-N "{{ssh_key_secret}}" \
|
-N "{{ssh_key_secret}}" \
|
||||||
-C "$SSH_KEY_COMMENT"
|
-C "$SSH_KEY_COMMENT"
|
||||||
|
|
||||||
delete:
|
|
||||||
|
|
||||||
|
ssh delete:
|
||||||
desc: Delete existing SSH key
|
desc: Delete existing SSH key
|
||||||
cmd: |
|
cmd: |
|
||||||
find $HOME/.ssh/{ident}/ -name "{user}_*"
|
find $HOME/.ssh/{ident}/ -name "{user}_*"
|
||||||
@ -119,28 +122,92 @@ providers:
|
|||||||
|
|
||||||
commands:
|
commands:
|
||||||
|
|
||||||
|
shell_start:
|
||||||
|
desc: Start ssh-agent
|
||||||
|
cmd: |
|
||||||
|
socket=$HOME/.local/state/ssh-agent/{{user}}
|
||||||
|
start=true
|
||||||
|
|
||||||
|
running=2
|
||||||
|
if [[ ! -e "$socket.env" ]]; then
|
||||||
|
running=2
|
||||||
|
elif [[ -e "$socket" ]]; then
|
||||||
|
running=$(SSH_AUTH_SOCK=$socket ssh-add -l &>/dev/null; echo $rc)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$running" -eq 2 ]]; then
|
||||||
|
# Start agent
|
||||||
|
>&2 echo "Start ssh-agent for {{ident}}"
|
||||||
|
mkdir -p "${socket%/*}"
|
||||||
|
ssh-agent -a $socket -t {{ssh_agent_tmout}} > $socket.env
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset socket start running
|
||||||
|
|
||||||
|
# if [[ -d "/run/user/$(id -u)" ]]; then
|
||||||
|
# socket=/run/user/$(id -u)/ssh-agent/{{user}}
|
||||||
|
# else
|
||||||
|
|
||||||
|
# fi
|
||||||
|
|
||||||
|
|
||||||
shell_enable:
|
shell_enable:
|
||||||
desc: Enable ssh-agent
|
desc: Enable ssh-agent
|
||||||
|
|
||||||
cmd: |
|
cmd: |
|
||||||
export SSH_AUTH_SOCK={{ssh_agent_socket_dir}}/{{user}}
|
socket=$HOME/.local/state/ssh-agent/{{user}}
|
||||||
ssh-agent -a $SSH_AUTH_SOCK -t {{ssh_agent_tmout}}
|
|
||||||
# SSH_AGENT_PID= ???
|
if [[ -e "$socket.env" ]]; then
|
||||||
|
# >&2 echo "Enable ssh-agent for {{ident}}"
|
||||||
|
source "$socket.env" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset socket
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
shell_disable:
|
shell_disable:
|
||||||
desc: Disable ssh-agent
|
desc: Disable ssh-agent
|
||||||
cmd: ssh-agent -k && unset SSH_AUTH_SOCK
|
cmd: |
|
||||||
|
unset SSH_AUTH_SOCK SSH_AGENT_PID
|
||||||
|
|
||||||
|
|
||||||
|
shell_stop:
|
||||||
|
desc: Kill ssh-agent
|
||||||
|
cmd: |
|
||||||
|
socket=$HOME/.local/state/ssh-agent/{{user}}
|
||||||
|
|
||||||
|
if [[ -e "$socket.env" ]]; then
|
||||||
|
# >&2 echo "Enable ssh-agent for {{ident}}"
|
||||||
|
source "$socket.env" >/dev/null
|
||||||
|
# fi
|
||||||
|
|
||||||
|
# if [[ -n "$SSH_AGENT_PID" ]]; then
|
||||||
|
>&2 echo "Kill ssh-agent for {{ident}}"
|
||||||
|
eval "(ssh-agent -k)" >/dev/null
|
||||||
|
[[ -e "$socket.env" ]] && rm "$socket.env" || true
|
||||||
|
fi
|
||||||
|
unset socket
|
||||||
|
|
||||||
|
# env_file="$HOME/.local/state/ssh-agent/{{user}}.env"
|
||||||
|
|
||||||
|
# if [[ -f "$env_file" ]]; then
|
||||||
|
# source "$env_file"
|
||||||
|
# fi
|
||||||
|
# if [[ -f "$env_file" ]]; then
|
||||||
|
# rm "$env_file"
|
||||||
|
# fi
|
||||||
|
|
||||||
|
|
||||||
local.ssh_agent_keys:
|
local.ssh_agent_keys:
|
||||||
desc: Local ssh-agent keys
|
desc: Local ssh-agent keys
|
||||||
|
|
||||||
commands:
|
commands:
|
||||||
enable:
|
ssh add:
|
||||||
desc: Unload keys into ssh-agent
|
desc: Unload keys into ssh-agent
|
||||||
cmd: ssh-agent -d {ssh_key_file}
|
cmd: ssh-agent -d {ssh_key_file}
|
||||||
|
|
||||||
disable:
|
ssh rm:
|
||||||
desc: Load keys into ssh-agent
|
desc: Load keys into ssh-agent
|
||||||
cmd: |
|
cmd: |
|
||||||
ssh-add {% for item in loop %} {{item.ssh_key_file}} {% endfor %}
|
ssh-add {% for item in loop %} {{item.ssh_key_file}} {% endfor %}
|
||||||
@ -263,15 +330,16 @@ providers:
|
|||||||
commands:
|
commands:
|
||||||
|
|
||||||
shell_enable:
|
shell_enable:
|
||||||
desc: Enable git identity
|
desc: Enable PS1
|
||||||
cmd: |
|
cmd: |
|
||||||
OLD_PS1=$PS1
|
export OLD_PS1=$PS1
|
||||||
export PS1="\[\033[0;34m\]({{ident}})\[\033[00m\] ${PS1}"
|
export PS1="\033[0;34m\]({{ident}})\033[00m\] ${PS1}"
|
||||||
|
|
||||||
shell_disable:
|
shell_disable:
|
||||||
desc: Disable git identity
|
desc: Disable PS1
|
||||||
cmd: |
|
cmd: |
|
||||||
export PS1=$OLD_PS1
|
export PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
||||||
|
# export PS1="$OLD_PS1"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
169
poetry.lock
generated
169
poetry.lock
generated
@ -1,34 +1,5 @@
|
|||||||
# This file is automatically @generated by Poetry 1.6.0 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.6.0 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "attrs"
|
|
||||||
version = "23.1.0"
|
|
||||||
description = "Classes Without Boilerplate"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.7"
|
|
||||||
files = [
|
|
||||||
{file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
|
|
||||||
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
|
|
||||||
dev = ["attrs[docs,tests]", "pre-commit"]
|
|
||||||
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
|
|
||||||
tests = ["attrs[tests-no-zope]", "zope-interface"]
|
|
||||||
tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autopage"
|
|
||||||
version = "0.5.1"
|
|
||||||
description = "A library to provide automatic paging for console output"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "autopage-0.5.1-py3-none-any.whl", hash = "sha256:0fbf5efbe78d466a26753e1dee3272423a3adc989d6a778c700e89a3f8ff0d88"},
|
|
||||||
{file = "autopage-0.5.1.tar.gz", hash = "sha256:01be3ee61bb714e9090fcc5c10f4cf546c396331c620c6ae50a2321b28ed3199"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "black"
|
name = "black"
|
||||||
version = "23.9.1"
|
version = "23.9.1"
|
||||||
@ -87,47 +58,6 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cliff"
|
|
||||||
version = "4.3.0"
|
|
||||||
description = "Command Line Interface Formulation Framework"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "cliff-4.3.0-py3-none-any.whl", hash = "sha256:db3dc8774f47db9aa86796921ff158d0f023630261c2746c4fff12584b75f5b2"},
|
|
||||||
{file = "cliff-4.3.0.tar.gz", hash = "sha256:fc5b6ebc8fb815332770b2485ee36c09753937c37cce4f3227cdd4e10b33eacc"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
autopage = ">=0.4.0"
|
|
||||||
cmd2 = ">=1.0.0"
|
|
||||||
importlib-metadata = ">=4.4"
|
|
||||||
PrettyTable = ">=0.7.2"
|
|
||||||
PyYAML = ">=3.12"
|
|
||||||
stevedore = ">=2.0.1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cmd2"
|
|
||||||
version = "2.4.3"
|
|
||||||
description = "cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "cmd2-2.4.3-py3-none-any.whl", hash = "sha256:f1988ff2fff0ed812a2d25218a081b0fa0108d45b48ba2a9272bb98091b654e6"},
|
|
||||||
{file = "cmd2-2.4.3.tar.gz", hash = "sha256:71873c11f72bd19e2b1db578214716f0d4f7c8fa250093c601265a9a717dee52"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
attrs = ">=16.3.0"
|
|
||||||
pyperclip = ">=1.6"
|
|
||||||
pyreadline3 = {version = "*", markers = "sys_platform == \"win32\""}
|
|
||||||
wcwidth = ">=0.1.7"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["codecov", "doc8", "flake8", "invoke", "mypy", "nox", "pytest (>=4.6)", "pytest-cov", "pytest-mock", "sphinx", "sphinx-autobuild", "sphinx-rtd-theme", "twine (>=1.11)"]
|
|
||||||
test = ["codecov", "coverage", "gnureadline", "pytest (>=4.6)", "pytest-cov", "pytest-mock"]
|
|
||||||
validate = ["flake8", "mypy", "types-pkg-resources"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
@ -170,25 +100,6 @@ files = [
|
|||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""}
|
pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""}
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "importlib-metadata"
|
|
||||||
version = "6.8.0"
|
|
||||||
description = "Read metadata from Python packages"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"},
|
|
||||||
{file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
zipp = ">=0.5"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
||||||
perf = ["ipython"]
|
|
||||||
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "isort"
|
name = "isort"
|
||||||
version = "5.12.0"
|
version = "5.12.0"
|
||||||
@ -350,17 +261,6 @@ files = [
|
|||||||
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
|
{file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pbr"
|
|
||||||
version = "5.11.1"
|
|
||||||
description = "Python Build Reasonableness"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=2.6"
|
|
||||||
files = [
|
|
||||||
{file = "pbr-5.11.1-py2.py3-none-any.whl", hash = "sha256:567f09558bae2b3ab53cb3c1e2e33e726ff3338e7bae3db5dc954b3a44eef12b"},
|
|
||||||
{file = "pbr-5.11.1.tar.gz", hash = "sha256:aefc51675b0b533d56bb5fd1c8c6c0522fe31896679882e1c4c63d5e4a0fccb3"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "3.11.0"
|
version = "3.11.0"
|
||||||
@ -376,23 +276,6 @@ files = [
|
|||||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
|
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"]
|
||||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
|
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prettytable"
|
|
||||||
version = "3.9.0"
|
|
||||||
description = "A simple Python library for easily displaying tabular data in a visually appealing ASCII table format"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "prettytable-3.9.0-py3-none-any.whl", hash = "sha256:a71292ab7769a5de274b146b276ce938786f56c31cf7cea88b6f3775d82fe8c8"},
|
|
||||||
{file = "prettytable-3.9.0.tar.gz", hash = "sha256:f4ed94803c23073a90620b201965e5dc0bccf1760b7a7eaf3158cab8aaffdf34"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
wcwidth = "*"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
tests = ["pytest", "pytest-cov", "pytest-lazy-fixture"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyaml"
|
name = "pyaml"
|
||||||
version = "23.9.6"
|
version = "23.9.6"
|
||||||
@ -424,16 +307,6 @@ files = [
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
plugins = ["importlib-metadata"]
|
plugins = ["importlib-metadata"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pyperclip"
|
|
||||||
version = "1.8.2"
|
|
||||||
description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "pyperclip-1.8.2.tar.gz", hash = "sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyreadline3"
|
name = "pyreadline3"
|
||||||
version = "3.4.1"
|
version = "3.4.1"
|
||||||
@ -551,20 +424,6 @@ rich = ">=10.7.0"
|
|||||||
[package.extras]
|
[package.extras]
|
||||||
dev = ["pre-commit"]
|
dev = ["pre-commit"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "stevedore"
|
|
||||||
version = "5.1.0"
|
|
||||||
description = "Manage dynamic plugins for Python applications"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "stevedore-5.1.0-py3-none-any.whl", hash = "sha256:8cc040628f3cea5d7128f2e76cf486b2251a4e543c7b938f58d9a377f6694a2d"},
|
|
||||||
{file = "stevedore-5.1.0.tar.gz", hash = "sha256:a54534acf9b89bc7ed264807013b505bf07f74dbe4bcfa37d32bd063870b087c"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
pbr = ">=2.0.0,<2.1.0 || >2.1.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typer"
|
name = "typer"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -597,33 +456,7 @@ files = [
|
|||||||
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
|
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wcwidth"
|
|
||||||
version = "0.2.8"
|
|
||||||
description = "Measures the displayed width of unicode strings in a terminal"
|
|
||||||
optional = false
|
|
||||||
python-versions = "*"
|
|
||||||
files = [
|
|
||||||
{file = "wcwidth-0.2.8-py2.py3-none-any.whl", hash = "sha256:77f719e01648ed600dfa5402c347481c0992263b81a027344f3e1ba25493a704"},
|
|
||||||
{file = "wcwidth-0.2.8.tar.gz", hash = "sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zipp"
|
|
||||||
version = "3.17.0"
|
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"},
|
|
||||||
{file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"]
|
|
||||||
testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
|
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.11"
|
python-versions = "^3.11"
|
||||||
content-hash = "6c7761768920ef58522d19560d56ce366cca74dc275b4e019acf10838923d63d"
|
content-hash = "1747400a30523d50e0ccaf55386f60f05b4d6e5e222aeb8a737d4e78b702a210"
|
||||||
|
|||||||
@ -20,11 +20,13 @@ pyxdg = "^0.28"
|
|||||||
coloredlogs = "^15.0.1"
|
coloredlogs = "^15.0.1"
|
||||||
rich = "^13.6.0"
|
rich = "^13.6.0"
|
||||||
rich-click = "^1.6.1"
|
rich-click = "^1.6.1"
|
||||||
|
colorama = "^0.4.6"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.scripts]
|
[tool.poetry.scripts]
|
||||||
iam2 = "iam.cli:run"
|
|
||||||
iam = "iam.cli_click:run"
|
iam = "iam.cli_click:run"
|
||||||
|
iam2 = "iam.cli_typer:run"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
black = "^23.9.1"
|
black = "^23.9.1"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user