update: plugin system to load yaml/python
This commit is contained in:
parent
cbe88fba59
commit
724eb8e780
87
iam/app.py
87
iam/app.py
@ -1,6 +1,7 @@
|
|||||||
import glob
|
import glob
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
@ -12,23 +13,24 @@ 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 get_root_pkg_dir, import_module, open_yaml
|
from .lib.utils import (filter_existing_files, get_root_pkg_dir, import_module,
|
||||||
|
open_yaml, to_yaml)
|
||||||
from .meta import NAME, VERSION
|
from .meta import NAME, VERSION
|
||||||
from .providers import Providers
|
from .providers import Providers
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
IamException = error.IamException
|
# IamException = error.IamException
|
||||||
|
|
||||||
|
|
||||||
class App:
|
class App:
|
||||||
name = NAME
|
name = NAME
|
||||||
|
|
||||||
def __init__(self, ident="_", config_path=None):
|
def __init__(self, ident="_", config_path=None, cli_context=None):
|
||||||
# Load application
|
self.cli_ctx = cli_context
|
||||||
db = self.load_config_files(config_path=config_path)
|
|
||||||
|
|
||||||
self.load_db(db)
|
# Load application
|
||||||
|
self.init_db(config_path)
|
||||||
self.init_ident(ident)
|
self.init_ident(ident)
|
||||||
|
|
||||||
def init_ident(self, ident):
|
def init_ident(self, ident):
|
||||||
@ -49,7 +51,7 @@ class App:
|
|||||||
self.ident = self.idents.get(self.ident_name)
|
self.ident = self.idents.get(self.ident_name)
|
||||||
|
|
||||||
# Load user and catalog
|
# Load user and catalog
|
||||||
self.catalog = Catalog(self, self.ident)
|
self.catalog = Catalog(self, self.ident, self.cli_ctx)
|
||||||
|
|
||||||
def load_config_files(self, config_path=None):
|
def load_config_files(self, config_path=None):
|
||||||
"Fetch config from default place"
|
"Fetch config from default place"
|
||||||
@ -68,7 +70,7 @@ class App:
|
|||||||
files = glob.glob(f"{path}/*.yml")
|
files = glob.glob(f"{path}/*.yml")
|
||||||
|
|
||||||
for file_ in files:
|
for file_ in files:
|
||||||
file_ = os.path.join(path, file_)
|
# file_ = os.path.join(path, file_) # Python > 3.10, see above
|
||||||
payloads = open_yaml(file_)
|
payloads = open_yaml(file_)
|
||||||
for payload in payloads:
|
for payload in payloads:
|
||||||
config_candidates.append(
|
config_candidates.append(
|
||||||
@ -89,16 +91,24 @@ class App:
|
|||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
def load_db(self, db):
|
def init_db(self, config_path):
|
||||||
"Load database"
|
"Load database"
|
||||||
|
|
||||||
|
# Update python PATH for later plugin loading
|
||||||
|
self.conf_plugin_dir = os.path.join(config_path, "plugins")
|
||||||
|
sys.path.insert(0, self.conf_plugin_dir)
|
||||||
|
|
||||||
# Init Databases
|
# Init Databases
|
||||||
|
db = self.load_config_files(config_path=config_path)
|
||||||
self.db = db
|
self.db = db
|
||||||
self._load_plugins(db.get("plugins", []))
|
self._load_plugins(db.get("plugins", []))
|
||||||
|
|
||||||
# Load providers
|
# Load providers
|
||||||
providers_conf = {}
|
providers_conf = {}
|
||||||
providers_conf.update(self.plugin_providers)
|
providers_conf.update(self.plugin_providers)
|
||||||
|
|
||||||
|
# pprint(providers_conf)
|
||||||
|
|
||||||
providers_conf.update(db.get("providers", {}))
|
providers_conf.update(db.get("providers", {}))
|
||||||
self.providers = Providers("ConfigProviders", providers_conf)
|
self.providers = Providers("ConfigProviders", providers_conf)
|
||||||
|
|
||||||
@ -114,29 +124,52 @@ class App:
|
|||||||
|
|
||||||
plugins = {}
|
plugins = {}
|
||||||
for plugin_name in plugins_refs:
|
for plugin_name in plugins_refs:
|
||||||
if not ":" in plugin_name:
|
providers = self.parse_plugin_def(plugin_name)
|
||||||
plugin_name = plugin_name + ":all"
|
|
||||||
|
|
||||||
load_one = False
|
plugins.update(providers)
|
||||||
if not plugin_name.endswith(":all"):
|
|
||||||
load_one = plugin_name.split(":", 2)[1]
|
|
||||||
|
|
||||||
mod = None
|
# print (to_yaml(mod))
|
||||||
try:
|
|
||||||
mod = import_module(plugin_name)
|
|
||||||
except ModuleNotFoundError as err:
|
|
||||||
msg = f"Impossible to load module: {plugin_name}"
|
|
||||||
raise IamException(msg)
|
|
||||||
print(err)
|
|
||||||
continue
|
|
||||||
|
|
||||||
if load_one:
|
|
||||||
mod = {load_one: mod}
|
|
||||||
|
|
||||||
plugins.update(mod)
|
|
||||||
|
|
||||||
self.plugin_providers = plugins
|
self.plugin_providers = plugins
|
||||||
|
|
||||||
|
def parse_plugin_def(self, plugin_name):
|
||||||
|
mod_name = plugin_name
|
||||||
|
mod_comp = "__all__"
|
||||||
|
if ":" in plugin_name:
|
||||||
|
mod_name, mod_comp = plugin_name.split(":", 2)
|
||||||
|
plugin_name = f"{mod_name}:{mod_comp}"
|
||||||
|
|
||||||
|
# Load plugin
|
||||||
|
providers = None
|
||||||
|
matches = filter_existing_files(
|
||||||
|
self.conf_plugin_dir, [f"{mod_name}.yml", f"{mod_name}.yaml"]
|
||||||
|
)
|
||||||
|
|
||||||
|
if matches:
|
||||||
|
logger.debug(f"Load YAML plugin {mod_name}")
|
||||||
|
providers = open_yaml(matches[0])[0].get("providers")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
mod = import_module(mod_name)
|
||||||
|
logger.debug(f"Load Python plugin {mod_name}")
|
||||||
|
providers = mod.providers
|
||||||
|
except ModuleNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# pprint(providers)
|
||||||
|
|
||||||
|
# Report empty plugins
|
||||||
|
if not providers:
|
||||||
|
_msg = f"Impossible to load module: {plugin_name}"
|
||||||
|
raise error.ConfigUnknownPlugin(_msg)
|
||||||
|
|
||||||
|
# Select only required items
|
||||||
|
if not plugin_name.endswith(":__all__"):
|
||||||
|
item = providers.get(mod_comp)
|
||||||
|
providers = {mod_comp: item}
|
||||||
|
|
||||||
|
return providers
|
||||||
|
|
||||||
def user_dump(self, pattern=None):
|
def user_dump(self, pattern=None):
|
||||||
"Dump ident config"
|
"Dump ident config"
|
||||||
|
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import sh
|
|||||||
from . import exceptions as error
|
from . import exceptions as error
|
||||||
from .framework import DictCtrl, DictItem, KeyValue, KeyValueExtra
|
from .framework import DictCtrl, DictItem, KeyValue, KeyValueExtra
|
||||||
from .idents import Ident
|
from .idents import Ident
|
||||||
from .lib.utils import (empty, format_render, jinja_render,
|
from .lib.utils import (duplicates, empty, format_render, import_module,
|
||||||
jinja_template_vars, uniq)
|
jinja_render, jinja_template_vars, uniq)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
cli_logger = logging.getLogger("iam.cli")
|
cli_logger = logging.getLogger("iam.cli")
|
||||||
@ -55,6 +55,7 @@ class ServiceCommand(DictItem):
|
|||||||
default_attrs = {
|
default_attrs = {
|
||||||
"desc": "Service without description",
|
"desc": "Service without description",
|
||||||
"cmd": "", # Direct commands to launch
|
"cmd": "", # Direct commands to launch
|
||||||
|
"python": "", # Will be run in as python
|
||||||
"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_sh": "",
|
||||||
# "shell_bash": "",
|
# "shell_bash": "",
|
||||||
@ -301,7 +302,7 @@ class Services(DictCtrl):
|
|||||||
|
|
||||||
# Retrieve command list
|
# Retrieve command list
|
||||||
cmds = self.list_cmds()
|
cmds = self.list_cmds()
|
||||||
cmd_names = [cmd.name for cmd in cmds]
|
cmd_names = [cmd.cmd.name for cmd in cmds]
|
||||||
|
|
||||||
# Find best matching command
|
# Find best matching command
|
||||||
cmd_split_idx = None
|
cmd_split_idx = None
|
||||||
@ -328,26 +329,28 @@ class Services(DictCtrl):
|
|||||||
def list_cmds(self):
|
def list_cmds(self):
|
||||||
"List all services commands"
|
"List all services commands"
|
||||||
|
|
||||||
ret = []
|
cmd_catalog = []
|
||||||
for name, service in self.items():
|
for name, service in self.items():
|
||||||
cmds = service.get_cmds()
|
cmds = service.get_cmds()
|
||||||
ret.extend(cmds)
|
|
||||||
|
|
||||||
# Check for invalid configs
|
for cmd in cmds:
|
||||||
conf = []
|
# Check for invalid prefixes
|
||||||
for cmd in ret:
|
|
||||||
prefix = cmd.name.split(" ")[0]
|
prefix = cmd.name.split(" ")[0]
|
||||||
if prefix in self.RESERVED_CMD_PREFIX:
|
if prefix in self.RESERVED_CMD_PREFIX:
|
||||||
_msg = f"Forbidden prefix! {cmd}"
|
_msg = f"Forbidden prefix for command '{cmd.name}' in service: '{service.name}'"
|
||||||
raise Exception(_msg)
|
raise error.ConfigForbiddenPrefixCmds(_msg)
|
||||||
conf.append(cmd.name)
|
|
||||||
dump = uniq(conf)
|
|
||||||
|
|
||||||
if conf != dump:
|
# Check for duplicates
|
||||||
_msg = f"Duplicates values! {conf}"
|
dups = [x for x in cmd_catalog if x.cmd.name == cmd.name]
|
||||||
raise Exception(_msg)
|
if dups:
|
||||||
|
svcs = ",".join([x.svc.name for x in dups])
|
||||||
|
_msg = f"Duplicate command name '{cmd.name}' for services: '{svcs}' and '{service.name}'"
|
||||||
|
raise error.ConfigDuplicateCmds(_msg)
|
||||||
|
|
||||||
return ret
|
# Append to catalog
|
||||||
|
cmd_catalog.append(SimpleNamespace(svc=service, cmd=cmd))
|
||||||
|
|
||||||
|
return cmd_catalog
|
||||||
|
|
||||||
def get_linked_resources(self):
|
def get_linked_resources(self):
|
||||||
"""
|
"""
|
||||||
@ -763,6 +766,7 @@ class Context(DictItem):
|
|||||||
|
|
||||||
default_attrs = {
|
default_attrs = {
|
||||||
"ident": None,
|
"ident": None,
|
||||||
|
"cli_ctx": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
# Overrides
|
# Overrides
|
||||||
@ -795,7 +799,7 @@ class Context(DictItem):
|
|||||||
class Catalog:
|
class Catalog:
|
||||||
"Manage catalog resources"
|
"Manage catalog resources"
|
||||||
|
|
||||||
def __init__(self, app, ident):
|
def __init__(self, app, ident, cli_ctx=None):
|
||||||
# Prepare catalog
|
# Prepare catalog
|
||||||
self.app = app
|
self.app = app
|
||||||
self.ident = ident
|
self.ident = ident
|
||||||
@ -803,6 +807,7 @@ class Catalog:
|
|||||||
# Prepare context
|
# Prepare context
|
||||||
ctx_conf = {
|
ctx_conf = {
|
||||||
"ident": ident,
|
"ident": ident,
|
||||||
|
"cli_ctx": cli_ctx,
|
||||||
}
|
}
|
||||||
self.context = Context("current_context", ctx_conf, parent=self)
|
self.context = Context("current_context", ctx_conf, parent=self)
|
||||||
|
|
||||||
@ -847,9 +852,11 @@ class Catalog:
|
|||||||
# Get resources from providers and user
|
# Get resources from providers and user
|
||||||
providers = self.app.providers
|
providers = self.app.providers
|
||||||
ident = self.ident
|
ident = self.ident
|
||||||
|
# pprint (self.__dict__)
|
||||||
|
|
||||||
# Build kind catalog
|
# Build kind catalog
|
||||||
res_kind_configs = providers.get_resource_kinds()
|
res_kind_configs = providers.get_resource_kinds()
|
||||||
|
assert res_kind_configs, "TOFIX"
|
||||||
self.resources_kind = ResourcesKinds(
|
self.resources_kind = ResourcesKinds(
|
||||||
"CatalogResourcesKinds", payload=res_kind_configs, parent=self
|
"CatalogResourcesKinds", payload=res_kind_configs, parent=self
|
||||||
)
|
)
|
||||||
@ -986,12 +993,13 @@ class Catalog:
|
|||||||
def run_svc_cmd(self, cmd):
|
def run_svc_cmd(self, cmd):
|
||||||
"Run a command against the services"
|
"Run a command against the services"
|
||||||
|
|
||||||
cmd, args = self.services.get_svc_command(cmd)
|
cmd_def, args = self.services.get_svc_command(cmd)
|
||||||
|
|
||||||
# pprint (cmd.cmd)
|
# pprint (cmd_def)
|
||||||
# pprint (args)
|
# pprint (args)
|
||||||
|
|
||||||
service = cmd.service
|
service = cmd_def.svc
|
||||||
|
cmd = cmd_def.cmd
|
||||||
|
|
||||||
# pprint (service)
|
# pprint (service)
|
||||||
# pprint (service.__dict__)
|
# pprint (service.__dict__)
|
||||||
@ -1019,15 +1027,17 @@ class Catalog:
|
|||||||
|
|
||||||
# pprint (ctx_vars)
|
# pprint (ctx_vars)
|
||||||
|
|
||||||
|
env_prefix = "IAM_"
|
||||||
new_env = dict(os.environ)
|
new_env = dict(os.environ)
|
||||||
new_env.update(ctx_vars)
|
new_env.update({env_prefix + key: val for key, val in ctx_vars.items()})
|
||||||
# pprint(new_env)
|
|
||||||
|
|
||||||
if cmd.cmd and cmd.shell:
|
# Validate config: TOFIX: Should not be here !
|
||||||
logger.warning(f"Duplicate cmd and shell for {service.name}")
|
tests = [cmd.cmd, cmd.shell, cmd.python]
|
||||||
|
tests = [x for x in tests if x]
|
||||||
|
if len(tests) > 1:
|
||||||
|
logger.warning(f"Duplicate cmd and shell for {service.name}: {tests}")
|
||||||
|
|
||||||
out = None
|
out = None
|
||||||
|
|
||||||
if cmd.shell:
|
if cmd.shell:
|
||||||
mode = "shell"
|
mode = "shell"
|
||||||
payload = cmd.shell
|
payload = cmd.shell
|
||||||
@ -1069,9 +1079,12 @@ class Catalog:
|
|||||||
payload = cmd.cmd
|
payload = cmd.cmd
|
||||||
real_cmd = jinja_render(payload, ctx_vars)
|
real_cmd = jinja_render(payload, ctx_vars)
|
||||||
|
|
||||||
cmd_parts = real_cmd.split(" ", 1)
|
# print ("PAYLOAD", real_cmd)
|
||||||
|
|
||||||
|
cmd_parts = real_cmd.split(" ")
|
||||||
sh_cmd = cmd_parts[0]
|
sh_cmd = cmd_parts[0]
|
||||||
sh_args = cmd_parts[1] if len(cmd_parts) > 0 else []
|
sh_args = cmd_parts[1:] if len(cmd_parts) > 1 else []
|
||||||
|
sh_args.extend(args)
|
||||||
|
|
||||||
# print ("Prepare", sh_cmd, " ||| ", sh_args)
|
# print ("Prepare", sh_cmd, " ||| ", sh_args)
|
||||||
|
|
||||||
@ -1080,11 +1093,41 @@ class Catalog:
|
|||||||
|
|
||||||
cmd = sh.Command(sh_cmd)
|
cmd = sh.Command(sh_cmd)
|
||||||
if sh_args:
|
if sh_args:
|
||||||
|
# sh_args = sh_args.split(" ")
|
||||||
|
pprint(cmd)
|
||||||
|
pprint(sh_args)
|
||||||
out = cmd(sh_args, _fg=True, _env=new_env)
|
out = cmd(sh_args, _fg=True, _env=new_env)
|
||||||
else:
|
else:
|
||||||
out = cmd(_fg=True, _env=new_env)
|
out = cmd(_fg=True, _env=new_env)
|
||||||
|
|
||||||
# print (out)
|
# print (out)
|
||||||
|
elif cmd.python:
|
||||||
|
mode = "python"
|
||||||
|
plugin_name = cmd.python
|
||||||
|
# print ("LOAD MODULE", plugin_name)
|
||||||
|
|
||||||
|
# this expect a callable, function or class
|
||||||
|
try:
|
||||||
|
mod = import_module(plugin_name)
|
||||||
|
except ModuleNotFoundError as err:
|
||||||
|
msg = f"Impossible to load module: {plugin_name}"
|
||||||
|
raise IamException(msg)
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
cmd_name = cmd.name.replace(" ", "_")
|
||||||
|
|
||||||
|
# pprint (mod)
|
||||||
|
# print ("locals")
|
||||||
|
# pprint (locals())
|
||||||
|
|
||||||
|
# print ("RUN PLUGIN")
|
||||||
|
mod(
|
||||||
|
cmd_name=cmd_name,
|
||||||
|
env=new_env,
|
||||||
|
vars=ctx_vars,
|
||||||
|
args=args,
|
||||||
|
ctx=self.context,
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise Exception("MIssing cmd or shell in config !")
|
raise Exception("MIssing cmd or shell in config !")
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import io
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
@ -45,7 +46,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
|
||||||
@ -90,7 +91,8 @@ list_view = ViewList(output=console.print)
|
|||||||
APP_NAME = "iam"
|
APP_NAME = "iam"
|
||||||
APP_VERSION = "__version__TOFIX"
|
APP_VERSION = "__version__TOFIX"
|
||||||
APP_EXCEPTION = error.IamException
|
APP_EXCEPTION = error.IamException
|
||||||
|
APP_TTY = os.isatty(0)
|
||||||
|
APP_COLORS = APP_TTY or APP_RICH
|
||||||
|
|
||||||
# See: https://docs.python.org/3.8/library/logging.html#logging-levels
|
# See: https://docs.python.org/3.8/library/logging.html#logging-levels
|
||||||
DEFAULT_LOG_LEVEL = 30 # warning
|
DEFAULT_LOG_LEVEL = 30 # warning
|
||||||
@ -129,16 +131,37 @@ def global_options(function):
|
|||||||
# is_flag=True, show_default=False, default=False,
|
# is_flag=True, show_default=False, default=False,
|
||||||
# help="Force"
|
# help="Force"
|
||||||
# )(function)
|
# )(function)
|
||||||
# function = click.option(
|
|
||||||
# "interactive", "--interactive", "-i"
|
function = click.option(
|
||||||
# is_flag=True, show_default=False, default=False,
|
"interactive",
|
||||||
# help="Interactive mode"
|
"--interactive/--no-interactive",
|
||||||
# )(function)
|
"-I",
|
||||||
|
is_flag=True,
|
||||||
|
show_default=APP_TTY,
|
||||||
|
default=APP_TTY,
|
||||||
|
help="Interactive mode",
|
||||||
|
)(function)
|
||||||
|
|
||||||
|
function = click.option(
|
||||||
|
"colors",
|
||||||
|
"--colors/--no-colors",
|
||||||
|
"-C",
|
||||||
|
is_flag=True,
|
||||||
|
show_default=APP_COLORS,
|
||||||
|
default=APP_COLORS,
|
||||||
|
help="Enable colors",
|
||||||
|
)(function)
|
||||||
|
|
||||||
# function = click.option(
|
# function = click.option(
|
||||||
# "recursive", "--recursive", "-r"
|
# "recursive", "--recursive", "-r"
|
||||||
# is_flag=True, show_default=False, default=False,
|
# is_flag=True, show_default=False, default=False,
|
||||||
# help="Recursive mode"
|
# help="Recursive mode"
|
||||||
# )(function)
|
# )(function)
|
||||||
|
# function = click.option(
|
||||||
|
# 'dry_run', '-n', '--dry-run',
|
||||||
|
# is_flag=True, show_default=False, default=False,
|
||||||
|
# help="Dry run, do not take any actions."
|
||||||
|
# )(function)
|
||||||
|
|
||||||
function = click.option(
|
function = click.option(
|
||||||
"quiet",
|
"quiet",
|
||||||
@ -171,12 +194,6 @@ def global_options(function):
|
|||||||
|
|
||||||
|
|
||||||
def format_options(function):
|
def format_options(function):
|
||||||
# function = click.option(
|
|
||||||
# 'dry_run', '-n', '--dry-run',
|
|
||||||
# is_flag=True, show_default=False, default=False,
|
|
||||||
# help="Dry run, do not take any actions."
|
|
||||||
# )(function)
|
|
||||||
|
|
||||||
# Duplicates
|
# Duplicates
|
||||||
function = click.option(
|
function = click.option(
|
||||||
"-v",
|
"-v",
|
||||||
@ -243,6 +260,8 @@ def cli_app(
|
|||||||
config: str = DEFAULT_IDENT,
|
config: str = DEFAULT_IDENT,
|
||||||
ident: str = DEFAULT_IDENT,
|
ident: str = DEFAULT_IDENT,
|
||||||
quiet=False,
|
quiet=False,
|
||||||
|
interactive=False,
|
||||||
|
colors=False,
|
||||||
log_trace=False,
|
log_trace=False,
|
||||||
fmt_fields=None,
|
fmt_fields=None,
|
||||||
fmt_sort=None,
|
fmt_sort=None,
|
||||||
@ -255,6 +274,15 @@ def cli_app(
|
|||||||
is not all that interesting.
|
is not all that interesting.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Show trace on errors, more like the --trace flag
|
||||||
|
if log_trace:
|
||||||
|
global APP_EXCEPTION
|
||||||
|
APP_EXCEPTION = None
|
||||||
|
|
||||||
|
# Disable COLORS
|
||||||
|
global APP_COLORS
|
||||||
|
APP_COLORS = colors
|
||||||
|
|
||||||
# Calculate log level
|
# Calculate log level
|
||||||
log_level = DEFAULT_LOG_LEVEL - verbose * 10
|
log_level = DEFAULT_LOG_LEVEL - verbose * 10
|
||||||
log_level = log_level if log_level > 0 else 10
|
log_level = log_level if log_level > 0 else 10
|
||||||
@ -272,6 +300,8 @@ def cli_app(
|
|||||||
log_level=log_level,
|
log_level=log_level,
|
||||||
fmt_name=fmt_name or DEFAULT_FORMAT,
|
fmt_name=fmt_name or DEFAULT_FORMAT,
|
||||||
ident=ident,
|
ident=ident,
|
||||||
|
interactive=interactive,
|
||||||
|
quiet=quiet,
|
||||||
)
|
)
|
||||||
render_config = {
|
render_config = {
|
||||||
"fmt_name": cli_config.fmt_name,
|
"fmt_name": cli_config.fmt_name,
|
||||||
@ -288,7 +318,7 @@ def cli_app(
|
|||||||
# Instanciate app
|
# Instanciate app
|
||||||
logger.info(f"Current ident: {ident}")
|
logger.info(f"Current ident: {ident}")
|
||||||
ctx.obj = SimpleNamespace(
|
ctx.obj = SimpleNamespace(
|
||||||
app=App(config_path=config, ident=ident),
|
app=App(config_path=config, ident=ident, cli_context=cli_config),
|
||||||
cli=cli_config,
|
cli=cli_config,
|
||||||
render_item=render_item,
|
render_item=render_item,
|
||||||
render_list=render_list,
|
render_list=render_list,
|
||||||
@ -892,12 +922,13 @@ def cli_app_run(ctx, cmd_params):
|
|||||||
|
|
||||||
if show_list:
|
if show_list:
|
||||||
ret = app.catalog.services.list_cmds()
|
ret = app.catalog.services.list_cmds()
|
||||||
data = [[x.name, x.desc] for x in ret]
|
pprint(ret)
|
||||||
|
data = [[x.cmd.name, x.cmd.desc, x.svc.name] for x in ret]
|
||||||
|
|
||||||
# Render data
|
# Render data
|
||||||
ctx.obj.render_list(
|
ctx.obj.render_list(
|
||||||
data,
|
data,
|
||||||
["name", "desc"],
|
["name", "desc", "service"],
|
||||||
conf={
|
conf={
|
||||||
"table_title": f"Services commands",
|
"table_title": f"Services commands",
|
||||||
# "fmt_name": fmt_name,
|
# "fmt_name": fmt_name,
|
||||||
@ -969,11 +1000,18 @@ def run():
|
|||||||
clean_terminate(err)
|
clean_terminate(err)
|
||||||
|
|
||||||
# Developper catchall
|
# Developper catchall
|
||||||
raise Exception(err) from err
|
if APP_COLORS:
|
||||||
# logger.error(traceback.format_exc())
|
console.print_exception(show_locals=True)
|
||||||
# logger.critical("Uncatched error %s; this may be a bug!", err.__class__)
|
else:
|
||||||
# logger.critical("Exit 1 with bugs")
|
# raise Exception(err) from err
|
||||||
# sys.exit(1)
|
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
|
if APP_EXCEPTION:
|
||||||
|
logger.critical("Uncatched error %s; this may be a bug!", err.__class__)
|
||||||
|
logger.critical("Exit 1 with bugs")
|
||||||
|
else:
|
||||||
|
logger.critical("Exited with %s error: %s", err.__class__.__name__, err)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@ -2,6 +2,10 @@ class IamException(Exception):
|
|||||||
"Iam Exception"
|
"Iam Exception"
|
||||||
|
|
||||||
|
|
||||||
|
# Second level classes
|
||||||
|
# =====================
|
||||||
|
|
||||||
|
|
||||||
class UnresolvedResourceDependencies(IamException):
|
class UnresolvedResourceDependencies(IamException):
|
||||||
"Raised when resources dependency is unmet"
|
"Raised when resources dependency is unmet"
|
||||||
|
|
||||||
@ -20,3 +24,23 @@ class MissingConfigFiles(IamException):
|
|||||||
|
|
||||||
class UnknownServiceCommand(IamException):
|
class UnknownServiceCommand(IamException):
|
||||||
"Raised when a command is not matched against services"
|
"Raised when a command is not matched against services"
|
||||||
|
|
||||||
|
|
||||||
|
# Configuration errors
|
||||||
|
# =====================
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigurationError(IamException):
|
||||||
|
"Raised when a command is not matched against services"
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigDuplicateCmds(ConfigurationError):
|
||||||
|
"Raised when two service commands overlap. May be caused by plugins"
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigForbiddenPrefixCmds(ConfigurationError):
|
||||||
|
"Raised when a service is not correctly prefixed. May be caused by plugins"
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigUnknownPlugin(ConfigurationError):
|
||||||
|
"Raised when a plugin can't be found"
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import importlib
|
import importlib
|
||||||
|
import importlib.util
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
@ -72,6 +73,21 @@ def empty(item):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def duplicates(_list):
|
||||||
|
"""Check if given list contains duplicates"""
|
||||||
|
known = set()
|
||||||
|
dup = set()
|
||||||
|
for item in _list:
|
||||||
|
if item in known:
|
||||||
|
dup.add(item)
|
||||||
|
else:
|
||||||
|
known.add(item)
|
||||||
|
|
||||||
|
if len(dup) > 0:
|
||||||
|
return list(dup)
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def prune(items):
|
def prune(items):
|
||||||
"Prune empty lists, dicts and None values from list or dict"
|
"Prune empty lists, dicts and None values from list or dict"
|
||||||
|
|
||||||
@ -197,6 +213,16 @@ def to_hcl(data):
|
|||||||
# return tomllib.dumps(data)
|
# return tomllib.dumps(data)
|
||||||
|
|
||||||
|
|
||||||
|
def filter_existing_files(root_path, candidates):
|
||||||
|
"""Return only existing files"""
|
||||||
|
result = [
|
||||||
|
os.path.join(root_path, cand)
|
||||||
|
for cand in candidates
|
||||||
|
if os.path.isfile(os.path.join(root_path, cand))
|
||||||
|
]
|
||||||
|
return list(set(result))
|
||||||
|
|
||||||
|
|
||||||
def to_toml(data):
|
def to_toml(data):
|
||||||
"Render to toml"
|
"Render to toml"
|
||||||
pprint(data)
|
pprint(data)
|
||||||
@ -274,6 +300,18 @@ def get_pkg_dir(name):
|
|||||||
return os.path.dirname(mod.__file__)
|
return os.path.dirname(mod.__file__)
|
||||||
|
|
||||||
|
|
||||||
|
def import_module_file(package, path):
|
||||||
|
"Simple helper to load dynamically python modules"
|
||||||
|
|
||||||
|
spec = importlib.util.spec_from_file_location(package, path)
|
||||||
|
mod = importlib.util.module_from_spec(spec)
|
||||||
|
|
||||||
|
sys.modules[package] = mod
|
||||||
|
spec.loader.exec_module(mod)
|
||||||
|
|
||||||
|
return mod
|
||||||
|
|
||||||
|
|
||||||
def import_module_pkg(package):
|
def import_module_pkg(package):
|
||||||
"Simple helper to load dynamically python modules"
|
"Simple helper to load dynamically python modules"
|
||||||
return importlib.import_module(package)
|
return importlib.import_module(package)
|
||||||
|
|||||||
@ -1,7 +1,21 @@
|
|||||||
plugin_base = {
|
plugin_base = {
|
||||||
"resources_def": {
|
"resources_def": {
|
||||||
# Secrets
|
# Main
|
||||||
|
# -------------
|
||||||
"secret": {"desc": "Secret", "input": {"secret": None}},
|
"secret": {"desc": "Secret", "input": {"secret": None}},
|
||||||
|
"auth": {"desc": "Authentification"},
|
||||||
|
"account": {
|
||||||
|
"desc": "Account",
|
||||||
|
"input": {"password": None, "user": None},
|
||||||
|
},
|
||||||
|
"service": {"desc": "Session service"},
|
||||||
|
"scope": {"desc": "Scoped identity"},
|
||||||
|
# Bases
|
||||||
|
"service.id": {"desc": "Default ident service"},
|
||||||
|
"service.scope": {"desc": "Default scope service"},
|
||||||
|
# Other assets:
|
||||||
|
# -------------
|
||||||
|
# Secrets
|
||||||
"secret.env": {
|
"secret.env": {
|
||||||
"desc": "Environment secret" "vars",
|
"desc": "Environment secret" "vars",
|
||||||
"input": {"secret_env": None},
|
"input": {"secret_env": None},
|
||||||
@ -11,7 +25,6 @@ plugin_base = {
|
|||||||
"input": {"secret_file": None},
|
"input": {"secret_file": None},
|
||||||
},
|
},
|
||||||
# Auths
|
# Auths
|
||||||
"auth": {"desc": "Authentification"},
|
|
||||||
"auth.password": {"desc": "Password", "input": {"password": None}},
|
"auth.password": {"desc": "Password", "input": {"password": None}},
|
||||||
"auth.token": {
|
"auth.token": {
|
||||||
"desc": "Token",
|
"desc": "Token",
|
||||||
@ -22,20 +35,15 @@ plugin_base = {
|
|||||||
"input": {"token": None},
|
"input": {"token": None},
|
||||||
},
|
},
|
||||||
# Accounts
|
# Accounts
|
||||||
"account": {
|
|
||||||
"desc": "Account",
|
|
||||||
"input": {"password": None, "user": None},
|
|
||||||
},
|
|
||||||
"account.email": {"desc": "Email account", "input": {"email": None}},
|
"account.email": {"desc": "Email account", "input": {"email": None}},
|
||||||
# Services
|
|
||||||
"service": {"desc": "Session service"},
|
|
||||||
# ID
|
|
||||||
"service.id": {"desc": "Default ident service"},
|
|
||||||
},
|
},
|
||||||
"resources": {
|
"resources": {
|
||||||
"service.id": {
|
"service.id": {
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
},
|
},
|
||||||
|
"service.scope": {
|
||||||
|
"enabled": True,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"id": {
|
"id": {
|
||||||
@ -59,8 +67,29 @@ plugin_base = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"scope": {
|
||||||
|
"desc": "Local scope identity/sub identities",
|
||||||
|
"commands": {
|
||||||
|
"shell_enable": {
|
||||||
|
"desc": "Enable shell scope",
|
||||||
|
"shell": "export SHELL_SCOPE={{scope}}",
|
||||||
|
},
|
||||||
|
"shell_disable": {
|
||||||
|
"desc": "Disable shell scope",
|
||||||
|
"shell": "unset SHELL_SCOPE",
|
||||||
|
},
|
||||||
|
"scope new": {
|
||||||
|
"desc": "Create shell scope",
|
||||||
|
"shell": "add_scope {{ param }}",
|
||||||
|
},
|
||||||
|
"scope delete": {
|
||||||
|
"desc": "Delete shell scope",
|
||||||
|
"shell": "rm_scope {{ param }}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
all = {"base": plugin_base}
|
providers = {"base": plugin_base}
|
||||||
|
|||||||
@ -2,9 +2,9 @@ import os
|
|||||||
|
|
||||||
from iam.lib.utils import get_pkg_dir, open_yaml, to_yaml
|
from iam.lib.utils import get_pkg_dir, open_yaml, to_yaml
|
||||||
|
|
||||||
all = None
|
providers = None
|
||||||
yml_dir = get_pkg_dir(__name__)
|
yml_dir = get_pkg_dir(__name__)
|
||||||
conf_files = open_yaml(os.path.join(yml_dir, "devops.yml"))
|
conf_files = open_yaml(os.path.join(yml_dir, "devops.yml"))
|
||||||
for conf in conf_files:
|
for conf in conf_files:
|
||||||
all = conf.get("providers", {})
|
providers = conf.get("providers", {})
|
||||||
break
|
break
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
import os
|
|
||||||
from pprint import pprint
|
|
||||||
|
|
||||||
from iam.lib.utils import get_pkg_dir, open_yaml, to_yaml
|
|
||||||
|
|
||||||
yml_dir = get_pkg_dir(__name__)
|
|
||||||
plugin_conf = open_yaml(os.path.join(yml_dir, "local.yml"))[0]
|
|
||||||
|
|
||||||
|
|
||||||
all = plugin_conf.get("providers", {})
|
|
||||||
@ -1,404 +0,0 @@
|
|||||||
|
|
||||||
providers:
|
|
||||||
|
|
||||||
# Provider: SSH
|
|
||||||
# ==================
|
|
||||||
ssh:
|
|
||||||
|
|
||||||
services:
|
|
||||||
local.ssh_key:
|
|
||||||
desc: Local ssh key
|
|
||||||
inputs:
|
|
||||||
ssh_key_secret: ""
|
|
||||||
ssh_key_alg: "ed25519"
|
|
||||||
|
|
||||||
commands:
|
|
||||||
|
|
||||||
ssh new:
|
|
||||||
desc: Create new SSH key
|
|
||||||
|
|
||||||
|
|
||||||
# shell: |
|
|
||||||
# echo "This is my shelll !!! $SHELL"
|
|
||||||
# env | grep jez
|
|
||||||
|
|
||||||
# cmd: |
|
|
||||||
# env
|
|
||||||
# # echo Create ssh key: {{ssh_key_alg}} for ident '{{ident}}' with pass: {{ssh_key_secret}}
|
|
||||||
|
|
||||||
shell: |
|
|
||||||
# env | sort
|
|
||||||
# echo
|
|
||||||
|
|
||||||
|
|
||||||
SSH_KEY_ALG={{ssh_key_alg}}
|
|
||||||
|
|
||||||
SSH_KEY_VERSION="$(date +'%Y%m%d')"
|
|
||||||
SSH_KEY_HOST="$(hostname -f)"
|
|
||||||
|
|
||||||
SSH_KEY_FILE=$HOME/.ssh/{{ident}}/{{user}}_${SSH_KEY_ALG}_${SSH_KEY_VERSION}
|
|
||||||
SSH_KEY_COMMENT={{user}}@${SSH_KEY_HOST}:${SSH_KEY_ALG}_${SSH_KEY_VERSION}
|
|
||||||
|
|
||||||
echo mkdir -p $HOME/.ssh/{{ident}}/
|
|
||||||
echo ssh-keygen -f "${SSH_KEY_FILE}" \
|
|
||||||
-t ed25519 -a 100 \
|
|
||||||
{% if ssh_key_secret %}-N "{{ssh_key_secret}}"{%endif%} \
|
|
||||||
-C "$SSH_KEY_COMMENT"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ssh delete:
|
|
||||||
desc: Delete existing SSH key
|
|
||||||
cmd: |
|
|
||||||
find $HOME/.ssh/{{ident}}/ -name "{{user}}_*"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
resources_def:
|
|
||||||
|
|
||||||
|
|
||||||
auth.ssh_certificate:
|
|
||||||
desc: SSH Certificates
|
|
||||||
input:
|
|
||||||
ssh_cert_file: null
|
|
||||||
needs:
|
|
||||||
- auth.ssh_key
|
|
||||||
|
|
||||||
auth.ssh_key:
|
|
||||||
desc: SSH Keypair
|
|
||||||
input:
|
|
||||||
ssh_key_file: null
|
|
||||||
ssh_key_secret: null
|
|
||||||
needs:
|
|
||||||
- kind: auth.password
|
|
||||||
remap:
|
|
||||||
ssh_key_secret: passord
|
|
||||||
|
|
||||||
account.ssh:
|
|
||||||
desc: Unix account
|
|
||||||
input:
|
|
||||||
host: null
|
|
||||||
|
|
||||||
|
|
||||||
# service.local.ssh_key:
|
|
||||||
# desc: A local ssh key
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# resources:
|
|
||||||
|
|
||||||
# service.local.ssh_agent:
|
|
||||||
# enabled: true
|
|
||||||
|
|
||||||
# service.local.ssh_agent_keys:
|
|
||||||
# enabled: true
|
|
||||||
# loop:
|
|
||||||
# - auth.ssh_key:{ident}/ed25519
|
|
||||||
# - auth.ssh_key:{ident}/rsa4096
|
|
||||||
# - auth.ssh_key:{ident}/rsa2048
|
|
||||||
# - auth.ssh_key:{ident}/rsa1024
|
|
||||||
# - auth.ssh_key:{ident}
|
|
||||||
# loop_limit: 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Provider: GPG Agent
|
|
||||||
# ==================
|
|
||||||
gpg_agent:
|
|
||||||
|
|
||||||
|
|
||||||
resources_def:
|
|
||||||
|
|
||||||
auth.gpg_key:
|
|
||||||
desc: GPG keypair
|
|
||||||
input:
|
|
||||||
gpg_key_file: null
|
|
||||||
gpg_key_secret: null
|
|
||||||
needs:
|
|
||||||
- kind: auth.password
|
|
||||||
remap:
|
|
||||||
gpg_key_secret: passord
|
|
||||||
|
|
||||||
|
|
||||||
# Provider: SSH Agent
|
|
||||||
# ==================
|
|
||||||
ssh_agent:
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
local.ssh_agent:
|
|
||||||
desc: Local ssh-agent
|
|
||||||
input:
|
|
||||||
ssh_agent_socket_dir: /run/user/ssh-agent
|
|
||||||
ssh_agent_tmout: 7d
|
|
||||||
|
|
||||||
commands:
|
|
||||||
|
|
||||||
shell_start:
|
|
||||||
desc: Start ssh-agent
|
|
||||||
shell: |
|
|
||||||
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:
|
|
||||||
desc: Enable ssh-agent
|
|
||||||
|
|
||||||
shell: |
|
|
||||||
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
|
|
||||||
|
|
||||||
unset socket
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
shell_disable:
|
|
||||||
desc: Disable ssh-agent
|
|
||||||
shell: |
|
|
||||||
unset SSH_AUTH_SOCK SSH_AGENT_PID
|
|
||||||
|
|
||||||
|
|
||||||
shell_stop:
|
|
||||||
desc: Kill ssh-agent
|
|
||||||
shell: |
|
|
||||||
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:
|
|
||||||
desc: Local ssh-agent keys
|
|
||||||
|
|
||||||
commands:
|
|
||||||
ssh add:
|
|
||||||
desc: Unload keys into ssh-agent
|
|
||||||
shell: ssh-agent -d {ssh_key_file}
|
|
||||||
|
|
||||||
ssh rm:
|
|
||||||
desc: Load keys into ssh-agent
|
|
||||||
shell: |
|
|
||||||
ssh-add {% for item in loop %} {{item.ssh_key_file}} {% endfor %}
|
|
||||||
|
|
||||||
|
|
||||||
required_services:
|
|
||||||
- local.ssh_agent
|
|
||||||
|
|
||||||
|
|
||||||
resources_def:
|
|
||||||
|
|
||||||
service.local.ssh_agent:
|
|
||||||
desc: Configure ssh-agent daemon
|
|
||||||
|
|
||||||
service.local.ssh_agent_keys:
|
|
||||||
desc: Configure ssh-agent keys autoloader
|
|
||||||
|
|
||||||
|
|
||||||
resources:
|
|
||||||
|
|
||||||
service.local.ssh_agent:
|
|
||||||
enabled: true
|
|
||||||
|
|
||||||
service.local.ssh_agent_keys:
|
|
||||||
enabled: true
|
|
||||||
loop:
|
|
||||||
- auth.ssh_key:{ident}/ed25519
|
|
||||||
- auth.ssh_key:{ident}/rsa4096
|
|
||||||
- auth.ssh_key:{ident}/rsa2048
|
|
||||||
- auth.ssh_key:{ident}/rsa1024
|
|
||||||
- auth.ssh_key:{ident}
|
|
||||||
loop_limit: 3
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Provider: Git Config
|
|
||||||
# ==================
|
|
||||||
git:
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
local.git:
|
|
||||||
desc: Git identity
|
|
||||||
# input:
|
|
||||||
# ssh_agent_socket_dir: /run/user/ssh-agent
|
|
||||||
# ssh_agent_tmout: 7d
|
|
||||||
|
|
||||||
commands:
|
|
||||||
|
|
||||||
shell_enable:
|
|
||||||
desc: Enable git identity
|
|
||||||
shell: |
|
|
||||||
export GIT_AUTHOR_NAME='{{ident}}'
|
|
||||||
export GIT_AUTHOR_EMAIL='{{email}}'
|
|
||||||
export GIT_COMMITTER_NAME='{{ident}}'
|
|
||||||
export GIT_COMMITTER_EMAIL='{{email}}'
|
|
||||||
|
|
||||||
|
|
||||||
shell_disable:
|
|
||||||
desc: Disable git identity
|
|
||||||
shell: |
|
|
||||||
unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
|
|
||||||
|
|
||||||
|
|
||||||
local.git_home:
|
|
||||||
desc: Home as git repo
|
|
||||||
input:
|
|
||||||
git_dir: "$HOME"
|
|
||||||
git_work_tree: $HOME/.local/share/home_git
|
|
||||||
|
|
||||||
commands:
|
|
||||||
|
|
||||||
shell_enable:
|
|
||||||
desc: Enable git home management
|
|
||||||
shell: |
|
|
||||||
export GIT_DIR="{{git_dir}}"
|
|
||||||
export GIT_WORK_TREE="{{git_work_tree}}/{{ ident }}"
|
|
||||||
|
|
||||||
shell_disable:
|
|
||||||
desc: Disable git home management
|
|
||||||
shell: |
|
|
||||||
unset GIT_DIR GIT_WORK_TREE
|
|
||||||
|
|
||||||
required_services:
|
|
||||||
- local.git
|
|
||||||
|
|
||||||
resources_def:
|
|
||||||
|
|
||||||
service.local.git:
|
|
||||||
desc: Configure git
|
|
||||||
|
|
||||||
service.local.git_home:
|
|
||||||
desc: Configure home as git repo
|
|
||||||
|
|
||||||
resources:
|
|
||||||
|
|
||||||
service.local.git:
|
|
||||||
enabled: true
|
|
||||||
uses:
|
|
||||||
- account:{user}
|
|
||||||
|
|
||||||
# Disabled by default
|
|
||||||
service.local.git_home:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Provider: PS1 Config
|
|
||||||
# ==================
|
|
||||||
ps1:
|
|
||||||
|
|
||||||
services:
|
|
||||||
|
|
||||||
local.ps1:
|
|
||||||
desc: PS1 prompt
|
|
||||||
input:
|
|
||||||
enabled: True
|
|
||||||
|
|
||||||
commands:
|
|
||||||
|
|
||||||
shell_enable:
|
|
||||||
desc: Enable PS1
|
|
||||||
shell: |
|
|
||||||
export OLD_PS1=$PS1
|
|
||||||
export PS1="\033[0;34m\]({{ident}})\033[00m\] ${PS1}"
|
|
||||||
|
|
||||||
shell_disable:
|
|
||||||
desc: Disable PS1
|
|
||||||
shell: |
|
|
||||||
export PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
|
|
||||||
# export PS1="$OLD_PS1"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
resources_def:
|
|
||||||
service.local.ps1:
|
|
||||||
desc: PS1 prompt
|
|
||||||
|
|
||||||
|
|
||||||
resources:
|
|
||||||
|
|
||||||
service.local.ps1:
|
|
||||||
desc: Custom Ident PS1
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# EXISTING
|
|
||||||
|
|
||||||
# WARN__: Your workspace is already activated
|
|
||||||
# NOTICE: Enabling id ...
|
|
||||||
# export SHELL_ID='mrjk'
|
|
||||||
# export GIT_AUTHOR_NAME='mrjk'
|
|
||||||
# export GIT_AUTHOR_EMAIL='mrjk.78@gmail.com'
|
|
||||||
# export GIT_COMMITTER_NAME='mrjk'
|
|
||||||
# export GIT_COMMITTER_EMAIL='mrjk.78@gmail.com'
|
|
||||||
|
|
||||||
# NOTICE: Enabling gpg ...
|
|
||||||
# export GNUPGHOME=/home/jez/.config/gpg/mrjk
|
|
||||||
# export GPG_AGENT_INFO=/run/user/1000/pgp-agent/mrjk/socket
|
|
||||||
# export GPG_DEFAULT_ID=mrjk
|
|
||||||
# export GPG_TTY=/dev/pts/48
|
|
||||||
# export GNUPGHOME=/home/jez/.config/gpg/mrjk
|
|
||||||
|
|
||||||
# NOTICE: Enabling ssh ...
|
|
||||||
# export SSH_AUTH_SOCK=/run/user/1000/ssh-agent/mrjk/socket
|
|
||||||
|
|
||||||
# NOTICE: Enabling gh ...
|
|
||||||
# export GH_TOKEN="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"
|
|
||||||
# export GH_REPO="mrjk"
|
|
||||||
|
|
||||||
# NOTICE: Enabling gitea ...
|
|
||||||
# export GITEA_SERVER_URL="ad808bc88fa37bce5e3bb963f1420aa575194d30"
|
|
||||||
# export GITEA_LOGIN="mrjk@git.jeznet.org"
|
|
||||||
|
|
||||||
# NOTICE: Enabling ps1 ...
|
|
||||||
# export PS1="\[\](mrjk)\[\] ${IDM_SHELL_PS1}"
|
|
||||||
|
|
||||||
# NOTICE: Identity 'mrjk' is loaded
|
|
||||||
Loading…
x
Reference in New Issue
Block a user