Source code for fastiot.cli.commands.deploy

""" Command for automatic deployments using ansible playbooks """
import logging
import os
from typing import Optional, List

import jinja2
import typer

from fastiot.cli.constants import DEPLOYMENTS_CONFIG_DIR
from fastiot.cli.helper_fn import get_jinja_env
from fastiot.cli.model.project import ProjectContext
from fastiot.cli.typer_app import DEFAULT_CONTEXT_SETTINGS, app


def _deployment_completion(*_) -> List[str]:
    return ProjectContext.default.deployment_names


[docs]@app.command(context_settings=DEFAULT_CONTEXT_SETTINGS) def deploy(deployments: Optional[List[str]] = typer.Argument(default=None, shell_complete=_deployment_completion, help="Select the deployments to deploy"), ask_pass: bool = typer.Option(False, '--ask-pass', '-k', help="Use password instead of SSH publickey to connect to targets"), dry: bool = typer.Option(False, help="Only create playbooks but do not run actual deployment.")): """ This command handles deployment of a config using an Ansible Playbook if you have configured any deployments based on :class:`fastiot.cli.model.deployment.DeploymentTargetSetup` in your :file:`deployment.yaml`. """ context = ProjectContext.default if not deployments: deployments = [] for deployment_name in deployments: if deployment_name not in context.deployment_names: typer.echo(f"Deployment {deployment_name} not in project deployments.") raise typer.Exit(code=1) for deployment_name in deployments: deployment = context.deployment_by_name(deployment_name) if deployment.deployment_target is None: typer.echo(f"Deployment {deployment_name} does not have a deployment_target configured.") raise typer.Exit(code=2) _write_ansible_playbook(deployment_name, deployment) if not dry: ask_pass = "-k" if ask_pass else "" os.system(f"cd {context.build_dir}/{DEPLOYMENTS_CONFIG_DIR}/{deployment_name};" f"ansible-playbook {ask_pass} -i hosts --diff ansible-playbook.yaml")
def _write_ansible_playbook(deployment_name, deployment): """ Creates the actual playbook and inventory files""" context = ProjectContext.default output_dir = os.path.join(context.project_root_dir, context.build_dir, DEPLOYMENTS_CONFIG_DIR, deployment_name) os.makedirs(output_dir, exist_ok=True) try: jinja_env = get_jinja_env() playbook_template = jinja_env.get_template('ansible-playbook.yaml.j2') playbook_document = playbook_template.render(deployment_name=deployment_name, deployment_target=deployment.deployment_target) with open(os.path.join(output_dir, "ansible-playbook.yaml"), "w") as playbook_file: playbook_file.write(playbook_document) jinja_env = get_jinja_env() inventory_template = jinja_env.get_template('ansible_hosts.j2') inventory_document = inventory_template.render(deployment_target=deployment.deployment_target) with open(os.path.join(output_dir, "hosts"), "w") as inventory_file: inventory_file.write(inventory_document) except jinja2.exceptions.UndefinedError: logging.exception('Exception raised during transpiling of playbook %s', deployment_name)