1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
6 # http://www.apache.org/licenses/LICENSE-2.0
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
14 """Implementation of low level functionality used in communication with
17 Exception HoneycombError is used in all methods and in all modules with
20 Class HoneycombUtil implements methods used by Honeycomb keywords. They must not
21 be used directly in tests. Use keywords implemented in the module
22 HoneycombAPIKeywords instead.
25 from json import loads
27 from robot.api import logger
29 from resources.libraries.python.HTTPRequest import HTTPRequest
30 from resources.libraries.python.constants import Constants as Const
33 class HoneycombError(Exception):
35 """Exception(s) raised by methods working with Honeycomb.
37 When raising this exception, put this information to the message in this
39 - short description of the encountered problem (parameter msg),
40 - relevant messages if there are any collected, e.g., from caught
41 exception (optional parameter details),
42 - relevant data if there are any collected (optional parameter details).
43 The logging is performed on two levels: 1. error - short description of the
44 problem; 2. debug - detailed information.
47 def __init__(self, msg, details='', enable_logging=True):
48 """Sets the exception message and enables / disables logging.
50 It is not wanted to log errors when using these keywords together
51 with keywords like "Wait until keyword succeeds". So you can disable
52 logging by setting enable_logging to False.
54 :param msg: Message to be displayed and logged
55 :param enable_logging: When True, logging is enabled, otherwise
58 :type enable_logging: bool
60 super(HoneycombError, self).__init__()
61 self._msg = "{0}: {1}".format(self.__class__.__name__, msg)
62 self._details = details
64 logger.error(self._msg)
65 logger.debug(self._details)
68 return repr(self._msg)
74 class HoneycombUtil(object):
75 """Implements low level functionality used in communication with Honeycomb.
77 There are implemented methods to get, put and delete data to/from Honeycomb.
78 They are based on functionality implemented in the module HTTPRequests which
79 uses HTTP requests GET, PUT, POST and DELETE to communicate with Honeycomb.
81 It is possible to PUT the data represented as XML or JSON structures or as
83 Data received in the response of GET are always represented as a JSON
86 There are also two supportive methods implemented:
87 - read_path_from_url_file which reads URL file and returns a path (see
88 docs/honeycomb_url_files.rst).
89 - parse_json_response which parses data from response in JSON representation
90 according to given path.
97 def read_path_from_url_file(url_file):
98 """Read path from *.url file.
100 For more information about *.url file see docs/honeycomb_url_files.rst
101 :param url_file: URL file. The argument contains only the name of file
102 without extension, not the full path.
104 :return: Requested path.
108 url_file = "{0}/{1}.url".format(Const.RESOURCES_TPL_HC, url_file)
109 with open(url_file) as template:
110 path = template.readline()
114 def parse_json_response(response, path=None):
115 """Parse data from response string in JSON format according to given
118 :param response: JSON formatted string.
119 :param path: Path to navigate down the data structure.
120 :type response: string
122 :return: JSON dictionary/list tree.
125 data = loads(response)
128 data = HoneycombUtil._parse_json_tree(data, path)
129 if not isinstance(data, list):
135 def _parse_json_tree(data, path):
136 """Retrieve data addressed by path from python representation of JSON
139 :param data: Parsed JSON dictionary tree.
140 :param path: Path to navigate down the dictionary tree.
143 :return: Data from specified path.
144 :rtype: list, dict or str
149 if isinstance(data, dict):
152 elif isinstance(data, list):
155 result.append(HoneycombUtil._parse_json_tree(item,
161 def get_honeycomb_data(node, url_file):
162 """Retrieve data from Honeycomb according to given URL.
164 :param node: Honeycomb node.
165 :param url_file: URL file. The argument contains only the name of file
166 without extension, not the full path.
169 :return: Requested information.
173 path = HoneycombUtil.read_path_from_url_file(url_file)
174 status_code, resp = HTTPRequest.get(node, path)
175 return status_code, resp
178 def put_honeycomb_data(node, url_file, data, data_representation='json'):
179 """Send configuration data using PUT request and return the status code
182 :param node: Honeycomb node.
183 :param url_file: URL file. The argument contains only the name of file
184 without extension, not the full path.
185 :param data: Configuration data to be sent to Honeycomb.
186 :param data_representation: How the data is represented. Supported types
187 of representation are: json, xml and txt.
191 :type data_representation: str
192 :return: Status code and content of response.
197 {"Content-Type": "application/json",
198 'Accept': 'text/plain'},
200 {"Content-Type": "application/xml",
201 'Accept': 'text/plain'},
203 {"Content-Type": "text/plain",
204 'Accept': 'text/plain'}
207 header = headers[data_representation]
208 except KeyError as err:
209 raise HoneycombError("Wrong data type: {0}.".
210 format(data_representation), repr(err))
212 path = HoneycombUtil.read_path_from_url_file(url_file)
213 status_code, resp = HTTPRequest.put(node=node, path=path,
214 headers=header, payload=data)
215 return status_code, resp
218 def delete_honeycomb_data(node, url_file):
219 """Delete data from Honeycomb according to given URL.
221 :param node: Honeycomb node.
222 :param url_file: URL file. The argument contains only the name of file
223 without extension, not the full path.
226 :return: Status code and response.
230 path = HoneycombUtil.read_path_from_url_file(url_file)
231 return HTTPRequest.delete(node, path)