Exemplo n.º 1
0
def whoami_command(linked_identities):
    """
    Executor for `globus whoami`
    """
    client = get_auth_client()

    # get userinfo from auth.
    # if we get back an error the user likely needs to log in again
    try:
        res = client.oauth2_userinfo()
    except AuthAPIError:
        safeprint(
            "Unable to get user information. Please try " "logging in again.",
            write_to_stderr=True,
        )
        click.get_current_context().exit(1)

    print_command_hint(
        "For information on which identities are in session see\n"
        "  globus session show\n"
    )

    # --linked-identities either displays all usernames or a table if verbose
    if linked_identities:
        try:
            formatted_print(
                res["identity_set"],
                fields=[
                    ("Username", "username"),
                    ("Name", "name"),
                    ("ID", "sub"),
                    ("Email", "email"),
                ],
                simple_text=(
                    None
                    if is_verbose()
                    else "\n".join([x["username"] for x in res["identity_set"]])
                ),
            )
        except KeyError:
            safeprint(
                "Your current login does not have the consents required "
                "to view your full identity set. Please log in again "
                "to agree to the required consents.",
                write_to_stderr=True,
            )

    # Default output is the top level data
    else:
        formatted_print(
            res,
            text_format=FORMAT_TEXT_RECORD,
            fields=[
                ("Username", "preferred_username"),
                ("Name", "name"),
                ("ID", "sub"),
                ("Email", "email"),
            ],
            simple_text=(None if is_verbose() else res["preferred_username"]),
        )
Exemplo n.º 2
0
def whoami_command(linked_identities):
    """
    Executor for `globus whoami`
    """
    client = get_auth_client()

    # get userinfo from auth.
    # if we get back an error the user likely needs to log in again
    try:
        res = client.oauth2_userinfo()
    except AuthAPIError:
        click.echo(
            "Unable to get user information. Please try logging in again.",
            err=True)
        click.get_current_context().exit(1)

    print_command_hint(
        "For information on which identities are in session see\n"
        "  globus session show\n")

    # --linked-identities either displays all usernames or a table if verbose
    if linked_identities:
        try:
            formatted_print(
                res["identity_set"],
                fields=[
                    ("Username", "username"),
                    ("Name", "name"),
                    ("ID", "sub"),
                    ("Email", "email"),
                ],
                simple_text=(None if is_verbose() else "\n".join(
                    [x["username"] for x in res["identity_set"]])),
            )
        except KeyError:
            click.echo(
                "Your current login does not have the consents required "
                "to view your full identity set. Please log in again "
                "to agree to the required consents.",
                err=True,
            )

    # Default output is the top level data
    else:
        formatted_print(
            res,
            text_format=FORMAT_TEXT_RECORD,
            fields=[
                ("Username", "preferred_username"),
                ("Name", "name"),
                ("ID", "sub"),
                ("Email", "email"),
            ],
            simple_text=(None if is_verbose() else res["preferred_username"]),
        )
Exemplo n.º 3
0
def bookmark_show(bookmark_id_or_name):
    """
    Given a single bookmark ID or bookmark name, show the bookmark details. By default,
    when the format is TEXT, this will display the endpoint ID and path in
    'ENDPOINT_ID:PATH' notation.

    The default output is suitable for use in a subshell in another command.

    If *-v, --verbose* is given, several fields will be displayed.
    """
    client = get_client()
    res = resolve_id_or_name(client, bookmark_id_or_name)
    formatted_print(
        res,
        text_format=FORMAT_TEXT_RECORD,
        fields=(
            ("ID", "id"),
            ("Name", "name"),
            ("Endpoint ID", "endpoint_id"),
            ("Path", "path"),
        ),
        simple_text=(
            # standard output is endpoint:path format
            "{}:{}".format(res["endpoint_id"], res["path"])
            # verbose output includes all fields
            if not is_verbose() else None),
    )
Exemplo n.º 4
0
def print_version():
    """
    Print out the current version, and at least try to fetch the latest from
    PyPi to print alongside it.

    It may seem odd that this isn't in globus_cli.version , but it's done this
    way to separate concerns over printing the version from looking it up.
    """
    latest, current = get_versions()
    if latest is None:
        click.echo(
            ("Installed Version: {0}\n" "Failed to lookup latest version.").format(
                current
            )
        )
    else:
        click.echo(
            ("Installed Version: {0}\n" "Latest Version:    {1}\n" "\n{2}").format(
                current,
                latest,
                "You are running the latest version of the Globus CLI"
                if current == latest
                else (
                    "You should update your version of the Globus CLI with\n"
                    "  globus update"
                )
                if current < latest
                else "You are running a preview version of the Globus CLI",
            )
        )

    # verbose shows more platform and python info
    # it also includes versions of some CLI dependencies
    if is_verbose():
        moddata = _get_package_data()

        click.echo("\nVerbose Data\n---")

        click.echo("platform:")
        click.echo("  platform: {}".format(platform.platform()))
        click.echo("  py_implementation: {}".format(platform.python_implementation()))
        click.echo("  py_version: {}".format(platform.python_version()))
        click.echo("  sys.executable: {}".format(sys.executable))
        click.echo("  site.USER_BASE: {}".format(site.USER_BASE))

        click.echo("modules:")
        for mod, modversion, modfile, modpath in moddata:
            click.echo("  {}:".format(mod))
            click.echo("    __version__: {}".format(modversion))
            click.echo("    __file__: {}".format(modfile))
            click.echo("    __path__: {}".format(modpath))
Exemplo n.º 5
0
def print_version():
    """
    Print out the current version, and at least try to fetch the latest from
    PyPi to print alongside it.

    It may seem odd that this isn't in globus_cli.version , but it's done this
    way to separate concerns over printing the version from looking it up.
    """
    latest, current = get_versions()
    if latest is None:
        safeprint(
            ("Installed Version: {0}\n" "Failed to lookup latest version.").format(
                current
            )
        )
    else:
        safeprint(
            ("Installed Version: {0}\n" "Latest Version:    {1}\n" "\n{2}").format(
                current,
                latest,
                "You are running the latest version of the Globus CLI"
                if current == latest
                else (
                    "You should update your version of the Globus CLI with\n"
                    "  globus update"
                )
                if current < latest
                else "You are running a preview version of the Globus CLI",
            )
        )

    # verbose shows more platform and python info
    # it also includes versions of some CLI dependencies
    if is_verbose():
        moddata = _get_package_data()

        safeprint("\nVerbose Data\n---")

        safeprint("platform:")
        safeprint("  platform: {}".format(platform.platform()))
        safeprint("  py_implementation: {}".format(platform.python_implementation()))
        safeprint("  py_version: {}".format(platform.python_version()))
        safeprint("  sys.executable: {}".format(sys.executable))
        safeprint("  site.USER_BASE: {}".format(site.USER_BASE))

        safeprint("modules:")
        for mod, modversion, modfile, modpath in moddata:
            safeprint("  {}:".format(mod))
            safeprint("    __version__: {}".format(modversion))
            safeprint("    __file__: {}".format(modfile))
            safeprint("    __path__: {}".format(modpath))
Exemplo n.º 6
0
def bookmark_show(bookmark_id_or_name):
    """
    Executor for `globus bookmark show`
    """
    client = get_client()
    res = resolve_id_or_name(client, bookmark_id_or_name)
    formatted_print(
        res,
        text_format=FORMAT_TEXT_RECORD,
        fields=(
            ("ID", "id"),
            ("Name", "name"),
            ("Endpoint ID", "endpoint_id"),
            ("Path", "path"),
        ),
        simple_text=(
            # standard output is endpoint:path format
            "{}:{}".format(res["endpoint_id"], res["path"])
            # verbose output includes all fields
            if not is_verbose() else None),
    )
Exemplo n.º 7
0
def print_version():
    """
    Print out the current version, and at least try to fetch the latest from
    PyPi to print alongside it.

    It may seem odd that this isn't in globus_cli.version , but it's done this
    way to separate concerns over printing the version from looking it up.
    """
    upgrade_target, latest, current = get_versions()
    if latest is None:
        click.echo(("Installed Version: {0}\nFailed to lookup latest version."
                    ).format(current))
    else:
        click.echo(
            _get_versionblock_message(current, latest, upgrade_target) +
            "\n\n" + _get_post_message(current, latest, upgrade_target))

    # verbose shows more platform and python info
    # it also includes versions of some CLI dependencies
    if is_verbose():
        moddata = _get_package_data()

        click.echo("\nVerbose Data\n---")

        click.echo("platform:")
        click.echo("  platform: {}".format(platform.platform()))
        click.echo("  py_implementation: {}".format(
            platform.python_implementation()))
        click.echo("  py_version: {}".format(platform.python_version()))
        click.echo("  sys.executable: {}".format(sys.executable))
        click.echo("  site.USER_BASE: {}".format(site.USER_BASE))

        click.echo("modules:")
        for mod, modversion, modfile, modpath in moddata:
            click.echo("  {}:".format(mod))
            click.echo("    __version__: {}".format(modversion))
            click.echo("    __file__: {}".format(modfile))
            click.echo("    __path__: {}".format(modpath))
Exemplo n.º 8
0
def bookmark_show(bookmark_id_or_name):
    """
    Executor for `globus bookmark show`
    """
    client = get_client()
    res = resolve_id_or_name(client, bookmark_id_or_name)
    formatted_print(
        res,
        text_format=FORMAT_TEXT_RECORD,
        fields=(
            ("ID", "id"),
            ("Name", "name"),
            ("Endpoint ID", "endpoint_id"),
            ("Path", "path"),
        ),
        simple_text=(
            # standard output is endpoint:path format
            "{}:{}".format(res["endpoint_id"], res["path"])
            # verbose output includes all fields
            if not is_verbose()
            else None
        ),
    )
Exemplo n.º 9
0
def ls_command(
    endpoint_plus_path,
    recursive_depth_limit,
    recursive,
    long_output,
    show_hidden,
    filter_val,
):
    """
    List the contents of a directory on an endpoint. If no path is given, the default
    directory on that endpoint will be used.

    If using text output files and directories are printed with one entry per line in
    alphabetical order.  Directories are always displayed with a trailing '/'.


    \b
    === Filtering

    --filter takes "filter patterns" subject to the following rules.

    \b
    Filter patterns must start with "=", "~", "!", or "!~"
    If none of these are given, "=" will be used

    \b
    "=" does exact matching
    "~" does regex matching, supporting globs (*)
    "!" does inverse "=" matching
    "!~" does inverse "~" matching

    \b
    "~*.txt" matches all .txt files, for example

    {AUTOMATIC_ACTIVATION}
    """
    endpoint_id, path = endpoint_plus_path

    # do autoactivation before the `ls` call so that recursive invocations
    # won't do this repeatedly, and won't have to instantiate new clients
    client = get_client()
    autoactivate(client, endpoint_id, if_expires_in=60)

    # create the query paramaters to send to operation_ls
    ls_params = {"show_hidden": int(show_hidden)}
    if path:
        ls_params["path"] = path
    if filter_val:
        # this char has special meaning in the LS API's filter clause
        # can't be part of the pattern (but we don't support globbing across
        # dir structures anyway)
        if "/" in filter_val:
            raise click.UsageError('--filter cannot contain "/"')
        # format into a simple filter clause which operates on filenames
        ls_params["filter"] = "name:{}".format(filter_val)

    # get the `ls` result
    if recursive:
        # NOTE:
        # --recursive and --filter have an interplay that some users may find
        # surprising
        # if we're asked to change or "improve" the behavior in the future, we
        # could do so with "type:dir" or "type:file" filters added in, and
        # potentially work out some viable behavior based on what people want
        res = client.recursive_operation_ls(endpoint_id,
                                            depth=recursive_depth_limit,
                                            **ls_params)
    else:
        res = client.operation_ls(endpoint_id, **ls_params)

    def cleaned_item_name(item):
        return item["name"] + ("/" if item["type"] == "dir" else "")

    # and then print it, per formatting rules
    formatted_print(
        res,
        fields=[
            ("Permissions", "permissions"),
            ("User", "user"),
            ("Group", "group"),
            ("Size", "size"),
            ("Last Modified", "last_modified"),
            ("File Type", "type"),
            ("Filename", cleaned_item_name),
        ],
        simple_text=(None if long_output or is_verbose()
                     or not outformat_is_text() else "\n".join(
                         cleaned_item_name(x) for x in res)),
        json_converter=iterable_response_to_dict,
    )
Exemplo n.º 10
0
def get_identities_command(values):
    """
    Executor for `globus get-identities`
    """
    client = get_auth_client()

    resolved_values = [_try_b32_decode(v) or v for v in values]

    # since API doesn't accept mixed ids and usernames,
    # split input values into separate lists
    ids = []
    usernames = []
    for val in resolved_values:
        try:
            uuid.UUID(val)
            ids.append(val)
        except ValueError:
            usernames.append(val)

    # make two calls to get_identities with ids and usernames
    # then combine the calls into one response
    results = []
    if len(ids):
        results += client.get_identities(ids=ids)["identities"]
    if len(usernames):
        results += client.get_identities(usernames=usernames)["identities"]
    res = GlobusResponse({"identities": results})

    def _custom_text_format(identities):
        """
        Non-verbose text output is customized
        """

        def resolve_identity(value):
            """
            helper to deal with variable inputs and uncertain response order
            """
            for identity in identities:
                if identity["id"] == value:
                    return identity["username"]
                if identity["username"] == value:
                    return identity["id"]
            return "NO_SUCH_IDENTITY"

        # standard output is one resolved identity per line in the same order
        # as the inputs. A resolved identity is either a username if given a
        # UUID vice versa, or "NO_SUCH_IDENTITY" if the identity could not be
        # found
        for val in resolved_values:
            safeprint(resolve_identity(val))

    formatted_print(
        res,
        response_key="identities",
        fields=[
            ("ID", "id"),
            ("Username", "username"),
            ("Full Name", "name"),
            ("Organization", "organization"),
            ("Email Address", "email"),
        ],
        # verbose output is a table. Order not guaranteed, may contain
        # duplicates
        text_format=(FORMAT_TEXT_TABLE if is_verbose() else _custom_text_format),
    )
Exemplo n.º 11
0
def ls_command(
    endpoint_plus_path,
    recursive_depth_limit,
    recursive,
    long_output,
    show_hidden,
    filter_val,
):
    """
    Executor for `globus ls`
    """
    endpoint_id, path = endpoint_plus_path

    # do autoactivation before the `ls` call so that recursive invocations
    # won't do this repeatedly, and won't have to instantiate new clients
    client = get_client()
    autoactivate(client, endpoint_id, if_expires_in=60)

    # create the query paramaters to send to operation_ls
    ls_params = {"show_hidden": int(show_hidden)}
    if path:
        ls_params["path"] = path
    if filter_val:
        # this char has special meaning in the LS API's filter clause
        # can't be part of the pattern (but we don't support globbing across
        # dir structures anyway)
        if "/" in filter_val:
            raise click.UsageError('--filter cannot contain "/"')
        # format into a simple filter clause which operates on filenames
        ls_params["filter"] = "name:{}".format(filter_val)

    # get the `ls` result
    if recursive:
        # NOTE:
        # --recursive and --filter have an interplay that some users may find
        # surprising
        # if we're asked to change or "improve" the behavior in the future, we
        # could do so with "type:dir" or "type:file" filters added in, and
        # potentially work out some viable behavior based on what people want
        res = client.recursive_operation_ls(
            endpoint_id, depth=recursive_depth_limit, **ls_params
        )
    else:
        res = client.operation_ls(endpoint_id, **ls_params)

    def cleaned_item_name(item):
        return item["name"] + ("/" if item["type"] == "dir" else "")

    # and then print it, per formatting rules
    formatted_print(
        res,
        fields=[
            ("Permissions", "permissions"),
            ("User", "user"),
            ("Group", "group"),
            ("Size", "size"),
            ("Last Modified", "last_modified"),
            ("File Type", "type"),
            ("Filename", cleaned_item_name),
        ],
        simple_text=(
            None
            if long_output or is_verbose() or not outformat_is_text()
            else "\n".join(cleaned_item_name(x) for x in res)
        ),
        json_converter=iterable_response_to_dict,
    )
Exemplo n.º 12
0
def get_identities_command(values):
    """
    Executor for `globus get-identities`
    """
    client = get_auth_client()

    resolved_values = [_try_b32_decode(v) or v for v in values]

    # since API doesn't accept mixed ids and usernames,
    # split input values into separate lists
    ids = []
    usernames = []
    for val in resolved_values:
        try:
            uuid.UUID(val)
            ids.append(val)
        except ValueError:
            usernames.append(val)

    # make two calls to get_identities with ids and usernames
    # then combine the calls into one response
    results = []
    if len(ids):
        results += client.get_identities(ids=ids)["identities"]
    if len(usernames):
        results += client.get_identities(usernames=usernames)["identities"]
    res = GlobusResponse({"identities": results})

    def _custom_text_format(identities):
        """
        Non-verbose text output is customized
        """
        def resolve_identity(value):
            """
            helper to deal with variable inputs and uncertain response order
            """
            for identity in identities:
                if identity["id"] == value:
                    return identity["username"]
                if identity["username"] == value:
                    return identity["id"]
            return "NO_SUCH_IDENTITY"

        # standard output is one resolved identity per line in the same order
        # as the inputs. A resolved identity is either a username if given a
        # UUID vice versa, or "NO_SUCH_IDENTITY" if the identity could not be
        # found
        for val in resolved_values:
            click.echo(resolve_identity(val))

    formatted_print(
        res,
        response_key="identities",
        fields=[
            ("ID", "id"),
            ("Username", "username"),
            ("Full Name", "name"),
            ("Organization", "organization"),
            ("Email Address", "email"),
        ],
        # verbose output is a table. Order not guaranteed, may contain
        # duplicates
        text_format=(FORMAT_TEXT_TABLE
                     if is_verbose() else _custom_text_format),
    )
Exemplo n.º 13
0
def get_identities_command(values, provision):
    """
    Lookup Globus Auth Identities given one or more uuids
    and/or usernames.

    Default output resolves each UUID to a username and each username to a UUID,
    with one output per line in the same order as the inputs.
    If a particular input had no corresponding identity in Globus Auth,
    "NO_SUCH_IDENTITY" is printed instead.

    If more fields are desired, --verbose will give tabular output, but does not
    guarantee order and ignores inputs with no corresponding Globus Auth identity.
    """
    client = get_auth_client()

    resolved_values = [_try_b32_decode(v) or v for v in values]

    # since API doesn't accept mixed ids and usernames,
    # split input values into separate lists
    ids = []
    usernames = []
    for val in resolved_values:
        try:
            uuid.UUID(val)
            ids.append(val)
        except ValueError:
            usernames.append(val)

    # make two calls to get_identities with ids and usernames
    # then combine the calls into one response
    results = []
    if len(ids):
        results += client.get_identities(ids=ids,
                                         provision=provision)["identities"]
    if len(usernames):
        results += client.get_identities(usernames=usernames,
                                         provision=provision)["identities"]
    res = GlobusResponse({"identities": results})

    def _custom_text_format(identities):
        """
        Non-verbose text output is customized
        """
        def resolve_identity(value):
            """
            helper to deal with variable inputs and uncertain response order
            """
            for identity in identities:
                if identity["id"] == value:
                    return identity["username"]
                if identity["username"] == value:
                    return identity["id"]
            return "NO_SUCH_IDENTITY"

        # standard output is one resolved identity per line in the same order
        # as the inputs. A resolved identity is either a username if given a
        # UUID vice versa, or "NO_SUCH_IDENTITY" if the identity could not be
        # found
        for val in resolved_values:
            click.echo(resolve_identity(val))

    formatted_print(
        res,
        response_key="identities",
        fields=[
            ("ID", "id"),
            ("Username", "username"),
            ("Full Name", "name"),
            ("Organization", "organization"),
            ("Email Address", "email"),
        ],
        # verbose output is a table. Order not guaranteed, may contain
        # duplicates
        text_format=(FORMAT_TEXT_TABLE
                     if is_verbose() else _custom_text_format),
    )
Exemplo n.º 14
0
def ls_command(
    endpoint_plus_path,
    recursive_depth_limit,
    recursive,
    long_output,
    show_hidden,
    filter_val,
):
    """
    Executor for `globus ls`
    """
    endpoint_id, path = endpoint_plus_path

    # do autoactivation before the `ls` call so that recursive invocations
    # won't do this repeatedly, and won't have to instantiate new clients
    client = get_client()
    autoactivate(client, endpoint_id, if_expires_in=60)

    # create the query paramaters to send to operation_ls
    ls_params = {"show_hidden": int(show_hidden)}
    if path:
        ls_params["path"] = path
    if filter_val:
        # this char has special meaning in the LS API's filter clause
        # can't be part of the pattern (but we don't support globbing across
        # dir structures anyway)
        if "/" in filter_val:
            raise click.UsageError('--filter cannot contain "/"')
        # format into a simple filter clause which operates on filenames
        ls_params["filter"] = "name:{}".format(filter_val)

    # get the `ls` result
    if recursive:
        # NOTE:
        # --recursive and --filter have an interplay that some users may find
        # surprising
        # if we're asked to change or "improve" the behavior in the future, we
        # could do so with "type:dir" or "type:file" filters added in, and
        # potentially work out some viable behavior based on what people want
        res = client.recursive_operation_ls(
            endpoint_id, depth=recursive_depth_limit, **ls_params
        )
    else:
        res = client.operation_ls(endpoint_id, **ls_params)

    def cleaned_item_name(item):
        return item["name"] + ("/" if item["type"] == "dir" else "")

    # and then print it, per formatting rules
    formatted_print(
        res,
        fields=[
            ("Permissions", "permissions"),
            ("User", "user"),
            ("Group", "group"),
            ("Size", "size"),
            ("Last Modified", "last_modified"),
            ("File Type", "type"),
            ("Filename", cleaned_item_name),
        ],
        simple_text=(
            None
            if long_output or is_verbose() or not outformat_is_text()
            else "\n".join(cleaned_item_name(x) for x in res)
        ),
        json_converter=iterable_response_to_dict,
    )