blazar/blazar/context.py
Masahito Muroi 29e68d8295 Ignore keys unsupported by BlazarContext in its creation
BlazarContext class raises an error when the class is instantiated
with unspported keys. The class is used as a context for RPC and
the RPC is implemented over oslo.messaging. If oslo.messaging
automatically adds a new key for the context, the RPC execution
fails since the new key is unexpected by BlazarContext and it
raises an error.

This patch relaxes the limitations in BlazarContext. If unexpected
keys are passed for the class instantiation, the class ignores the
keys.

Change-Id: Ibdca6eead0ee726bc10a07ee43e4ef10110d23e2
Closes-Bug: #1775363
2018-06-06 18:57:16 +09:00

107 lines
3.0 KiB
Python

# Copyright (c) 2013 Mirantis Inc.
#
# 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 threading
class BaseContext(object):
_elements = set()
_context_stack = threading.local()
def __init__(self, __mapping=None, **kwargs):
if __mapping is None:
self.__values = dict(**kwargs)
else:
if isinstance(__mapping, BaseContext):
__mapping = __mapping.__values
self.__values = dict(__mapping)
self.__values.update(**kwargs)
not_supported_keys = set(self.__values) - self._elements
for k in not_supported_keys:
del self.__values[k]
def __getattr__(self, name):
try:
return self.__values[name]
except KeyError:
if name in self._elements:
return None
else:
raise AttributeError(name)
def __setattr__(self, name, value):
# NOTE(yorik-sar): only the very first assignment for __values is
# allowed. All context arguments should be set at the time the context
# object is being created.
if not self.__dict__:
super(BaseContext, self).__setattr__(name, value)
else:
raise Exception(self.__dict__, name, value)
def __enter__(self):
try:
stack = self._context_stack.stack
except AttributeError:
stack = []
self._context_stack.stack = stack
stack.append(self)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
res = self._context_stack.stack.pop()
assert res is self, "self should be the top element of the stack"
@classmethod
def current(cls):
try:
return cls._context_stack.stack[-1]
except (AttributeError, IndexError):
raise RuntimeError("Context isn't available here")
# NOTE(yorik-sar): as long as oslo.rpc requires this
def to_dict(self):
return self.__values
class BlazarContext(BaseContext):
_elements = set([
"user_id",
"project_id",
"auth_token",
"service_catalog",
"user_name",
"project_name",
"roles",
"is_admin",
])
@classmethod
def elevated(cls):
try:
ctx = cls.current()
except RuntimeError:
ctx = None
return cls(ctx, is_admin=True)
def current():
return BlazarContext.current()
def elevated():
return BlazarContext.elevated()