112 lines
3.5 KiB
Python
112 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
|
import getpass
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
import click
|
|
|
|
from lib.config import DEFAULT_CONFIG, load_yaml, get_profile_dir
|
|
from lib.functions import deep_update
|
|
from lib.run import compose_exec, run
|
|
from lib.profiles import profile_exists, ensure_profile, set_state
|
|
from lib.profiles import apply_settings, copy_seed
|
|
|
|
|
|
def merged_profile(cfg, name):
|
|
profile = cfg["profiles"][name]
|
|
template_name = profile.get("template")
|
|
template = cfg.get("templates", {}).get(template_name, {}) if template_name else {}
|
|
|
|
merged = dict(template)
|
|
merged = deep_update(merged, profile)
|
|
merged["name"] = name
|
|
return merged
|
|
|
|
|
|
@click.group()
|
|
@click.option("--config", "config_path", default=DEFAULT_CONFIG, show_default=True)
|
|
@click.pass_context
|
|
def cli(ctx, config_path):
|
|
ctx.obj = {
|
|
"config_path": config_path,
|
|
"config": load_yaml(config_path),
|
|
}
|
|
|
|
|
|
@cli.command()
|
|
@click.pass_context
|
|
def reconcile(ctx):
|
|
"""Create missing profiles and apply desired state."""
|
|
cfg = ctx.obj["config"]
|
|
|
|
for name in cfg.get("profiles", {}):
|
|
profile = merged_profile(cfg, name)
|
|
container = profile["container"]
|
|
description = profile.get("description")
|
|
|
|
click.echo(f"\n==> Reconciling {name} in {container}")
|
|
existed_before = profile_exists(container, name)
|
|
|
|
ensure_profile(container, name, description)
|
|
|
|
if not existed_before:
|
|
# Set profile dir as write-able by current user
|
|
profile_path = str(get_profile_dir(container, name).parent.parent)
|
|
user = getpass.getuser()
|
|
cmd = ["sudo", "setfacl", "-R", "-m", f"u:{user}:rwx",
|
|
"-m", f"d:u:{user}:rwx", profile_path]
|
|
run(cmd, capture=False)
|
|
# If a seed directory is set, use its files as default
|
|
if profile.get("seed"):
|
|
copy_seed(container, name, profile["seed"])
|
|
# Apply settings from hermes-profiles file
|
|
apply_settings(container, name, profile)
|
|
set_state(container, name, profile.get("state", "existing"))
|
|
|
|
|
|
@cli.command()
|
|
@click.argument("name")
|
|
@click.pass_context
|
|
def start(ctx, name):
|
|
"""Start one configured profile."""
|
|
profile = merged_profile(ctx.obj["config"], name)
|
|
compose_exec(profile["container"], "hermes", "-p", name, "gateway", "start")
|
|
|
|
|
|
@cli.command()
|
|
@click.argument("name")
|
|
@click.pass_context
|
|
def stop(ctx, name):
|
|
"""Stop one configured profile."""
|
|
profile = merged_profile(ctx.obj["config"], name)
|
|
compose_exec(profile["container"], "hermes", "-p", name, "gateway", "stop")
|
|
|
|
|
|
@cli.command()
|
|
@click.argument("name")
|
|
@click.pass_context
|
|
def restart(ctx, name):
|
|
"""Restart one configured profile."""
|
|
profile = merged_profile(ctx.obj["config"], name)
|
|
compose_exec(profile["container"], "hermes", "-p", name, "gateway", "restart")
|
|
|
|
|
|
@cli.command()
|
|
@click.pass_context
|
|
def list(ctx):
|
|
"""List configured profiles."""
|
|
cfg = ctx.obj["config"]
|
|
padding = max([len(x) for x in cfg.get("profiles", {})])
|
|
for name in cfg.get("profiles", {}):
|
|
profile = merged_profile(cfg, name)
|
|
state = profile.get('state', 'existing')
|
|
if state == "running": state = click.style(state, fg='green')
|
|
elif state == "stopped": state = click.style(state, fg='red')
|
|
click.echo(f"{name.ljust(padding)}\t{profile['container']}\t{state}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
cli()
|