Esempio n. 1
0
def test_execute_system_command_unknown_error(mocker):

    # noinspection PyUnusedLocal
    def raise_command_exception(*args, **kwargs):
        raise subprocess.SubprocessError()

    mocker.patch('subprocess.check_output', new=raise_command_exception)

    with pytest.raises(subprocess.SubprocessError):
        execute_system_command(['ls'])
Esempio n. 2
0
def _show_workflow_logs(workflow: ArgoWorkflow, namespace: str):
    try:
        log.debug(f'Worklfow {workflow.name} main container logs:')
        output, _, _ = execute_system_command(command=[
            'kubectl', 'logs', '-n', namespace, workflow.name, 'main'
        ])
        log.debug(output)
        log.debug(f'Worklfow {workflow.name} wait container logs:')
        output, _, _ = execute_system_command(command=[
            'kubectl', 'logs', '-n', namespace, workflow.name, 'wait'
        ])
        log.debug(output)
    except Exception:
        log.exception(f'Failed to get {workflow.name} worklfow logs.')
Esempio n. 3
0
File: helm.py Progetto: yuanbw/nauta
def delete_helm_release(release_name: str, purge=False, namespace: str = None):
    """
    Deletes release of a helm's chart.

    :param release_name: name of a release to be removed
    :param purge: if True, helm release will be purged
    In case of any problems it throws an exception
    """
    if purge:
        delete_release_command = [
            os.path.join(Config().config_path, 'helm'), "delete", "--purge",
            release_name
        ]
    else:
        delete_release_command = [
            os.path.join(Config().config_path, 'helm'), "delete", release_name
        ]

    if namespace:
        delete_release_command += ["--tiller-namespace", namespace]

    output, err_code, log_output = execute_system_command(
        delete_release_command)

    if (f"release \"{release_name}\" deleted" not in output
            and f"release: \"{release_name}\" not found" not in output):
        logger.error(log_output)
        raise RuntimeError(
            Texts.HELM_RELEASE_REMOVAL_ERROR_MSG.format(
                release_name=release_name))
Esempio n. 4
0
def get_top_for_pod(name: str, namespace: str) -> Tuple[str, str]:
    """
    Returns cpu and memory usage for a pod with a given name located in a given namespace
    :param name: name of a pod
    :param namespace:  namespace where the pod resided. Optional - if not given, function searches the pod in
                        current namespace
    :return: tuple containing two values - cpu and memory usage expressed in k8s format
    """
    top_command = ["kubectl", "top", "pod", name]

    if namespace:
        top_command.extend(["-n", namespace])
    output, err_code, log_output = system.execute_system_command(top_command)
    if err_code:
        raise KubectlConnectionError(
            Texts.K8S_CLUSTER_NO_CONNECTION_ERROR_MSG.format(
                output=log_output))

    if output:
        lines = output.split("\n")

        if lines and len(lines) > 1:
            second_line = lines[1]
            if second_line:
                split_second_line = second_line.split()
                if split_second_line and len(split_second_line) > 2:
                    return (split_second_line[1], split_second_line[2])

    logger.error(Texts.TOP_COMMAND_ERROR_LOG.format(output=log_output))
    raise KubernetesError(Texts.TOP_COMMAND_ERROR)
Esempio n. 5
0
def _debug_workflow_logs(workflow: ArgoWorkflow, namespace: str):
    try:
        output, _, _ = execute_system_command(command=[
            'kubectl', 'logs', '-n', namespace, workflow.name, 'main'
        ])
        log.debug(output)
    except Exception:
        log.exception(f'Failed to get {workflow.name} worklfow logs.')
Esempio n. 6
0
def delete_k8s_object(kind: str, name: str):
    delete_command = ['kubectl', 'delete', kind, name]
    logger.debug(delete_command)
    output, err_code, log_output = system.execute_system_command(
        delete_command)
    logger.debug(f"delete_k8s_object - output : {err_code} - {log_output}")
    if err_code:
        raise RuntimeError(
            Texts.K8S_OBJECT_DELETE_ERROR_MSG.format(output=log_output))
Esempio n. 7
0
def get_mounts_windows():
    output, error_code, log_output = execute_system_command(["net", "use"])

    if error_code:
        handle_error(logger, Texts.MOUNTS_LIST_COMMAND_ERROR_MSG,
                     Texts.MOUNTS_LIST_COMMAND_ERROR_MSG)
        exit(1)
    host = get_kubectl_host(with_port=False)
    data = output.split("\n")

    start_analyzing = False
    ret_list = []
    first_line = None
    second_line = None

    for item in data:
        if start_analyzing:
            if "The command completed successfully." in item:
                break
            else:
                if not first_line:
                    first_line = item
                elif not second_line:
                    second_line = item

                if first_line and second_line:
                    if host in first_line:
                        split_first_line = first_line.split()
                        status = None
                        remote_location = None
                        if len(split_first_line) == 3:
                            status = split_first_line[0].strip()
                            local_folder = split_first_line[1].strip()
                            remote_location = split_first_line[2].strip()
                        elif len(split_first_line) == 2:
                            status = split_first_line[0].strip()
                            local_folder = ""
                            remote_location = split_first_line[1].strip()
                        network = second_line.strip()
                        if status and remote_location:
                            ret_list.append(
                                ShareData(remote_share=remote_location,
                                          local_share=local_folder,
                                          status=status,
                                          network=network))
                    first_line = None
                    second_line = None
        elif "--------" in item:
            start_analyzing = True

    ret_list.sort(key=lambda x: x.remote_share, reverse=False)

    click.echo(
        tabulate([x.windows_tabular_format() for x in ret_list],
                 headers=ShareData.WIN_MOUNTS_LIST_HEADERS,
                 tablefmt=TBLT_TABLE_FORMAT))
Esempio n. 8
0
def test_execute_system_command_limited_logs(mocker):
    cop_mock = mocker.patch('subprocess.check_output')
    cop_mock.return_value = 50 * "a"
    output, exit_code, log_output = execute_system_command(['ls'],
                                                           logs_size=20)

    assert len(log_output) == 20
    assert len(output) == 50
    # noinspection PyUnresolvedReferences
    assert subprocess.check_output.call_count == 1
Esempio n. 9
0
def get_mounts_linux_osx(username: str = "",
                         is_admin: bool = False,
                         osx: bool = False):
    output, error_code, log_output = execute_system_command(["mount"])

    if error_code:
        handle_error(logger, Texts.MOUNTS_LIST_COMMAND_ERROR_MSG,
                     Texts.MOUNTS_LIST_COMMAND_ERROR_MSG)
        exit(1)
    host = get_kubectl_host(with_port=False)
    if osx:
        username_string = f"//{username}@"
    else:
        username_string = f"username={username},"

    if osx:
        mnt_regex = "//(.*)@(.*) on (.*) \("
    else:
        mnt_regex = "(.*) on (.*) type"

    ret_list = []

    if output:
        for item in [
                nauta_item for nauta_item in output.split("\n")
                if host in nauta_item and (
                    is_admin or username_string in nauta_item)
        ]:
            try:
                mount_data = re.search(mnt_regex, item)
                if osx:
                    # Type checking is disabled here - we are catching AttributeError exception anyway
                    username = mount_data.group(1)  # type: ignore
                    remote_location = mount_data.group(2)  # type: ignore
                    local_folder = mount_data.group(3)  # type: ignore
                else:
                    remote_location = mount_data.group(1)  # type: ignore
                    local_folder = mount_data.group(2)  # type: ignore
                    username = re.search("username=(.*?),",
                                         item).group(1)  # type: ignore

                ret_list.append(
                    ShareData(remote_share=remote_location,
                              local_share=local_folder,
                              username=username))
            except Exception:
                handle_error(logger, Texts.MOUNTS_LIST_COMMAND_ERROR_MSG,
                             Texts.MOUNTS_LIST_COMMAND_ERROR_MSG)

    ret_list.sort(key=lambda x: x.username, reverse=False)

    click.echo(
        tabulate([x.linux_osx_tabular_format() for x in ret_list],
                 headers=ShareData.LINUX_MOUNTS_LIST_HEADERS,
                 tablefmt=TBLT_TABLE_FORMAT))
Esempio n. 10
0
def check_connection_to_cluster():
    check_connection_cmd = ['kubectl', 'get', 'pods']
    logger.debug(check_connection_cmd)
    output, err_code, log_output = system.execute_system_command(
        check_connection_cmd)
    logger.debug(
        f"check_connection_to_cluster - output : {err_code} - {log_output}")
    if err_code:
        raise KubectlConnectionError(
            Texts.K8S_CLUSTER_NO_CONNECTION_ERROR_MSG.format(
                output=log_output))
Esempio n. 11
0
def test_execute_system_command_known_error(mocker):

    bad_exit_code = 1

    # noinspection PyUnusedLocal
    def raise_command_exception(*args, **kwargs):
        raise subprocess.CalledProcessError(returncode=bad_exit_code, cmd='ls')

    mocker.patch('subprocess.check_output', new=raise_command_exception)

    output, exit_code, log_output = execute_system_command(['ls'])

    assert exit_code == bad_exit_code
Esempio n. 12
0
def call_draft(args: List[str], cwd: str = None, namespace: str = None, logs_size: int = 0) \
        -> (str, int, str):
    config_path = Config().config_path
    full_command = [os.path.join(config_path, DRAFT_BIN)]
    full_command.extend(args)
    if get_verbosity_level() == logging.DEBUG:
        full_command.append('--debug')
    env = os.environ.copy()
    env['PATH'] = config_path + os.pathsep + env['PATH']
    env['DRAFT_HOME'] = os.path.join(config_path, DRAFT_HOME_FOLDER)
    if namespace:
        env['TILLER_NAMESPACE'] = namespace
    return execute_system_command(
        full_command, env=env, cwd=cwd, logs_size=logs_size)
Esempio n. 13
0
File: helm.py Progetto: yuanbw/nauta
def install_helm_chart(chart_dirpath: str,
                       release_name: str = None,
                       tiller_namespace: str = None):
    command = [
        os.path.join(Config().config_path, 'helm'), "install", chart_dirpath
    ]
    if release_name:
        command.extend(["--name", release_name])
    if tiller_namespace:
        command.extend(["--tiller-namespace", tiller_namespace])

    output, err_code, log_output = execute_system_command(command)
    logger.debug(f"helm exit code: {err_code} returned: {output}")

    if err_code != 0:
        raise RuntimeError(f"helm returned with non-zero code: {err_code}")
Esempio n. 14
0
def install_helm_chart(chart_dirpath: str,
                       release_name: str = None,
                       tiller_namespace: str = None):
    command = ["helm", "install", chart_dirpath]
    if release_name:
        command.extend(["--name", release_name])
    if tiller_namespace:
        command.extend(["--tiller-namespace", tiller_namespace])

    env = os.environ.copy()
    env['PATH'] = f"{Config().config_path}{os.pathsep}{env['PATH']}"
    output, err_code, log_output = execute_system_command(command, env=env)
    logger.debug(f"helm exit code: {err_code} returned: {output}")

    if err_code != 0:
        raise RuntimeError(f"helm returned with non-zero code: {err_code}")
Esempio n. 15
0
File: create.py Progetto: zhcf/nauta
def create(state: State, username: str, list_only: bool, filename: str):
    """
    Adds a new user with a name given as a parameter.

    :param username: name of a new user
    """

    if list_only and filename:
        handle_error(user_msg=Texts.F_L_OPTIONS_EXCLUSION_ERROR_MSG)
        exit(1)

    try:
        try:
            validate_user_name(username)
        except ValueError as exe:
            handle_error(
                logger,
                Texts.NAME_VALIDATION_ERROR_MSG.format(username=username),
                str(exe),
                add_verbosity_msg=state.verbosity == 0)
            exit(1)

        if not is_current_user_administrator():
            handle_error(logger, Texts.USER_NOT_ADMIN_ERROR_MSG,
                         Texts.USER_NOT_ADMIN_ERROR_MSG)
            exit(1)

        user_state = check_users_presence(username)

        if user_state == UserState.ACTIVE:
            handle_error(
                logger,
                Texts.USER_ALREADY_EXISTS_ERROR_MSG.format(username=username),
                Texts.USER_ALREADY_EXISTS_ERROR_MSG.format(username=username))
            exit(1)

        if user_state == UserState.TERMINATING:
            handle_error(
                logger,
                Texts.USER_BEING_REMOVED_ERROR_MSG.format(username=username),
                Texts.USER_BEING_REMOVED_ERROR_MSG.format(username=username))
            exit(1)

    except Exception:
        handle_error(
            logger,
            Texts.USER_VERIFICATION_ERROR_MSG.format(username=username),
            Texts.USER_VERIFICATION_ERROR_MSG.format(username=username),
            add_verbosity_msg=state.verbosity == 0)
        exit(1)

    try:
        with spinner(text=Texts.CREATING_USER_PROGRESS_MSG.format(
                username=username)):
            chart_location = os.path.join(Config().config_path,
                                          ADD_USER_CHART_NAME)

            nauta_config_map = NAUTAConfigMap()

            tiller_location = nauta_config_map.image_tiller
            tensorboard_service_location = nauta_config_map.image_tensorboard_service

            add_user_command = [
                "helm", "install", "--wait", "--namespace", username, "--name",
                username, chart_location, "--set", "global.nauta=nauta",
                "--set", f"username={username}", "--set",
                "TillerImage={}".format(tiller_location), "--set",
                f"TensorboardServiceImage={tensorboard_service_location}"
            ]
            env = os.environ.copy()
            env['PATH'] = Config().config_path + os.pathsep + env['PATH']
            _, err_code, log_output = execute_system_command(
                ' '.join(add_user_command), env=env, shell=True)

        if err_code:
            handle_error(logger,
                         log_output,
                         Texts.USER_ADD_ERROR_MSG,
                         add_verbosity_msg=state.verbosity == 0)

            if not delete_user(username):
                handle_error(user_msg=Texts.REMOVE_USER_ERROR_MSG.format(
                    username=username))
            sys.exit(1)

        try:
            users_password = get_users_token(username)
        except Exception:
            handle_error(logger,
                         Texts.PASSWORD_GATHER_ERROR_MSG,
                         Texts.PASSWORD_GATHER_ERROR_MSG,
                         add_verbosity_msg=state.verbosity == 0)
            users_password = ""

        try:
            cert = get_certificate(username)
        except Exception:
            handle_error(logger,
                         Texts.CERT_GATHER_ERROR_MSG,
                         Texts.CERT_GATHER_ERROR_MSG,
                         add_verbosity_msg=state.verbosity == 0)
            cert = ""

    except Exception:
        handle_error(logger,
                     Texts.USER_ADD_ERROR_MSG.format(username=username),
                     Texts.USER_ADD_ERROR_MSG.format(username=username),
                     add_verbosity_msg=state.verbosity == 0)
        if not delete_user(username):
            handle_error(user_msg=Texts.REMOVE_USER_ERROR_MSG.format(
                username=username))
        sys.exit(1)

    if is_user_created(username, 90):
        click.echo(Texts.USER_CREATION_SUCCESS_MSG.format(username=username))
    else:
        # if during 90 seconds a user hasn't been created - app displays information about it
        # but don't step processing the command - config file generated here my be useful later
        # when user has been created
        click.echo(Texts.USER_NOT_READY_ERROR_MSG.format(username=username))

    try:
        kubeconfig = generate_kubeconfig(username, username,
                                         get_kubectl_host(), users_password,
                                         cert)
    except Exception:
        handle_error(logger,
                     Texts.CONFIG_CREATION_ERROR_MSG,
                     Texts.CONFIG_CREATION_ERROR_MSG,
                     add_verbosity_msg=state.verbosity == 0)
        exit(1)

    if list_only:
        click.echo(Texts.LIST_ONLY_HEADER)
        click.echo(kubeconfig)
    else:
        if not filename:
            filename = DEFAULT_FILENAME.format(username)
        try:
            with open(filename, "w") as file:
                file.write(kubeconfig)

            click.echo(Texts.CONFIG_SAVE_SUCCESS_MSG.format(filename=filename))
        except Exception:
            handle_error(logger,
                         Texts.CONFIG_SAVE_FAIL_MSG,
                         Texts.CONFIG_SAVE_FAIL_MSG,
                         add_verbosity_msg=state.verbosity == 0)
            click.echo(Texts.CONFIG_SAVE_FAIL_INSTRUCTIONS_MSG)
            click.echo(kubeconfig)
            sys.exit(1)
Esempio n. 16
0
def test_execute_system_command(mocker):
    mocker.patch('subprocess.check_output')
    output, exit_code, log_output = execute_system_command(['ls'])

    # noinspection PyUnresolvedReferences
    assert subprocess.check_output.call_count == 1