Example #1
0
def git_reset(tenant, env):
    """
    Perform git reset in the specified tenant/environment folder.
    After this, updates the md5 file to reflect the new status.

    :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)
    _pipe = subprocess.PIPE
    subprocess.Popen(
        ['git', '-C', _dir, 'clean -xdf', env], stdout=_pipe, stderr=_pipe)
    subprocess.Popen(
        ['git', '-C', _dir, 'checkout', env], stdout=_pipe, stderr=_pipe)
    subprocess.Popen(
        ['git', '-C', _dir, 'reset --hard'], stdout=_pipe, stderr=_pipe)
    md5_store_folder = utils.get_md5_folder(tenant)
    md5_store_file = md5_store_folder + "/appflow-" + env + "-md5"
    utils.safe_remove(md5_store_file)
    utils.safe_remove(md5_store_file + "-new")
Example #2
0
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)
        is_decrypted = True

    shutil.copy2(target_folder + "/assh.yml", dest_file)
    print(dest_folder + '/' + env + '.yml', "deployed")
    if is_decrypted is True:
        git_reset(tenant, env)
Example #3
0
def provision(tenant: str, env: str, limit: str, tags: str,
              skip_tags: str, firstrun: bool, local: bool):
    """
    This will perform the ansible playbook.
    We pass tenant and environment and all other options as
    --option xys
    in order to respect ansible's syntax.

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

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

    :type  limit: string
    :param limit: Comma separated list of hosts to provision.

    :type  tags: string
    :param tags: Comma separated list of tags to exec (default All).

    :type  skip_tags: string
    :param skip_tags: Comma separated list of tags to skip (default None).

    :type  firstrun: bool
    :param firstrun: if it's first run (default False)

    :rtype:   None
    :return:  the function prints to screen the ansible output of the
                execution.
    """
    inventory = utils.get_tenant_dir(tenant) + env + "/inventory"
    appflow_folder = utils.get_appflow_folder()
    playbook = appflow_folder + '/playbooks/generic.yml'
    password_file = utils.get_vault_file(tenant, env)

    # Let's be sure the arguments are strings.
    # In case of multiple arguments (comma separated), convert them back to str.
    limit = utils.format_string_argument(limit)
    tags = utils.format_string_argument(tags)
    skip_tags = utils.format_string_argument(skip_tags)

    tags_argument = []
    # Format arguments for ansible command now.
    if limit is not None:
        tags_argument.append("--limit " + limit)
    if tags is not None:
        tags_argument.append("--tags " + tags)
    if skip_tags is not None:
        tags_argument.append("--skip-tags " + skip_tags)
    # First run! Let's default to the generic user waiting for users provision
    if firstrun:
        tags_argument.append("-k -u ubuntu")
    if local:
        tags_argument.append("-c local")
    os.system('ansible-playbook -b ' + ' '.join(tags_argument) + ' -i ' +
              inventory + ' ' + playbook +
              ' --vault-password-file ' + password_file)
Example #4
0
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]

    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")
Example #5
0
def git_check_in(tenant, env, commit):
    """
    Git push.
    This will affecy only the modified files (see git_status function).
    Commit message can be specified.

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

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

    :type  commit: string
    :param commit: The commit message to use when committing.

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

    """
    _dir = utils.get_tenant_dir(tenant)
    folder = utils.get_tenant_env_dir(tenant, env)
    file_list = utils.get_file_list(folder)
    is_encrypted = False
    for file in file_list:
        if utils.check_string_in_file(file, 'AES256'):
            is_encrypted = True
    diff = git_status(tenant, env)
    if is_encrypted is False:
        apansible.encrypt(tenant, env)

    _pipe = subprocess.PIPE
    for file in diff:
        out = subprocess.Popen(
            ['git', '-C', _dir, 'add', file], stdout=_pipe, stderr=_pipe)
        for line in iter(out.stdout.readline, b''):
            print(line.decode('utf-8'))
    out = subprocess.Popen(
        ['git', '-C', _dir, 'commit', '-m', commit], stdout=_pipe, stderr=_pipe)
    for line in iter(out.stdout.readline, b''):
        print(line.decode('utf-8'))
    out = subprocess.Popen(
        ['git', '-C', _dir, 'push'], stdout=_pipe, stderr=_pipe)
    for line in iter(out.stdout.readline, b''):
        print(line.decode('utf-8'))
    git_reset(tenant, env)
Example #6
0
def list_tags(tenant, env):
    """
    List all available tags 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 prints to screen the available tags.
    """
    inventory = utils.get_tenant_dir(tenant) + env + "/inventory"
    appflow_folder = utils.get_appflow_folder()
    playbook = appflow_folder + '/playbooks/generic.yml'
    password_file = utils.get_vault_file(tenant, env)

    os.system('ansible-playbook --list-tags -i ' + inventory +
              ' ' + playbook + ' --vault-password-file ' + password_file)
Example #7
0
def git_status(tenant, env):
    """
    Return a status of modified files in the tenant/environment folder.
    this is tracked separately from git, because encryption/decryption of files
    will always override the git status method.

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

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

    :rtype:   list
    :return:  the function returns a list containing the different lines between
                the 2 md5 files.
    """
    _dir = utils.get_tenant_dir(tenant)
    target_folder = _dir + env
    if not utils.check_string_in_file(target_folder + "/inventory", 'AES256'):
        md5_store_folder = utils.get_md5_folder(tenant)
        md5_store_file = md5_store_folder + "/appflow-" + env + "-md5"
        md5_store_file_new = md5_store_folder + "/appflow-" + env + "-md5-new"
        utils.safe_remove(md5_store_file_new)
        file_list = utils.get_file_list(target_folder)
        for file in file_list:
            utils.write_md5_sum(file, md5_store_file_new)

        diff = utils.diff_files(md5_store_file, md5_store_file_new)
        return diff

    # Files are encrypted, simply do a git diff
    _pipe = subprocess.PIPE
    out = subprocess.Popen(['git', '-C', _dir,
                            'diff-files', '--name-only', '-B', '-R', '-M', env],
                           stdout=_pipe, stderr=_pipe)
    result = []
    for line in iter(out.stdout):
        result.append(line.decode('utf-8'))
    return result
Example #8
0
def git_check_out(tenant, env):
    """
    Git pull of the specified tenant/environment folder.
    un-pushed work can be overwritten by this, so ask for confirmation.

    :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.
    """
    query = utils.yes_no(
        'WARNING, this will overwrite any un-pushed work, continue?', 'no')
    if query is True:
        git_reset(tenant, env)
        _dir = utils.get_tenant_dir(tenant)
        _pipe = subprocess.PIPE
        out = subprocess.Popen(
            ['git', '-C', _dir, 'pull'], stdout=_pipe, stderr=_pipe)
        for line in iter(out.stdout.readline, b''):
            print(line.decode('utf-8'))