import os
import shutil
import time
import string
import random


def try_set_file_permissions(file):
    """
    Try setting the ownership group and permission of the file

    :param file: full path and filename
    """

    os.chmod(file, 0o660)
    try:
        shutil.chown(file, group='microk8s')
    except:
        # not setting the group means only the current user can access the file
        pass


def remove_expired_token_from_file(file):
    """
    Remove expired token from the valid tokens set
    
    :param token: the token to be removed
    :param file: the file to be removed from
    """
    backup_file = "{}.backup".format(file)
    # That is a critical section. We need to protect it.
    # We are safe for now because flask serves one request at a time.
    with open(backup_file, 'w') as back_fp:
        with open(file, 'r') as fp:
            for _, line in enumerate(fp):
                if is_token_expired(line):
                    continue
                back_fp.write("{}".format(line))

    try_set_file_permissions(backup_file)
    shutil.copyfile(backup_file, file)


def remove_token_from_file(token, file):
    """
    Remove a token from the valid tokens set
    
    :param token: the token to be removed
    :param file: the file to be removed from
    """
    backup_file = "{}.backup".format(file)
    # That is a critical section. We need to protect it.
    # We are safe for now because flask serves one request at a time.
    with open(backup_file, 'w') as back_fp:
        with open(file, 'r') as fp:
            for _, line in enumerate(fp):
                # Not considering cluster tokens with expiry in this method.
                if "|" not in line :
                    if line.strip() == token:
                        continue
                back_fp.write("{}".format(line))

    try_set_file_permissions(backup_file)
    shutil.copyfile(backup_file, file)


def is_token_expired(token_line):
    """
    Checks if the token in the file is expired, when using the TTL based.
    """
    if "|" in token_line:
        expiry = token_line.strip().split('|')[1]
        if int(round(time.time())) > int(expiry):
            return True

    return False  


def get_callback_token():
    """
    Generate a token and store it in the callback token file

    :return: the token
    """
    snapdata_path = os.environ.get('SNAP_DATA')
    callback_token_file = "{}/credentials/callback-token.txt".format(snapdata_path)
    if os.path.exists(callback_token_file):
        with open(callback_token_file) as fp:
            token = fp.read()
    else:
        token = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(64))
        with open(callback_token_file, "w") as fp:
            fp.write("{}\n".format(token))
        try_set_file_permissions(callback_token_file)

    return token


def is_node_running_dqlite():
    """
    Check if we should use the dqlite joining process (join api version 2.0)

    :return: True if dqlite is to be used
    """
    snapdata_path = os.environ.get('SNAP_DATA')
    apiserver_conf_file = "{}/args/kube-apiserver".format(snapdata_path)
    with open(apiserver_conf_file) as f:
        for line in f:
            if line.startswith("--storage-backend") and line.rstrip().endswith("dqlite"):
                return True

    return False

import os
import shutil
import time
import string
import random


def try_set_file_permissions(file):
    """
    Try setting the ownership group and permission of the file

    :param file: full path and filename
    """

    os.chmod(file, 0o660)
    try:
        shutil.chown(file, group='microk8s')
    except:
        # not setting the group means only the current user can access the file
        pass


def remove_expired_token_from_file(file):
    """
    Remove expired token from the valid tokens set
    
    :param token: the token to be removed
    :param file: the file to be removed from
    """
    backup_file = "{}.backup".format(file)
    # That is a critical section. We need to protect it.
    # We are safe for now because flask serves one request at a time.
    with open(backup_file, 'w') as back_fp:
        with open(file, 'r') as fp:
            for _, line in enumerate(fp):
                if is_token_expired(line):
                    continue
                back_fp.write("{}".format(line))

    try_set_file_permissions(backup_file)
    shutil.copyfile(backup_file, file)


def remove_token_from_file(token, file):
    """
    Remove a token from the valid tokens set
    
    :param token: the token to be removed
    :param file: the file to be removed from
    """
    backup_file = "{}.backup".format(file)
    # That is a critical section. We need to protect it.
    # We are safe for now because flask serves one request at a time.
    with open(backup_file, 'w') as back_fp:
        with open(file, 'r') as fp:
            for _, line in enumerate(fp):
                # Not considering cluster tokens with expiry in this method.
                if "|" not in line :
                    if line.strip() == token:
                        continue
                back_fp.write("{}".format(line))

    try_set_file_permissions(backup_file)
    shutil.copyfile(backup_file, file)


def is_token_expired(token_line):
    """
    Checks if the token in the file is expired, when using the TTL based.
    """
    if "|" in token_line:
        expiry = token_line.strip().split('|')[1]
        if int(round(time.time())) > int(expiry):
            return True

    return False  


def get_callback_token():
    """
    Generate a token and store it in the callback token file

    :return: the token
    """
    snapdata_path = os.environ.get('SNAP_DATA')
    callback_token_file = "{}/credentials/callback-token.txt".format(snapdata_path)
    if os.path.exists(callback_token_file):
        with open(callback_token_file) as fp:
            token = fp.read()
    else:
        token = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(64))
        with open(callback_token_file, "w") as fp:
            fp.write("{}\n".format(token))
        try_set_file_permissions(callback_token_file)

    return token


def is_node_running_dqlite():
    """
    Check if we should use the dqlite joining process (join api version 2.0)

    :return: True if dqlite is to be used
    """
    snapdata_path = os.environ.get('SNAP_DATA')
    apiserver_conf_file = "{}/args/kube-apiserver".format(snapdata_path)
    with open(apiserver_conf_file) as f:
        for line in f:
            if line.startswith("--storage-backend") and line.rstrip().endswith("dqlite"):
                return True

    return False

Try setting the ownership group and permission of the file      :param file: full path and filename # not setting the group means only the current user can access the file Remove expired token from the valid tokens set          :param token: the token to be removed     :param file: the file to be removed from # That is a critical section. We need to protect it. # We are safe for now because flask serves one request at a time. Remove a token from the valid tokens set          :param token: the token to be removed     :param file: the file to be removed from # That is a critical section. We need to protect it. # We are safe for now because flask serves one request at a time. # Not considering cluster tokens with expiry in this method. Checks if the token in the file is expired, when using the TTL based. Generate a token and store it in the callback token file      :return: the token Check if we should use the dqlite joining process (join api version 2.0)      :return: True if dqlite is to be used