From 29247d8726d337f7192e8cde75f2017f45ccbf25 Mon Sep 17 00:00:00 2001 From: Paul Larson Date: Mon, 29 Jul 2024 08:01:30 -0500 Subject: [PATCH] Exit when we know we're unable to get the list of queues from the server (#312) * Exit when we know we're unable to get the list of queues from the server * Fix up some SystemExit -> sys.exit() things * Add unit tests --- cli/testflinger_cli/__init__.py | 101 +++++++++++++------------- cli/testflinger_cli/tests/test_cli.py | 22 ++++++ 2 files changed, 74 insertions(+), 49 deletions(-) diff --git a/cli/testflinger_cli/__init__.py b/cli/testflinger_cli/__init__.py index 8dc405b5..b334bc25 100644 --- a/cli/testflinger_cli/__init__.py +++ b/cli/testflinger_cli/__init__.py @@ -51,8 +51,8 @@ def cli(): tfcli = TestflingerCli() configure_logging() tfcli.run() - except KeyboardInterrupt as exc: - raise SystemExit from exc + except KeyboardInterrupt: + sys.exit("Received KeyboardInterrupt") def configure_logging(): @@ -157,7 +157,7 @@ def __init__(self): ): return if not server.startswith(("http://", "https://")): - raise SystemExit( + sys.exit( 'Server must start with "http://" or "https://" ' '- currently set to: "{}"'.format(server) ) @@ -167,7 +167,7 @@ def __init__(self): def run(self): """Run the subcommand specified in command line arguments""" if hasattr(self.args, "func"): - raise SystemExit(self.args.func()) + sys.exit(self.args.func()) print(self.help) def get_args(self): @@ -286,22 +286,22 @@ def cancel(self, job_id=None): if not job_id: try: job_id = self.args.job_id - except AttributeError as exc: - raise SystemExit("No job id specified to cancel.") from exc + except AttributeError: + sys.exit("No job id specified to cancel.") try: self.client.put(f"/v1/job/{job_id}/action", {"action": "cancel"}) self.history.update(job_id, "cancelled") except client.HTTPError as exc: if exc.status == 400: - raise SystemExit( + sys.exit( "Invalid job ID specified or the job is already " "completed/cancelled." - ) from exc + ) if exc.status == 404: - raise SystemExit( + sys.exit( "Received 404 error from server. Are you " "sure this is a testflinger server?" - ) from exc + ) raise def configure(self): @@ -488,22 +488,23 @@ def show(self): results = self.client.show_job(self.args.job_id) except client.HTTPError as exc: if exc.status == 204: - raise SystemExit("No data found for that job id.") from exc + sys.exit("No data found for that job id.") if exc.status == 400: - raise SystemExit( + sys.exit( "Invalid job id specified. Check the job id " "to be sure it is correct" - ) from exc + ) if exc.status == 404: - raise SystemExit( + sys.exit( "Received 404 error from server. Are you " "sure this is a testflinger server?" - ) from exc + ) # This shouldn't happen, so let's get more information - raise SystemExit( - "Unexpected error status from testflinger " - "server: {}".format(exc.status) - ) from exc + logger.error( + "Unexpected error status from testflinger server: %s", + exc.status, + ) + sys.exit(1) print(json.dumps(results, sort_keys=True, indent=4)) def results(self): @@ -512,22 +513,23 @@ def results(self): results = self.client.get_results(self.args.job_id) except client.HTTPError as exc: if exc.status == 204: - raise SystemExit("No results found for that job id.") from exc + sys.exit("No results found for that job id.") if exc.status == 400: - raise SystemExit( + sys.exit( "Invalid job id specified. Check the job id " "to be sure it is correct" - ) from exc + ) if exc.status == 404: - raise SystemExit( + sys.exit( "Received 404 error from server. Are you " "sure this is a testflinger server?" - ) from exc + ) # This shouldn't happen, so let's get more information - raise SystemExit( - "Unexpected error status from testflinger " - "server: {}".format(exc.status) - ) from exc + logger.error( + "Unexpected error status from testflinger server: %s", + exc.status, + ) + sys.exit(1) print(json.dumps(results, sort_keys=True, indent=4)) @@ -538,24 +540,23 @@ def artifacts(self): self.client.get_artifact(self.args.job_id, self.args.filename) except client.HTTPError as exc: if exc.status == 204: - raise SystemExit( - "No artifacts tarball found for that job id." - ) from exc + sys.exit("No artifacts tarball found for that job id.") if exc.status == 400: - raise SystemExit( + sys.exit( "Invalid job id specified. Check the job id " "to be sure it is correct" - ) from exc + ) if exc.status == 404: - raise SystemExit( + sys.exit( "Received 404 error from server. Are you " "sure this is a testflinger server?" - ) from exc + ) # This shouldn't happen, so let's get more information - raise SystemExit( - "Unexpected error status from testflinger " - "server: {}".format(exc.status) - ) from exc + logger.error( + "Unexpected error status from testflinger server: %s", + exc.status, + ) + sys.exit(1) print("Artifacts downloaded to {}".format(self.args.filename)) def poll(self): @@ -655,10 +656,12 @@ def list_queues(self): queues = self.client.get_queues() except client.HTTPError as exc: if exc.status == 404: - raise SystemExit( + sys.exit( "Received 404 error from server. Are you " "sure this is a testflinger server?" - ) from exc + ) + logger.error("Unable to get a list of queues from the server.") + sys.exit(1) print("Advertised queues on this server:") for name, description in sorted(queues.items()): print(" {} - {}".format(name, description)) @@ -687,7 +690,7 @@ def reserve(self): not image.startswith(("http://", "https://")) and image not in images.keys() ): - raise SystemExit( + sys.exit( "ERROR: '{}' is not in the list of known " "images for that queue, please select " "another.".format(image) @@ -699,7 +702,7 @@ def reserve(self): ssh_keys = self.args.key or _get_ssh_keys() for ssh_key in ssh_keys: if not ssh_key.startswith("lp:") and not ssh_key.startswith("gh:"): - raise SystemExit( + sys.exit( "Please enter keys in the form lp:userid or gh:userid" ) template = inspect.cleandoc( @@ -769,20 +772,20 @@ def get_job_state(self, job_id): return self.client.get_status(job_id) except client.HTTPError as exc: if exc.status == 204: - raise SystemExit( + sys.exit( "No data found for that job id. Check the " "job id to be sure it is correct" - ) from exc + ) if exc.status == 400: - raise SystemExit( + sys.exit( "Invalid job id specified. Check the job id " "to be sure it is correct" - ) from exc + ) if exc.status == 404: - raise SystemExit( + sys.exit( "Received 404 error from server. Are you " "sure this is a testflinger server?" - ) from exc + ) except (IOError, ValueError): # For other types of network errors, or JSONDecodeError if we got # a bad return from get_status() diff --git a/cli/testflinger_cli/tests/test_cli.py b/cli/testflinger_cli/tests/test_cli.py index ff03ea32..95ed21fc 100644 --- a/cli/testflinger_cli/tests/test_cli.py +++ b/cli/testflinger_cli/tests/test_cli.py @@ -338,3 +338,25 @@ def test_results(capsys, requests_mock): tfcli.results() std = capsys.readouterr() assert "completed" in std.out + + +def test_list_queues(capsys, requests_mock): + """list_queues should report queues""" + fake_return = {"queue1": "description1", "queue2": "description2"} + requests_mock.get(URL + "/v1/agents/queues", json=fake_return) + sys.argv = ["", "list-queues"] + tfcli = testflinger_cli.TestflingerCli() + tfcli.list_queues() + std = capsys.readouterr() + assert "queue1 - description1" in std.out + assert "queue2 - description2" in std.out + + +def test_list_queues_connection_error(caplog, requests_mock): + """list_queues should report queues""" + requests_mock.get(URL + "/v1/agents/queues", status_code=400) + sys.argv = ["", "list-queues"] + tfcli = testflinger_cli.TestflingerCli() + with pytest.raises(SystemExit): + tfcli.list_queues() + assert "Unable to get a list of queues from the server." in caplog.text