summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNishant Kumar <nk613n@att.com>2018-12-10 19:11:57 +0000
committerNishant Kumar <nk613n@att.com>2019-01-03 20:31:30 +0000
commit30950202b323a49d21170941f5e46ab6077da5e9 (patch)
tree601d8a5d4a3ff881a5b7076cb2b58461ca6e142f
parenta235f8e6db6e791550727e3575e045e26f177252 (diff)
Raise specific errors during create configdocs
Currently shipyard raises same error for 2 scenarios- - Collection empty or resulted in no revision (Error code - 400) - Buffer is either not empty or the collection already exists in buffer (Error code - 409) This PS enables shipyard to raise specific errors for the above given scenarios which would equip consumers of Shipyard API client to handle the exception gracefully. Change-Id: I10860ca60f4fde4088cbb146283a2db305418320
Notes
Notes (review): Code-Review+2: Bryan Strassner <strassner.bryan@gmail.com> Code-Review+1: Evgeniy L <eli@mirantis.com> Code-Review+2: Aaron Sheffield <ajs@sheffieldfamily.net> Workflow+1: Aaron Sheffield <ajs@sheffieldfamily.net> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Tue, 22 Jan 2019 20:04:51 +0000 Reviewed-on: https://review.openstack.org/624178 Project: openstack/airship-shipyard Branch: refs/heads/master
-rw-r--r--src/bin/shipyard_client/shipyard_client/api_client/base_client.py6
-rw-r--r--src/bin/shipyard_client/shipyard_client/api_client/client_error.py8
-rw-r--r--src/bin/shipyard_client/shipyard_client/cli/action.py6
-rw-r--r--src/bin/shipyard_client/shipyard_client/cli/format_utils.py94
4 files changed, 77 insertions, 37 deletions
diff --git a/src/bin/shipyard_client/shipyard_client/api_client/base_client.py b/src/bin/shipyard_client/shipyard_client/api_client/base_client.py
index 6857095..6f08b3f 100644
--- a/src/bin/shipyard_client/shipyard_client/api_client/base_client.py
+++ b/src/bin/shipyard_client/shipyard_client/api_client/base_client.py
@@ -23,6 +23,8 @@ import requests
23from shipyard_client.api_client.client_error import ClientError 23from shipyard_client.api_client.client_error import ClientError
24from shipyard_client.api_client.client_error import UnauthenticatedClientError 24from shipyard_client.api_client.client_error import UnauthenticatedClientError
25from shipyard_client.api_client.client_error import UnauthorizedClientError 25from shipyard_client.api_client.client_error import UnauthorizedClientError
26from shipyard_client.api_client.client_error import ShipyardBufferError
27from shipyard_client.api_client.client_error import InvalidCollectionError
26 28
27 29
28class BaseClient(metaclass=abc.ABCMeta): 30class BaseClient(metaclass=abc.ABCMeta):
@@ -99,6 +101,10 @@ class BaseClient(metaclass=abc.ABCMeta):
99 raise UnauthenticatedClientError() 101 raise UnauthenticatedClientError()
100 if response.status_code == 403: 102 if response.status_code == 403:
101 raise UnauthorizedClientError() 103 raise UnauthorizedClientError()
104 if response.status_code == 400:
105 raise InvalidCollectionError(response.text)
106 if response.status_code == 409:
107 raise ShipyardBufferError(response.text)
102 return response 108 return response
103 except requests.exceptions.RequestException as e: 109 except requests.exceptions.RequestException as e:
104 self.error(str(e)) 110 self.error(str(e))
diff --git a/src/bin/shipyard_client/shipyard_client/api_client/client_error.py b/src/bin/shipyard_client/shipyard_client/api_client/client_error.py
index f6af742..19707d6 100644
--- a/src/bin/shipyard_client/shipyard_client/api_client/client_error.py
+++ b/src/bin/shipyard_client/shipyard_client/api_client/client_error.py
@@ -23,3 +23,11 @@ class UnauthorizedClientError(ClientError):
23 23
24class UnauthenticatedClientError(ClientError): 24class UnauthenticatedClientError(ClientError):
25 pass 25 pass
26
27
28class ShipyardBufferError(ClientError):
29 pass
30
31
32class InvalidCollectionError(ClientError):
33 pass
diff --git a/src/bin/shipyard_client/shipyard_client/cli/action.py b/src/bin/shipyard_client/shipyard_client/cli/action.py
index b5884bd..bc96b8a 100644
--- a/src/bin/shipyard_client/shipyard_client/cli/action.py
+++ b/src/bin/shipyard_client/shipyard_client/cli/action.py
@@ -19,6 +19,8 @@ import logging
19from shipyard_client.api_client.client_error import ClientError 19from shipyard_client.api_client.client_error import ClientError
20from shipyard_client.api_client.client_error import UnauthenticatedClientError 20from shipyard_client.api_client.client_error import UnauthenticatedClientError
21from shipyard_client.api_client.client_error import UnauthorizedClientError 21from shipyard_client.api_client.client_error import UnauthorizedClientError
22from shipyard_client.api_client.client_error import ShipyardBufferError
23from shipyard_client.api_client.client_error import InvalidCollectionError
22from shipyard_client.api_client.shipyard_api_client import ShipyardClient 24from shipyard_client.api_client.shipyard_api_client import ShipyardClient
23from shipyard_client.api_client.shipyardclient_context import \ 25from shipyard_client.api_client.shipyardclient_context import \
24 ShipyardClientContext 26 ShipyardClientContext
@@ -134,6 +136,10 @@ class CliAction(AbstractCliAction):
134 "Check credential values") 136 "Check credential values")
135 except UnauthorizedClientError: 137 except UnauthorizedClientError:
136 self.resp_txt = "Error: Unauthorized to perform this action." 138 self.resp_txt = "Error: Unauthorized to perform this action."
139 except ShipyardBufferError as ex:
140 self.resp_txt = format_utils.cli_format_exception_handler(ex)
141 except InvalidCollectionError as ex:
142 self.resp_txt = format_utils.cli_format_exception_handler(ex)
137 except ClientError as ex: 143 except ClientError as ex:
138 self.resp_txt = "Error: Client Error: {}".format(str(ex)) 144 self.resp_txt = "Error: Client Error: {}".format(str(ex))
139 except Exception as ex: 145 except Exception as ex:
diff --git a/src/bin/shipyard_client/shipyard_client/cli/format_utils.py b/src/bin/shipyard_client/shipyard_client/cli/format_utils.py
index 5ab1c9c..0568238 100644
--- a/src/bin/shipyard_client/shipyard_client/cli/format_utils.py
+++ b/src/bin/shipyard_client/shipyard_client/cli/format_utils.py
@@ -47,11 +47,7 @@ def cli_format_status_handler(response, is_error=False):
47 standard error format 47 standard error format
48 :is_error: toggles the use of status or error verbiage 48 :is_error: toggles the use of status or error verbiage
49 :returns: a generically formatted error response formulated from the 49 :returns: a generically formatted error response formulated from the
50 client_repsonse. The response will be in the format: 50 client_repsonse.
51
52 [Error|Status]: {{message}}
53 Reason: {{Reason}}
54 Additional: {{details message list messages}}
55 ... 51 ...
56 """ 52 """
57 formatted = "Error: {}\nReason: {}" if is_error \ 53 formatted = "Error: {}\nReason: {}" if is_error \
@@ -59,44 +55,68 @@ def cli_format_status_handler(response, is_error=False):
59 try: 55 try:
60 if response.text: 56 if response.text:
61 resp_j = response.json() 57 resp_j = response.json()
62 resp = formatted.format(resp_j.get('message', 'Not specified'), 58 return cli_format_response(formatted, resp_j)
63 resp_j.get('reason', 'Not specified'))
64 # lvl_counts must have a matching number of values as the
65 # _LEVEL_KEYS below + 1 for sentinel.
66 lvl_counts = [0, 0, 0, 0]
67 if resp_j.get('details'):
68 mlist = resp_j['details'].get('messageList', [])
69 # Decorate messages with level number and sortkey
70 for message in mlist:
71 message['lnum'], message['sortkey'] = _lvl_key(
72 message.get('level'),
73 message.get('error', False)
74 )
75 # Sort and formulate the messages
76 for message in sorted(mlist, key=lambda m: m['sortkey']):
77 lnum = message['lnum']
78 lvl_counts[lnum] = lvl_counts[lnum] + 1
79 if message.get('kind') == 'ValidationMessage':
80 resp = resp + _format_validation_message(message)
81 else:
82 resp = resp + _format_basic_message(message)
83 if message.get('source'):
84 resp = resp + "\n{}Source: {}".format(
85 _INDENT,
86 message['source']
87 )
88 # Append a count summary
89 resp = resp + ("\n\n#### Errors: {},"
90 " Warnings: {},"
91 " Infos: {},"
92 " Other: {} ####".format(*lvl_counts))
93 return resp
94 else: 59 else:
95 return '' 60 return ''
96 except ValueError: 61 except ValueError:
97 return "Error: Unable to decode response. Value: {}".format( 62 return "Error: Unable to decode response. Value: {}".format(
98 response.text) 63 response.text)
99 64
65def cli_format_exception_handler(exc_msg):
66 """ Formatter for custom error raised by Shipyard """
67 try:
68 formatted = "Error: {}\nReason: {}"
69 # Convert exception message to dict from string
70 exc_dict = json.loads(str(exc_msg))
71 return cli_format_response(formatted, exc_dict)
72 except Exception:
73 return "Error: Unable to decode response. Value: {}".format(
74 exc_msg)
75
76def cli_format_response(formatted, response):
77 """ Handler for Shipyard status and error responses
78
79 :param formatted: structure to be used for response
80 :param response: client response to be formatted
81
82 The response will be in the format:
83 [Error|Status]: {{message}}
84 Reason: {{Reason}}
85 Additional: {{details message list messages}}
86 """
87 resp = formatted.format(response.get('message', 'Not specified'),
88 response.get('reason', 'Not specified'))
89 # lvl_counts must have a matching number of values as the
90 # _LEVEL_KEYS below + 1 for sentinel.
91 lvl_counts = [0, 0, 0, 0]
92 if response.get('details'):
93 mlist = response['details'].get('messageList', [])
94 # Decorate messages with level number and sortkey
95 for message in mlist:
96 message['lnum'], message['sortkey'] = _lvl_key(
97 message.get('level'),
98 message.get('error', False)
99 )
100 # Sort and formulate the messages
101 for message in sorted(mlist, key=lambda m: m['sortkey']):
102 lnum = message['lnum']
103 lvl_counts[lnum] = lvl_counts[lnum] + 1
104 if message.get('kind') == 'ValidationMessage':
105 resp = resp + _format_validation_message(message)
106 else:
107 resp = resp + _format_basic_message(message)
108 if message.get('source'):
109 resp = resp + "\n{}Source: {}".format(
110 _INDENT,
111 message['source']
112 )
113 # Append a count summary
114 resp = resp + ("\n\n#### Errors: {},"
115 " Warnings: {},"
116 " Infos: {},"
117 " Other: {} ####".format(*lvl_counts))
118 return resp
119
100 120
101# Map of levels by severity. Extra values are included in this map but valid 121# Map of levels by severity. Extra values are included in this map but valid
102# values are defined here: 122# values are defined here: