ci: run ci and add a helper script

This commit is contained in:
mrjk 2023-10-09 03:58:37 -04:00
parent eda4c8ffd9
commit cbe88fba59
9 changed files with 118 additions and 120 deletions

View File

@ -12,7 +12,7 @@ from . import exceptions as error
from .catalog import Catalog
from .framework import DictItem, scoped_ident
from .idents import Idents
from .lib.utils import import_module, open_yaml, get_root_pkg_dir
from .lib.utils import get_root_pkg_dir, import_module, open_yaml
from .meta import NAME, VERSION
from .providers import Providers
@ -169,7 +169,6 @@ class App:
"Disable shell"
return self.catalog.shell_disable(**kwargs)
def shell_install(self, shell="bash", completion=True):
"Show your install script for shell"
@ -193,4 +192,4 @@ class App:
out.append(f" source {completion_file}")
out.append(f"fi")
out.append(f"### IAM ###")
return '\n'.join(out)
return "\n".join(out)

View File

@ -1,18 +1,18 @@
import os
import logging
import os
from collections import namedtuple
from pprint import pprint
from types import SimpleNamespace
import sh
# TO BE REMOVED !!!!
import click
import sh
from . import exceptions as error
from .framework import DictCtrl, DictItem, KeyValue, KeyValueExtra
from .idents import Ident
from .lib.utils import format_render, jinja_render, uniq, jinja_template_vars, empty
from .lib.utils import (empty, format_render, jinja_render,
jinja_template_vars, uniq)
logger = logging.getLogger(__name__)
cli_logger = logging.getLogger("iam.cli")
@ -54,19 +54,14 @@ class ServiceCommand(DictItem):
default_attrs = {
"desc": "Service without description",
"cmd": "", # Direct commands to launch
"shell": "", # Will be run in a shell (or specific shell below)
"shell": "", # Will be run in a shell (or specific shell below)
# "shell_sh": "",
# "shell_bash": "",
# "shell_zsh": "",
# "shell_fish": "",
# "shell_bash": "",
# "source_output": False, # True for shell commands by default !
}
# Overrides
@ -76,7 +71,6 @@ class ServiceCommand(DictItem):
"Transform short form into long form"
self.service = self.parent
# def payload_transform(self, name, kwargs=None):
# "Transform short form into long form"
# self.service = self.parent
@ -111,7 +105,6 @@ class Service(DictItem):
self.catalog = self.parent.catalog
def init(self):
ret = {}
for cmd_name, cmd in self.commands.items():
ret[cmd_name] = ServiceCommand(cmd_name, cmd, parent=self)
@ -229,7 +222,7 @@ class Service(DictItem):
out = cmd.format(**env_var)
except KeyError as err:
msg = f"Missing variable: {err} for service: {res.key}"
logger.warning (msg)
logger.warning(msg)
out = msg
# raise IamException(msg)
@ -245,9 +238,9 @@ class Service(DictItem):
def get_cmds(self):
"Get all services commands objects"
return [cmd for name, cmd in self.commands.items() if not name.startswith("shell")]
return [
cmd for name, cmd in self.commands.items() if not name.startswith("shell")
]
def list_cmds(self):
"List all services commands"
@ -268,7 +261,6 @@ class Service(DictItem):
# cmd_name = cmd_name[len(shell_prefix):]
name = f"{cmd_name}_{prefix}"
else:
name = cmd_name.replace("_", " ")
target[name] = conf.desc
@ -293,13 +285,11 @@ class Services(DictCtrl):
items_class = Service
RESERVED_CMD_PREFIX=["kind", "res", "svc", "shell", "run"]
RESERVED_CMD_PREFIX = ["kind", "res", "svc", "shell", "run"]
def prepare(self):
self.catalog = self.parent
def get_svc_command(self, cmd):
"Return the command to be run"
@ -311,13 +301,12 @@ class Services(DictCtrl):
# Retrieve command list
cmds = self.list_cmds()
cmd_names = [cmd.name for cmd in cmds ]
cmd_names = [cmd.name for cmd in cmds]
# Find best matching command
cmd_split_idx = None
cmd = None
curr=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:
@ -328,7 +317,7 @@ class Services(DictCtrl):
# Validate result
if not cmd:
_choices = ','.join(cmd_names)
_choices = ",".join(cmd_names)
_msg = f"No such services command named: {cmd_req}, please choose one of: {_choices}"
raise error.UnknownServiceCommand(_msg)
@ -336,8 +325,6 @@ class Services(DictCtrl):
return cmd, args
def list_cmds(self):
"List all services commands"
@ -351,18 +338,17 @@ class Services(DictCtrl):
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 )
_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)
_msg = f"Duplicates values! {conf}"
raise Exception(_msg)
return ret
def get_linked_resources(self):
"""
Like get method, but only grab enabled services
@ -791,7 +777,6 @@ class Context(DictItem):
self._vars = {
"ident": self.ident.name,
"user": self.ident.name,
"config_dir": root_dir,
"scripts_dir": os.path.join(root_dir, "scripts"),
"bin_dir": os.path.join(root_dir, "bin"),
@ -912,14 +897,12 @@ class Catalog:
# return self.services.get_loading_order(reverse=reverse)
# Shell helpers
# ================
def shell_enable(self, run_start=True):
"Enable shell"
actions = ["shell_enable"]
if run_start:
actions.insert(0, "shell_start")
@ -928,7 +911,6 @@ class Catalog:
return self._shell_action(actions)
def shell_disable(self, run_stop=False):
"Disable shell"
@ -940,7 +922,6 @@ class Catalog:
return self._shell_action(actions)
def _shell_action(self, action_names, reverse=False):
"Run command order"
@ -993,22 +974,20 @@ class Catalog:
# pprint (ctx_vars)
cmd = jinja_render(cmd_shell, ctx_vars)
output_code.append(f"# Loading: {action_name} {res.name} ({service.name})")
output_code.append(
f"# Loading: {action_name} {res.name} ({service.name})"
)
output_code.append(f"# =====================")
output_code.append(cmd)
output_code.append("\n")
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)
@ -1049,14 +1028,12 @@ class Catalog:
out = None
if cmd.shell:
mode = "shell"
payload = cmd.shell
# Scan for missing vars !!!
tmp = jinja_template_vars(payload)
tmp = jinja_template_vars(payload)
prompt_vars = []
for var_name in tmp:
if var_name not in ctx_vars:
@ -1074,7 +1051,7 @@ class Catalog:
answered_items = {}
for missed in prompt_vars:
default = ctx_vars.get(missed, None)
result = click.prompt(f'Select value for {missed}', default=default)
result = click.prompt(f"Select value for {missed}", default=default)
answered_items[missed] = result
ctx_vars.update(answered_items)
@ -1105,15 +1082,13 @@ class Catalog:
if sh_args:
out = cmd(sh_args, _fg=True, _env=new_env)
else:
out = cmd( _fg=True, _env=new_env)
out = cmd(_fg=True, _env=new_env)
# print (out)
else:
raise Exception("MIssing cmd or shell in config !")
return out
# print ("RUN CMD", mode, "\n\n\n====\n", real_cmd)

View File

@ -45,7 +45,7 @@ else:
import rich_click as click
from rich_click import RichGroup
from rich import box #, print
from rich import box # , print
from rich.console import Console
# Overrides defaults
from rich.pretty import pprint
@ -99,7 +99,7 @@ DEFAULT_LOG_LEVEL = 30 # warning
DEBUG = os.environ.get("IAM_DEBUG", "False")
DEFAULT_IDENT = os.environ.get("IAM_IDENT", os.environ.get("SHELL_IDENT", ""))
DEFAULT_FORMAT = os.environ.get("IAM_FORMAT", "table")
DEFAULT_HELP_OPTIONS=["-h", "--help"]
DEFAULT_HELP_OPTIONS = ["-h", "--help"]
DEFAULT_SHELL = os.environ.get("SHELL", "bash")
# list_view.formats_enum
@ -222,8 +222,7 @@ def get_var(name, default=None):
# @click.group(cls=NestedHelpGroup, context_settings=CONTEXT_SETTINGS)
@click.group(cls=NestedHelpGroup
)
@click.group(cls=NestedHelpGroup)
@global_options
@format_options
@click.version_option()
@ -686,7 +685,11 @@ def cli__shell():
@format_options
@click.pass_context
def shell_idents(
ctx, fmt_name=None, fmt_fields=None, fmt_sort=None, verbose=None,
ctx,
fmt_name=None,
fmt_fields=None,
fmt_sort=None,
verbose=None,
):
"Shell identities"
columns = ["name"]
@ -736,11 +739,15 @@ def shell_order(
)
@cli__shell.command("enable")
@click.option(
"skip_start", "--no-start", "-b", is_flag=True, show_default=False, default=False, help="Disable background process start"
"skip_start",
"--no-start",
"-b",
is_flag=True,
show_default=False,
default=False,
help="Disable background process start",
)
@click.pass_context
def shell_enable(ctx, skip_start=True, verbose=None):
@ -750,10 +757,15 @@ def shell_enable(ctx, skip_start=True, verbose=None):
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"
"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):
@ -765,7 +777,13 @@ def shell_disable(ctx, run_stop=False, verbose=None):
@cli__shell.command("kill")
@click.option(
"all_idents", "--all", "-a", is_flag=True, show_default=False, default=False, help="Kill on all users"
"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):
@ -785,20 +803,30 @@ def shell_kill(ctx, all_idents=False, verbose=None):
ret.append(app.shell_enable(run_start=False))
ret.append(app.shell_disable(run_stop=True))
print('\n'.join(ret))
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"
"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"
"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"
@ -808,9 +836,8 @@ def shell_switch(ctx, ident="", run_stop=False, skip_start=True, verbose=None):
src_ident = app.catalog.ident.name
dst_ident = ident
if src_ident == dst_ident:
print (">&2 echo 'No need to change'")
print(">&2 echo 'No need to change'")
else:
ret = []
@ -824,32 +851,25 @@ def shell_switch(ctx, ident="", run_stop=False, skip_start=True, verbose=None):
ret.append(app.shell_enable(run_start=not skip_start))
# Output
print('\n'.join(ret))
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",
@cli_app.command(
"run",
# cls=TmpGroup,
context_settings=dict(
ignore_unknown_options=True,
allow_extra_args=True,
help_option_names=[]
)
ignore_unknown_options=True, allow_extra_args=True, help_option_names=[]
),
)
@click.argument('cmd_params', nargs=-1, type=click.UNPROCESSED)
@click.argument("cmd_params", nargs=-1, type=click.UNPROCESSED)
@click.pass_context
def cli_app_run(ctx, cmd_params):
# print("Will run cmd:", cmd_params)
# Check first help parameter only
@ -867,7 +887,6 @@ def cli_app_run(ctx, cmd_params):
click.echo(ctx.get_help())
return
# Get instanciated app
app = ctx.obj.app
@ -875,7 +894,6 @@ def cli_app_run(ctx, cmd_params):
ret = app.catalog.services.list_cmds()
data = [[x.name, x.desc] for x in ret]
# Render data
ctx.obj.render_list(
data,
@ -892,11 +910,10 @@ def cli_app_run(ctx, cmd_params):
# Run the output
ret = app.catalog.run_svc_cmd(cmd=cmd_params)
print (ret)
print(ret)
# pprint (ret, expand_all=True)
# @cli_app.command("run2",
# context_settings=dict(
# ignore_unknown_options=True,
@ -912,9 +929,7 @@ def cli_app_run(ctx, cmd_params):
@cli__shell.command("install")
@click.argument("shell",
required=False,
default=DEFAULT_SHELL)
@click.argument("shell", required=False, default=DEFAULT_SHELL)
@click.pass_context
def shell_install(ctx, shell=None, verbose=None):
"Install iam in your shell"
@ -926,7 +941,6 @@ def shell_install(ctx, shell=None, verbose=None):
# print("-- %< --" * 8)
# Exception handler
# ===============================
def clean_terminate(err):

View File

@ -90,15 +90,12 @@ def get_app_logger(loggers=None, level="WARNING", colors=False, format="default"
},
# Where logs come from
"loggers": {
# Used to catch ALL logs
"": { # root logger
"handlers": ["default"],
"level": "WARNING",
"propagate": False,
},
# # Used to catch all logs of myapp and sublibs
# 'myapp': {
# 'handlers': ['default'],

View File

@ -21,7 +21,6 @@ except ModuleNotFoundError:
# duckdb support => https://stackoverflow.com/a/70538527
# MISSING_PKGS = []
# try:
# from rich.console import Console
@ -343,7 +342,6 @@ class _RootView:
# logger.warning(_msg)
# # raise Exception(_msg)
# Fetch renderer method
# ---------------------------
fmt_name = fmt_.name

View File

@ -1,4 +1,5 @@
import logging
import click
logger = logging.getLogger(__name__)
@ -49,7 +50,6 @@ class NestedHelpGroup(click.Group):
"""
# For partial name resolution
def resolve_command(self, ctx, args):
"Return the full command name if changed"
@ -59,7 +59,6 @@ class NestedHelpGroup(click.Group):
logger.debug(f"Rewrite command '{_}' to '{cmd.name}'")
return cmd.name, cmd, args
def get_command(self, ctx, cmd_name: str):
"""Given a context and a command name, this returns a :class:`Command`
object if it exists or returns ``None``.
@ -67,7 +66,7 @@ class NestedHelpGroup(click.Group):
# Resolve name part by part
parts = cmd_name.split(" ")
len_parts = len(parts) -1
len_parts = len(parts) - 1
curr = self
for idx, part in enumerate(parts):
match = curr.commands.get(part)
@ -75,8 +74,13 @@ class NestedHelpGroup(click.Group):
# Look for shortcut if last part
if match is None:
# Look for direct children only
matches = [x for x in self._resolve_children(self, ctx=ctx, ignore_groups=False, deep=0)
if x.startswith(cmd_name)]
matches = [
x
for x in self._resolve_children(
self, ctx=ctx, ignore_groups=False, deep=0
)
if x.startswith(cmd_name)
]
# Look for possible matches
if not matches:
@ -84,7 +88,9 @@ class NestedHelpGroup(click.Group):
elif len(matches) == 1:
match = click.Group.get_command(self, ctx, matches[0])
else:
ctx.fail(f"Too many matches for {cmd_name}: {', '.join(sorted(matches))}")
ctx.fail(
f"Too many matches for {cmd_name}: {', '.join(sorted(matches))}"
)
# Iterate over next child!
curr = match
@ -97,7 +103,9 @@ class NestedHelpGroup(click.Group):
return sorted(self._resolve_children(self, ctx=ctx, ignore_groups=True))
@classmethod
def _resolve_children(cls, obj, ctx=None, ignore_groups=False, _parent=None, deep=-1):
def _resolve_children(
cls, obj, ctx=None, ignore_groups=False, _parent=None, deep=-1
):
"Resolve recursively all children"
# Source: Adapted from https://stackoverflow.com/a/56159096
@ -119,14 +127,17 @@ class NestedHelpGroup(click.Group):
# Recursive loop
if deep != 0:
deep = deep -1
deep = deep - 1
ret.extend(
cls._resolve_children(
child, ctx=ctx, ignore_groups=ignore_groups, _parent=full_name, deep=deep
child,
ctx=ctx,
ignore_groups=ignore_groups,
_parent=full_name,
deep=deep,
)
)
return ret
return []

View File

@ -1,8 +1,8 @@
import sys
import importlib
import json
import logging
import os
import sys
import tomllib
from pprint import pprint
@ -83,6 +83,7 @@ def prune(items):
raise Exception(f"Function prune requires a list or a dict, got: {items}")
return ret
# from jinja2 import Environment, FileSystemLoader, meta
# env = Environment(loader=FileSystemLoader('templates'))
@ -91,9 +92,9 @@ def prune(items):
from jinja2 import Environment, PackageLoader, meta
def jinja_template_vars(payload):
env = Environment() #loader=PackageLoader('templates'))
def jinja_template_vars(payload):
env = Environment() # loader=PackageLoader('templates'))
parsed_content = env.parse(payload)
return meta.find_undeclared_variables(parsed_content)
@ -250,6 +251,7 @@ def iterate_any(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"""
@ -264,7 +266,6 @@ def get_root_pkg_dir(name):
return None
def get_pkg_dir(name):
"""Return the dir where the actual paasify source code lives, it loads the module !!!"""

View File

@ -7,6 +7,4 @@ yml_dir = get_pkg_dir(__name__)
plugin_conf = open_yaml(os.path.join(yml_dir, "local.yml"))[0]
all = plugin_conf.get("providers", {})

5
run_ci.sh Executable file
View File

@ -0,0 +1,5 @@
#!/bin/bash
black iam/
isort iam/