From 69df2db20b3c71ce32d68f109638158e55150079 Mon Sep 17 00:00:00 2001 From: Lei Wang Date: Mon, 23 Oct 2023 13:20:44 -0400 Subject: [PATCH] Add auth exception handling for expired token --- .../exception_handling.py | 19 +++++++++++++++ .../tests/unit/test_cli_behavior.py | 23 +++++++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/compute_endpoint/globus_compute_endpoint/exception_handling.py b/compute_endpoint/globus_compute_endpoint/exception_handling.py index 3c848a640..ea951de08 100644 --- a/compute_endpoint/globus_compute_endpoint/exception_handling.py +++ b/compute_endpoint/globus_compute_endpoint/exception_handling.py @@ -10,6 +10,7 @@ from __future__ import annotations import functools +import json import logging import os import sys @@ -86,6 +87,24 @@ def wrapper(*args, **kwargs): message: {e.text} """ ) + + # This specific Auth error has a common cause + if e.http_status == 400 and e.code == "Error": + try: + error_info = json.loads(e.text) + if "invalid_grant" == error_info.get("error"): + msg += ( + "\nYour Globus Compute credentials might have expired." + " You can clear them with `globus-compute-endpoint logout`" + " before retrying the command.\n" + "Note that Globus Connect (Transfer) credentials are managed " + " via the `globus` command, separately from the Globus " + " Compute ones." + ) + except Exception: + # Shouldn't get here unless Globus Auth changes its response + pass + log.warning(msg) click.echo(msg) sys.exit(os.EX_NOPERM) diff --git a/compute_endpoint/tests/unit/test_cli_behavior.py b/compute_endpoint/tests/unit/test_cli_behavior.py index 1515c6407..d854a9f38 100644 --- a/compute_endpoint/tests/unit/test_cli_behavior.py +++ b/compute_endpoint/tests/unit/test_cli_behavior.py @@ -666,9 +666,11 @@ def test_get_endpoint_by_name_or_uuid_error_message(run_line, data): @pytest.mark.parametrize( "data", [ - ("start", "start_endpoint"), - ("stop", "stop_endpoint"), - ("delete --yes", "delete_endpoint"), + ("start", "start_endpoint", '{"error":"invalid_grant"}'), + ("start", "start_endpoint", '{"error":"something else"}'), + ("start", "start_endpoint", ""), + ("stop", "stop_endpoint", "err_msg"), + ("delete --yes", "delete_endpoint", "err_msg"), ], ) def test_handle_globus_auth_error( @@ -679,15 +681,20 @@ def test_handle_globus_auth_error( ep_name, data: tuple[str, str], ): - cmd, ep_method = data + cmd, ep_method, auth_err_msg = data mock_ep, _ = mock_cli_state make_endpoint_dir() mock_log = mocker.patch("globus_compute_endpoint.exception_handling.log") + mock_resp = mock.MagicMock( + status_code=400, + reason="Bad Request", + text=auth_err_msg, + ) mocker.patch.object( mock_ep, ep_method, - side_effect=globus_sdk.AuthAPIError(r=mock.MagicMock(status_code=400)), + side_effect=globus_sdk.AuthAPIError(r=mock_resp), ) res = run_line(f"{cmd} {ep_name}", assert_exit_code=os.EX_NOPERM) @@ -699,3 +706,9 @@ def test_handle_globus_auth_error( assert err_msg in a[0] assert "400" in res.stdout assert "400" in a[0] + + additional_details = "You can clear them with" + if "invalid_grant" in auth_err_msg: + assert additional_details in res.stdout + else: + assert additional_details not in res.stdout