osc-placement/osc_placement/http.py
Chris Dent fc563d37bc Update tox and tests to work with modern setups
While trying to make some changes I discovered that the tox
configuration for osc-placement was rather out of date and
functional tests were not working for python3. With this
change we bring tox.ini into a style that is more in keeping
with modern standards, use stestr, and update some functional
tests so they work with python3.

The functional tests changes are either:

* to fix the decoding of response
* to adapt argparse error response checking between python
  version.

These changes cascade some required change into how the gate-side
functional testing is performed. We make it explicit that in the
python2 job, the 'functional' tox job is run. When the python3
job is run, 'functional-py3' is run. Also stestr replaces
testr in the post-test hook.

When the functional-py3 test had been run in the past it
was actually running a python2 osc-placement against a
python3 devstack. We change that here to be python3 and
python3. Once that was happening, additional failures
were revealed, now fixed.

One particular issue was that while the json module
for python 3.6 and greater will decode strings or bytes,
the version of 3.5 will only do strings. We switch
to using simplejson throughout which smooths things over.
This is added as a new requirement but it isn't really:
simplejson is required by osc-lib.

Finally, some requirements need to be tuned to pass the
gate requirements job.

Change-Id: I999a3103dd85c0a437785766eef533875fca31fc
2019-03-01 04:12:18 +00:00

61 lines
2.1 KiB
Python

# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import contextlib
import keystoneauth1.exceptions.http as ks_exceptions
import osc_lib.exceptions as exceptions
import simplejson as json
import six
_http_error_to_exc = {
cls.http_status: cls
for cls in exceptions.ClientException.__subclasses__()
}
@contextlib.contextmanager
def _wrap_http_exceptions():
"""Reraise osc-lib exceptions with detailed messages."""
try:
yield
except ks_exceptions.HttpError as exc:
detail = json.loads(exc.response.content)['errors'][0]['detail']
msg = detail.split('\n')[-1].strip()
exc_class = _http_error_to_exc.get(exc.http_status,
exceptions.CommandError)
six.raise_from(exc_class(exc.http_status, msg), exc)
class SessionClient(object):
def __init__(self, session, ks_filter, api_version='1.0'):
self.session = session
self.ks_filter = ks_filter
self.api_version = api_version
def request(self, method, url, **kwargs):
version = kwargs.pop('version', None)
api_version = (self.ks_filter['service_type'] + ' ' +
(version or self.api_version))
headers = kwargs.pop('headers', {})
headers.setdefault('OpenStack-API-Version', api_version)
headers.setdefault('Accept', 'application/json')
with _wrap_http_exceptions():
return self.session.request(url, method,
headers=headers,
endpoint_filter=self.ks_filter,
**kwargs)