diff --git a/pylxd/exceptions.py b/pylxd/exceptions.py index 54c06822..8afb1656 100644 --- a/pylxd/exceptions.py +++ b/pylxd/exceptions.py @@ -17,7 +17,13 @@ def __init__(self, response): def __str__(self): if self.response.status_code == 200: # Operation failure try: - return self.response.json()["metadata"]["err"] + json_response = self.response.json() + metadata = json_response.get("metadata") + if metadata and isinstance(metadata, dict) and "err" in metadata: + return json_response["metadata"]["err"] + if "error" in json_response: + return json_response["error"] + return str(json_response) except (ValueError, KeyError): pass diff --git a/pylxd/models/tests/test_operation.py b/pylxd/models/tests/test_operation.py index 8c2d6b7c..fc794fe4 100644 --- a/pylxd/models/tests/test_operation.py +++ b/pylxd/models/tests/test_operation.py @@ -100,6 +100,29 @@ def error(request, context): self.assertRaises(exceptions.LXDAPIException, an_operation.wait) + def test_wait_with_error_async_without_metadata(self): + """If the operation errors, wait raises an exception.""" + + def error(request, context): + context.status_code = 200 + return {"type": "async", "error": "Could not proceed", "metadata": None} + + self.add_rule( + { + "json": error, + "method": "GET", + "url": r"^http://pylxd.test/1.0/operations/operation-abc/wait$", + } + ) + + name = "/1.0/operations/operation-abc" + + an_operation = models.Operation.get(self.client, name) + + with self.assertRaises(exceptions.LXDAPIException) as wait_cm: + an_operation.wait() + assert str(wait_cm.exception) == "Could not proceed" + def test_unknown_attribute(self): self.add_rule( {