<commit_before>"""
Appflow Tools.
This contains all the functions needed to perform actions connected to
initialization, config deployment and git versioning.
"""
import json
import os
import shutil
import subprocess

import yaml

import lib.appflow_ansible as apansible
import lib.appflow_utils as utils
import lib.appflow_yaml as apyaml


def initialize(tenant, env):
    """
    Create default dirs, clone playbooks and yaml files for Assh to function properly.

    :type  tenant: string
    :param tenant: The name of the tenant. (ex: mrrobot)

    :type  env: string
    :param env: The name of the tenant.


    :rtype:   None
    :return:  This function doesn't have a return statement.
    """

    # We use this to distinguish if tenant+env is specified
    # if not, we should ask them!
    if tenant is None or env is None:
        tenant = input("What's the tenant name? ")
        choice = int(input("""
        Choose your default environment
        1) Development
        2) Staging
        3) Production
        """))
        if choice < 1 or choice > 3:
            print('Invalid option')
            return

        environmens = ['development', 'staging', 'production']
        env = environmens[choice - 1]

    dirs = ['/.ssh', '/.ssh/assh.d/' + tenant, '/tmp/.ssh/cm', '/.appflow',
            '/.appflow/tenant', '/.appflow/vault']

    # Mkdir -p of needed folders.
    for directory in dirs:
        os.makedirs(os.getenv('HOME') + directory, exist_ok=True)

    # Setup default configs
    setup_default_config(tenant, env)

    # Initialize a default assh.yml config
    conf = {'defaults': {'ControlMaster': 'auto',
                         'ControlPath': '~/tmp/.ssh/cm/%h-%p-%r.sock',
                         'ControlPersist': True,
                         'ForwardAgent': True},
            'includes': ['~/.ssh/assh.d/*/*.yml',
                         '~/.ssh/assh_personal.yml']}
    file_name = os.getenv('HOME') + "/.ssh/assh.yml"
    # Write it to file.
    with open(file_name, 'w') as outfile:
        yaml.dump(conf, outfile, default_flow_style=False,
                  indent=4)

    # Clone appflow-playbooks.
    subprocess.Popen(['git', '-C', os.getenv('HOME') + '/.appflow',
                      'clone',
                      'https://github.com/ttssdev/appflow-playbooks',
                      'playbooks'],
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    print("Done")
    return


def setup_default_config(tenant, env):
    """
    Deploy a default config file in ~/.appflow/config.yml

    :type  tenant: string
    :param tenant: The name of the tenant. (ex: mrrobot)

    :type  env: string
    :param env: The name of the tenant.

    :rtype:   None
    :return:  the function prints to screen the ansible output of the execution.
    """
    file_name = os.getenv('HOME') + "/.appflow/config.yml"
    utils.safe_remove(file_name)
    conf = {'appflow': {'tenant': {'id': 'appflow-' + tenant,
                                   'name': tenant,
                                   'default_env': env}}}
    with open(file_name, 'w') as outfile:
        yaml.dump(conf, outfile, default_flow_style=False,
                  indent=4)


def set_vhosts_hosts(tenant):
    """
    Setup /etc/hosts for tenant.
    Requires root access to write.

    :type  tenant: string
    :param tenant: The name of the tenant.

    :rtype:   None
    :return:  the function doesn't have a return statement.
    """
    _dir = utils.get_tenant_dir(tenant)
    target_folder = _dir + "development"
    is_decrypted = False
    # Files are encrypted. Decrypt and save status to re-encrypt later.
    if utils.check_string_in_file(target_folder + "/inventory", 'AES256'):
        apansible.decrypt(tenant, "development")
        is_decrypted = True
    vhosts = apyaml.get_value(tenant + ".development.group_vars.all",
                              "conf_vhosts_common")
    vhosts = json.loads(vhosts)
    ip_list = apyaml.get_value(tenant + ".development.group_vars.all",
                               "conf_hosts")
    ip_list = json.loads(ip_list)

    # Open /etc/hosts file.
    # Put it in string list.
    file = open("/etc/hosts", 'r')
    current_hosts = [line.strip() for line in file]

    # Just add a separation line.
    os.system('echo "\n" | sudo tee -a /etc/hosts')

    new_hosts = []
    for _ip in ip_list:
        # Check if this line is already present
        if _ip not in "".join(current_hosts):
            # if not present add it!
            new_hosts.append(_ip)
    for host in vhosts:
        if vhosts.get(host)["state"] == "enabled":
            server_alias = vhosts.get(host)["servername"]
            for alias in vhosts.get(host)["serveralias"]:
                server_alias = server_alias + " " + alias
        for _ip in ip_list:
            # Assemble the line IP + servername + aliases
            _ip = _ip.split()[0] + " " + server_alias
            # Check if this line is already present
            if _ip not in "".join(current_hosts):
                # if not present add it!
                new_hosts.append(_ip)
    for host in new_hosts:
        # let's append to the file only the lines we need
        # we will need sudo in order to write in /etc/hosts
        os.system('echo ' + host + ' | sudo tee -a /etc/hosts')
    if is_decrypted is True:
        git_reset(tenant, "development")


def setup_ssh(tenant, env):
    """
    Deploy Assh configs for tenant/environment.

    :type  tenant: string
    :param tenant: The name of the tenant.

    :type  env: string
    :param env: The name of the tenant.

    :rtype:   None
    :return:  the function doesn't have a return statement.
    """
    _dir = utils.get_tenant_dir(tenant)
    target_folder = _dir + env
    dest_folder = os.getenv('HOME') + '/.ssh/assh.d/' + tenant
    dest_file = dest_folder + '/' + env + '.yml'

    is_decrypted = False
    # Files are encrypted. Decrypt and save status to re-encrypt later.
    if utils.check_string_in_file(target_folder + "/inventory", 'AES256'):
        apansible.decrypt(tenant, env)<commit_msg>Fix bug: folder not created if it does not exists.<commit_after>"""
Appflow Tools.
This contains all the functions needed to perform actions connected to
initialization, config deployment and git versioning.
"""
import json
import os
import shutil
import subprocess

import yaml

import lib.appflow_ansible as apansible
import lib.appflow_utils as utils
import lib.appflow_yaml as apyaml


def initialize(tenant, env):
    """
    Create default dirs, clone playbooks and yaml files for Assh to function properly.

    :type  tenant: string
    :param tenant: The name of the tenant. (ex: mrrobot)

    :type  env: string
    :param env: The name of the tenant.


    :rtype:   None
    :return:  This function doesn't have a return statement.
    """

    # We use this to distinguish if tenant+env is specified
    # if not, we should ask them!
    if tenant is None or env is None:
        tenant = input("What's the tenant name? ")
        choice = int(input("""
        Choose your default environment
        1) Development
        2) Staging
        3) Production
        """))
        if choice < 1 or choice > 3:
            print('Invalid option')
            return

        environmens = ['development', 'staging', 'production']
        env = environmens[choice - 1]

    dirs = ['/.ssh', '/.ssh/assh.d/' + tenant, '/tmp/.ssh/cm', '/.appflow',
            '/.appflow/tenant', '/.appflow/vault']

    # Mkdir -p of needed folders.
    for directory in dirs:
        os.makedirs(os.getenv('HOME') + directory, exist_ok=True)

    # Setup default configs
    setup_default_config(tenant, env)

    # Initialize a default assh.yml config
    conf = {'defaults': {'ControlMaster': 'auto',
                         'ControlPath': '~/tmp/.ssh/cm/%h-%p-%r.sock',
                         'ControlPersist': True,
                         'ForwardAgent': True},
            'includes': ['~/.ssh/assh.d/*/*.yml',
                         '~/.ssh/assh_personal.yml']}
    file_name = os.getenv('HOME') + "/.ssh/assh.yml"
    # Write it to file.
    with open(file_name, 'w') as outfile:
        yaml.dump(conf, outfile, default_flow_style=False,
                  indent=4)

    # Clone appflow-playbooks.
    subprocess.Popen(['git', '-C', os.getenv('HOME') + '/.appflow',
                      'clone',
                      'https://github.com/ttssdev/appflow-playbooks',
                      'playbooks'],
                     stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    print("Done")
    return


def setup_default_config(tenant, env):
    """
    Deploy a default config file in ~/.appflow/config.yml

    :type  tenant: string
    :param tenant: The name of the tenant. (ex: mrrobot)

    :type  env: string
    :param env: The name of the tenant.

    :rtype:   None
    :return:  the function prints to screen the ansible output of the execution.
    """
    file_name = os.getenv('HOME') + "/.appflow/config.yml"
    utils.safe_remove(file_name)
    conf = {'appflow': {'tenant': {'id': 'appflow-' + tenant,
                                   'name': tenant,
                                   'default_env': env}}}
    with open(file_name, 'w') as outfile:
        yaml.dump(conf, outfile, default_flow_style=False,
                  indent=4)


def set_vhosts_hosts(tenant):
    """
    Setup /etc/hosts for tenant.
    Requires root access to write.

    :type  tenant: string
    :param tenant: The name of the tenant.

    :rtype:   None
    :return:  the function doesn't have a return statement.
    """
    _dir = utils.get_tenant_dir(tenant)
    target_folder = _dir + "development"
    is_decrypted = False
    # Files are encrypted. Decrypt and save status to re-encrypt later.
    if utils.check_string_in_file(target_folder + "/inventory", 'AES256'):
        apansible.decrypt(tenant, "development")
        is_decrypted = True
    vhosts = apyaml.get_value(tenant + ".development.group_vars.all",
                              "conf_vhosts_common")
    vhosts = json.loads(vhosts)
    ip_list = apyaml.get_value(tenant + ".development.group_vars.all",
                               "conf_hosts")
    ip_list = json.loads(ip_list)

    # Open /etc/hosts file.
    # Put it in string list.
    file = open("/etc/hosts", 'r')
    current_hosts = [line.strip() for line in file]

    # Just add a separation line.
    os.system('echo "\n" | sudo tee -a /etc/hosts')

    new_hosts = []
    for _ip in ip_list:
        # Check if this line is already present
        if _ip not in "".join(current_hosts):
            # if not present add it!
            new_hosts.append(_ip)
    for host in vhosts:
        if vhosts.get(host)["state"] == "enabled":
            server_alias = vhosts.get(host)["servername"]
            for alias in vhosts.get(host)["serveralias"]:
                server_alias = server_alias + " " + alias
        for _ip in ip_list:
            # Assemble the line IP + servername + aliases
            _ip = _ip.split()[0] + " " + server_alias
            # Check if this line is already present
            if _ip not in "".join(current_hosts):
                # if not present add it!
                new_hosts.append(_ip)
    for host in new_hosts:
        # let's append to the file only the lines we need
        # we will need sudo in order to write in /etc/hosts
        os.system('echo ' + host + ' | sudo tee -a /etc/hosts')
    if is_decrypted is True:
        git_reset(tenant, "development")


def setup_ssh(tenant, env):
    """
    Deploy Assh configs for tenant/environment.

    :type  tenant: string
    :param tenant: The name of the tenant.

    :type  env: string
    :param env: The name of the tenant.

    :rtype:   None
    :return:  the function doesn't have a return statement.
    """
    _dir = utils.get_tenant_dir(tenant)
    target_folder = _dir + env
    dest_folder = os.getenv('HOME') + '/.ssh/assh.d/' + tenant
    if not os.path.exists(dest_folder):
        os.makedirs(dest_folder, exist_ok=True)
    dest_file = dest_folder + '/' + env + '.yml'

    is_decrypted = False
    # Files are encrypted. Decrypt and save status to re-encrypt later.
    if utils.check_string_in_file(target_folder + "/inventory", 'AES256'):
        apansible.decrypt(tenant, env)
{'fraction_non_alphanumeric': 0.11372644180215158, 'fraction_numerical': 0.0024265954865323952, 'mean_word_length': 2.1678196259287725, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6773804', 'n_tokens_mistral': 3903, 'n_tokens_neox': 3731, 'n_words': 1129}