From e405b5a3b5d69b88738377957527b2f6253d0ce5 Mon Sep 17 00:00:00 2001 From: Sujen Shah Date: Fri, 16 Oct 2026 16:23:58 -0700 Subject: [PATCH] fix: never emit an empty MAAP_PGT from get_maap_pgt_token Fail with exit 78 and _alt_error.txt when _job.json has no username or the API returns an empty/non-string session_key, instead of printing nothing (or an empty token) and letting the container start. Refs #9 Claude-Session: https://claude.ai/code/session_0171HvL7yCdP2wCuxh7UngYP --- get_maap_pgt_token.py | 26 ++++++++++++++++---------- tests/test_get_maap_pgt_token.py | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/get_maap_pgt_token.py b/get_maap_pgt_token.py index cd06f94..6334ea8 100644 --- a/get_maap_pgt_token.py +++ b/get_maap_pgt_token.py @@ -65,11 +65,16 @@ def get_maap_pgt_token(username, maap_api_host=None): ) from e try: - return response.json()["session_key"] + token = response.json()["session_key"] except (ValueError, KeyError, TypeError) as e: raise PgtTokenError( f"Response from {url} for user '{username}' has no usable 'session_key'" ) from e + if not isinstance(token, str) or not token.strip(): + raise PgtTokenError( + f"Response from {url} for user '{username}' has an empty 'session_key'" + ) + return token def report_failure(error, job_dir="."): @@ -87,12 +92,13 @@ def report_failure(error, job_dir="."): if __name__ == '__main__': with open("_job.json") as fr: job = json.loads(fr.read()) - username = job.get("username") - if username: - try: - maap_pgt_token = get_maap_pgt_token(username) - print(maap_pgt_token) - except PgtTokenError as e: - # stdout is captured into MAAP_PGT by dps_wrapper.sh, so report on stderr - report_failure(e) - sys.exit(EXIT_CODE_PGT_FAILURE) + username = job.get("username") + try: + if not username: + # an empty MAAP_PGT would only surface later as a 401 in the user's code + raise PgtTokenError("no 'username' in _job.json, cannot request a MAAP_PGT") + print(get_maap_pgt_token(username)) + except PgtTokenError as e: + # stdout is captured into MAAP_PGT by dps_wrapper.sh, so report on stderr + report_failure(e) + sys.exit(EXIT_CODE_PGT_FAILURE) diff --git a/tests/test_get_maap_pgt_token.py b/tests/test_get_maap_pgt_token.py index a20ef1b..52aab74 100644 --- a/tests/test_get_maap_pgt_token.py +++ b/tests/test_get_maap_pgt_token.py @@ -145,6 +145,13 @@ def test_non_json_body_gives_clear_error(): get_maap_pgt_token("alice") +@pytest.mark.parametrize("key", ["", " ", None, 123]) +def test_empty_or_non_string_session_key_gives_clear_error(key): + with _mock_session(MagicMock(return_value=_resp(200, {"session_key": key}))): + with pytest.raises(PgtTokenError, match="empty 'session_key'"): + get_maap_pgt_token("alice") + + # --- failure reporting to HySDS --- def test_report_failure_writes_stderr_and_alt_error(tmp_path, capsys): @@ -169,3 +176,14 @@ def test_main_exits_with_custom_code_and_keeps_stdout_clean(tmp_path): assert r.stdout == "" assert "Unable to get user MAAP_PGT token" in r.stderr assert (tmp_path / "_alt_error.txt").exists() + + +def test_main_without_username_fails_instead_of_printing_empty_token(tmp_path): + (tmp_path / "_job.json").write_text(json.dumps({})) + r = subprocess.run( + [sys.executable, mod.__file__], cwd=tmp_path, capture_output=True, text=True, + env={"PATH": ""}, + ) + assert r.returncode == mod.EXIT_CODE_PGT_FAILURE, r.stderr + assert r.stdout == "" + assert "username" in (tmp_path / "_alt_error.txt").read_text()