def get_members(cluster: Cluster, cluster_name: str, member_names: List[str], role: CtlPostgresqlRole,
                force: bool, action: str, ask_confirmation: bool = True, group: Optional[int] = None) -> List[Member]:
    """Get the list of members based on the given filters.

    .. note::
        Contain some filtering and checks processing that are common to several actions that are exposed
        by `patronictl`, like:

            * Get members of *cluster* that respect the given *member_names*, *role*, and *group*;
            * Bypass confirmations;
            * Prompt user for information that has not been passed through the command-line options;
            * etc.

        Designed to handle both attended and unattended ``patronictl`` commands execution that need to retrieve and
        validate the members before doing anything.

        In the very end may call :func:`confirm_members_action` to ask if the user would like to proceed with *action*
        over the retrieved members. That won't actually perform the action, but it works as the "last confirmation"
        before the *action* is processed by the caller method.

        Additional checks can also be implemented in the caller method, in which case you might want to pass
        ``ask_confirmation=False``, and later call :func:`confirm_members_action` manually in the caller method. That
        way the workflow won't look broken to the user that is interacting with ``patronictl``.

    :param cluster: Patroni cluster.
    :param cluster_name: name of the Patroni cluster.
    :param member_names: used to filter which members should take the *action* based on their names. Each item is the
        name of a Patroni member, as per ``name`` configuration. If *member_names* is an empty :class:`tuple` no filters
        are applied based on names.
    :param role: used to filter which members should take the *action* based on their role. See :func:`get_all_members`
        for available options.
    :param force: if ``True``, then it won't ask for confirmations at any point nor prompt the user to select values
        for options that were not specified through the command-line.
    :param action: the action that is being processed, one among:

        * ``reload``: reload PostgreSQL configuration; or
        * ``restart``: restart PostgreSQL; or
        * ``reinitialize``: reinitialize PostgreSQL data directory; or
        * ``flush``: discard scheduled actions.
    :param ask_confirmation: if ``False``, then it won't ask for the final confirmation regarding the *action* before
        returning the list of members. Usually useful as ``False`` if you want to perform additional checks in
        the caller method besides the checks that are performed through this generic method.
    :param group: filter which Citus group we should get members from. If ``None`` consider members from all groups.

    :returns: a list of members that respect the given filters.

    :raises:
        :class:`PatroniCtlException`: if
            * Cluster does not have members that match the given *role*; or
            * Cluster does not have members that match the given *member_names*; or
            * No member with given *role* is found among the specified *member_names*.
    """
    members = list(get_all_members(cluster, group, role))

    candidates = {m.name for m in members}
    if not force or role:
        if not member_names and not candidates:
            raise PatroniCtlException('{0} cluster doesn\'t have any members'.format(cluster_name))
        output_members(cluster, cluster_name, group=group)

    if member_names:
        member_names = list(set(member_names) & candidates)
        if not member_names:
            raise PatroniCtlException('No {0} among provided members'.format(role))
    elif action != 'reinitialize':
        member_names = list(candidates)

    if not member_names and not force:
        member_names = [click.prompt('Which member do you want to {0} [{1}]?'.format(action,
                        ', '.join(candidates)), type=str, default='')]

    for member_name in member_names:
        if member_name not in candidates:
            raise PatroniCtlException('{0} is not a member of cluster'.format(member_name))

    members = [m for m in members if m.name in member_names]
    if ask_confirmation:
        confirm_members_action(members, force, action)
    return members
Get the list of members based on the given filters.

    .. note::
        Contain some filtering and checks processing that are common to several actions that are exposed
        by `patronictl`, like:

            * Get members of *cluster* that respect the given *member_names*, *role*, and *group*;
            * Bypass confirmations;
            * Prompt user for information that has not been passed through the command-line options;
            * etc.

        Designed to handle both attended and unattended ``patronictl`` commands execution that need to retrieve and
        validate the members before doing anything.

        In the very end may call :func:`confirm_members_action` to ask if the user would like to proceed with *action*
        over the retrieved members. That won't actually perform the action, but it works as the "last confirmation"
        before the *action* is processed by the caller method.

        Additional checks can also be implemented in the caller method, in which case you might want to pass
        ``ask_confirmation=False``, and later call :func:`confirm_members_action` manually in the caller method. That
        way the workflow won't look broken to the user that is interacting with ``patronictl``.

    :param cluster: Patroni cluster.
    :param cluster_name: name of the Patroni cluster.
    :param member_names: used to filter which members should take the *action* based on their names. Each item is the
        name of a Patroni member, as per ``name`` configuration. If *member_names* is an empty :class:`tuple` no filters
        are applied based on names.
    :param role: used to filter which members should take the *action* based on their role. See :func:`get_all_members`
        for available options.
    :param force: if ``True``, then it won't ask for confirmations at any point nor prompt the user to select values
        for options that were not specified through the command-line.
    :param action: the action that is being processed, one among:

        * ``reload``: reload PostgreSQL configuration; or
        * ``restart``: restart PostgreSQL; or
        * ``reinitialize``: reinitialize PostgreSQL data directory; or
        * ``flush``: discard scheduled actions.
    :param ask_confirmation: if ``False``, then it won't ask for the final confirmation regarding the *action* before
        returning the list of members. Usually useful as ``False`` if you want to perform additional checks in
        the caller method besides the checks that are performed through this generic method.
    :param group: filter which Citus group we should get members from. If ``None`` consider members from all groups.

    :returns: a list of members that respect the given filters.

    :raises:
        :class:`PatroniCtlException`: if
            * Cluster does not have members that match the given *role*; or
            * Cluster does not have members that match the given *member_names*; or
            * No member with given *role* is found among the specified *member_names*.
    
patroni/ctl.py