Wahlstedt, Walter (ww229g) 70aa35a396 update to focal and python 3.8
update dockerfile for python deckhand install
add deckhand version to chart 1.0
add chart version 0.2.0
update all packages to latest in requirements.txt
update zuul jobs for focal and python 3.8
remove zuul job functional-uwsgi-py38 in favor of functional-docker-py38
update tox config
typecast to string in re.sub() function
add stestr to test-requirements.txt
add SQLAlchemy jsonpickle sphinx-rtd-theme stestr to requirements.txt
deprecated function: BarbicanException -> BarbicanClientException
fix mock import using unittest
fix import collections to collections.abc
fix for collections modules for older than python 3.10 versions.
deprecated function: json -> to_json
deprecated function:  werkzeug.contrib.profiler ->
    werkzeug.middleware.profiler
deprecated function: falcon.AIP -> falcon.App
deprecation warning: switch from resp.body to resp.text
rename fixtures to dh_fixtures because there is an imported module
    fixtures
switch from stream.read to bounded_stream.read
deprecated function: falcon process_response needed additional parameter
deprecated function: falcon default_exception_handler changed parameter
    order
move from MagicMock object to falcon test generated object to fix
    incompatability with upgraded Falcon module.
Adjust gabbi tests to fix incompatability with upgraded DeepDiff module
update Makefile to execute ubuntu_focal
update HTK (helmtoolkit)
unpin barbican to pass integration tests
Use helm 3 in chart build.
    `helm serve` is removed in helm 3 so this moves
    to using local `file://` dependencies [0] instead.

Change-Id: I180416f480edea1b8968d80c993b3e1fcc95c08d
2023-02-24 10:51:57 -05:00

106 lines
3.6 KiB
Python

# Copyright 2017 AT&T Intellectual Property. All other rights reserved.
#
# 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 falcon
from oslo_log import log as logging
import yaml
from deckhand import context
LOG = logging.getLogger(__name__)
class BaseResource(object):
"""Base resource class for implementing API resources."""
# Shadowing no_authentication_methods and supplying the HTTP method as a
# value (e.g. 'GET') allows that method to run without authentication. By
# default all require authentication.
# Warning: This method of skipping authentication is applied to a HTTP
# method, which ultimately maps to a resource's on_ methods.
# If a method such as on_get were to service both a list and a single
# response, both would share the skipped authentication.
no_authentication_methods = []
def on_options(self, req, resp):
self_attrs = dir(self)
methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH']
allowed_methods = []
for m in methods:
if 'on_' + m.lower() in self_attrs:
allowed_methods.append(m)
resp.headers['Allow'] = ','.join(allowed_methods)
resp.status = falcon.HTTP_200
def from_yaml(self, req, expect_list=True, allow_empty=False):
"""Reads and converts YAML-formatted request body into a dict or list
of dicts.
:param req: Falcon Request object.
:param expect_list: Whether to expect a list or an object.
:param allow_empty: Whether the request body can be empty.
:returns: List of dicts if ``expect_list`` is True or else a dict.
"""
raw_data = req.bounded_stream.read()
if not allow_empty and not raw_data:
error_msg = ("The request body must not be empty.")
LOG.error(error_msg)
raise falcon.HTTPBadRequest(description=error_msg)
try:
if expect_list:
data = list(yaml.safe_load_all(raw_data))
else:
data = yaml.safe_load(raw_data)
except yaml.YAMLError as e:
error_msg = ("The request body must be properly formatted YAML. "
"Details: %s." % e)
LOG.error(error_msg)
raise falcon.HTTPBadRequest(description=error_msg)
if expect_list:
bad_entries = [str(i + 1) for i, x in enumerate(data)
if not x or not isinstance(x, dict)]
if bad_entries:
error_msg = (
"Expected a list of valid objects. Invalid entries "
"found at following indexes: %s." % ','.join(bad_entries))
LOG.error(error_msg)
raise falcon.HTTPBadRequest(description=error_msg)
return data
class DeckhandRequest(falcon.Request):
context_type = context.RequestContext
@property
def project_id(self):
return self.context.tenant
@property
def user_id(self):
return self.context.user
@property
def roles(self):
return self.context.roles
def __repr__(self):
return '%s, context=%s' % (self.path, self.context)