diff --git a/README.md b/README.md index 6c270b8..b2fe685 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,10 @@ For each app/recipe the following `` can be used: - it matches against parts of the line (i.E. `compose.smtp.yml`) - this is useful for env variables that are used multiple times like `COMPOSE_FILE` - **`env`**: Sets values for environment variables. -- **`execute`**: Specifies `abra.sh` commands to run post-deployment. +- **`*-hooks`**: Specifies `abra.sh` commands to run at specific stages. + - **`*initial-hooks`**: commands for initialisation + - **`*deploy-hooks`**: commands that should be run after each deployment + - **`*upgrade-hooks`**: commands that should be run after each upgrade - **`secrets`**: Inserts specific values (i.E. smtp passwords) into secrets; future updates will support encrypted file usage. - **`subdomain`**: Specifies the subdomain scheme for individual recipes and apps. (not available in `combine.yml`/`alaconnect.yml`) - i.e. `cloud.example.com` for nextcloud diff --git a/alakazam.py b/alakazam.py index aa84530..b7139ea 100755 --- a/alakazam.py +++ b/alakazam.py @@ -717,46 +717,39 @@ def replace_domains(path: Path, old_domain: str, new_domain: str) -> None: file.write(content) -def list_commands(app_config: Dict[str, Any]) -> None: - """ - Lists all post-deployment commands for an app based on the app configuration. - This can help in verifying which commands are set to run after deployment. - - Args: - app_config (dict): Configuration for the app which may include post-deployment commands. - - Returns: - None: Outputs the list of commands to standard output. - """ - domain = app_config['app_domain'] - if not (all_cmds:= app_config.get('execute')): - logging.info(f"No post deploy cmds for {domain}") - return - for cmd in all_cmds: - container = cmd.split()[0] - cmd = cmd.split()[1:] - print(f"{domain}:{container} --> '{cmd}'") - - -def execute_cmds(app_config: Dict[str, Any]) -> None: +def execute_cmds(app_config: Dict[str, Any], commands: Tuple[str] = tuple(), initial: bool = False, deploy: bool = False, upgrade: bool = False, dry_run: bool = False) -> None: """ Execute post-deployment commands for an application based on the provided configuration. This can include running scripts or commands inside the application's environment. Args: app_config (dict): A dictionary containing the deployment configuration and commands for an application. + commands (list): A list of commands that should be executed in the following format: + ' ' + initial (bool): execute initial-hooks + deploy (bool): execute deploy-hooks + upgrade (bool): execute upgrade-hooks + dry-run(bool): only show cmds, don't execute them Returns: None """ domain = app_config['app_domain'] - if not (all_cmds:= app_config.get('execute')): - logging.info(f"No post deploy cmds for {domain}") - return + all_cmds = [] + if initial and (initial_hooks:= app_config.get('initial-hooks')): + all_cmds = all_cmds + initial_hooks + if deploy and (deploy_hooks:= app_config.get('deploy-hooks')): + all_cmds = all_cmds + deploy_hooks + if upgrade and (upgrade_hooks:= app_config.get('upgrade-hooks')): + all_cmds = all_cmds + upgrade_hooks + if commands: + all_cmds = all_cmds + list(commands) for cmd in all_cmds: container = cmd.split()[0] cmd = cmd.split()[1:] print(f"Run '{cmd}' in {domain}:{container}") + if dry_run: + continue if container == "local": print(abra("app", "cmd", "--local", domain, *cmd, ignore_error=True)) else: @@ -944,7 +937,7 @@ def deploy(apps: Tuple[str], run_cmds: bool, force: bool, converge_checks: bool) print(abra("app", *cmd)) if run_cmds: logging.info(f'execute commands for {domain}') - execute_cmds(app_config) + execute_cmds(app_config, deploy=True) @cli.command() @@ -1008,8 +1001,8 @@ def upgrade(apps: Tuple[str], run_cmds: bool, dry_run: bool) -> None: for app_config, cmd in upgrade_cmds: print(abra("app", *cmd)) if run_cmds: - execute_cmds(app_config) logging.info(f'execute commands for {app_config.get("subdomain")}') + execute_cmds(app_config, upgrade=True) @cli.command() @@ -1042,16 +1035,15 @@ def undeploy(apps: Tuple[str]) -> None: @cli.command() -@click.option('-a', '--apps', multiple=True) -def cmds(apps: List[str]) -> None: +@click.option('-a', '--apps', metavar='', multiple=True, help='The applications, which post-deployment commands should be executed.') +@click.option('commands', '-c', '--command', multiple=True, metavar="' '", help='commands that should be executed') +@click.option('-i', '--initial', is_flag=True, help='execute initial-hooks from config') +@click.option('-d', '--deploy', is_flag=True, help='execute deploy-hooks from config') +@click.option('-u', '--upgrade', is_flag=True, help='execute upgrade-hooks from config') +@click.option('-l', '--list-cmds', is_flag=True, help="only show cmds, don't execute them") +def cmd(apps: Tuple[str], commands: Tuple[str], initial: bool, deploy: bool, upgrade: bool, list_cmds: bool = False) -> None: """ - Execute post-deployment commands for all specified applications based on the provided configuration. - - Args: - apps (list): A list containing the applications, which post-deployment commands should be executed. - - Returns: - None + Execute commands for all specified applications based on the provided configuration. """ deployed_domains = get_deployed_apps(apps) for _, instance_config in INSTANCE_CONFIGS.items(): @@ -1066,26 +1058,7 @@ def cmds(apps: List[str]) -> None: print(f"{domain} is not deployed") continue logging.info(f'execute commands for {domain}') - execute_cmds(app_config) - -@cli.command() -@click.option('-a', '--apps', multiple=True) -def list_cmds(apps: List[str]) -> None: - """ - Lists all post-deployment commands for specified applications. - This function helps in reviewing which commands would run after the deployment of the specified apps. - - Args: - apps (list): List of application names to list post-deployment commands for. - """ - for _, instance_config in INSTANCE_CONFIGS.items(): - if apps: - selected_apps = [app for app in apps if app in instance_config.keys()] - else: - selected_apps = instance_config.keys() - for app in selected_apps: - app_config = instance_config[app] - list_commands(app_config) + execute_cmds(app_config, commands, initial, deploy, upgrade, list_cmds) @cli.command() diff --git a/combine.yml b/combine.yml index 3a5ffc3..0667925 100644 --- a/combine.yml +++ b/combine.yml @@ -97,7 +97,7 @@ nextcloud: - AUTHENTIK_DOMAIN - SECRET_AUTHENTIK_SECRET_VERSION - SECRET_AUTHENTIK_ID_VERSION - execute: + initial-hooks: - app set_authentik shared_secrets: nextcloud_secret: authentik_secret @@ -107,12 +107,12 @@ nextcloud: - compose.onlyoffice.yml - ONLYOFFICE_URL - SECRET_ONLYOFFICE_JWT_VERSION - execute: + initial-hooks: - app install_onlyoffice collabora: uncomment: - COLLABORA_URL - execute: + initial-hooks: - app install_collabora onlyoffice: nextcloud: @@ -145,7 +145,7 @@ wordpress: - SECRET_AUTHENTIK_SECRET_VERSION - SECRET_AUTHENTIK_ID_VERSION - LOGIN_TYPE - execute: + initial-hooks: - app set_authentik shared_secrets: wordpress_secret: authentik_secret diff --git a/examples/alaka-defaults.yml b/examples/alaka-defaults.yml index c40251d..9738925 100644 --- a/examples/alaka-defaults.yml +++ b/examples/alaka-defaults.yml @@ -12,7 +12,7 @@ authentik: uncomment: - calendar.svg - bbb.jpg - execute: + initial-hooks: - worker set_admin_pass - worker apply_blueprints - worker add_applications @@ -27,7 +27,7 @@ nextcloud: - SECRET_BBB_SECRET_VERSION secrets: bbb_secret: "{{bbb_secret}}" - execute: + initial-hooks: - app install_bbb - app set_default_quota - app install_apps @@ -38,7 +38,7 @@ wordpress: DEFAULT_USER_ROLE: administrator uncomment: - EXTRA_DOMAINS - execute: + initial-hooks: - app core_install matrix-synapse: env: