"Fossies" - the Fresh Open Source Software Archive

Member "keystone-17.0.0/keystone/common/resource_options/core.py" (13 May 2020, 9368 Bytes) of package /linux/misc/openstack/keystone-17.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "core.py": 16.0.1_vs_17.0.0.

    1 # Licensed under the Apache License, Version 2.0 (the "License"); you may
    2 # not use this file except in compliance with the License. You may obtain
    3 # a copy of the License at
    4 #
    5 # http://www.apache.org/licenses/LICENSE-2.0
    6 #
    7 # Unless required by applicable law or agreed to in writing, software
    8 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    9 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   10 # License for the specific language governing permissions and limitations
   11 # under the License.
   12 
   13 """Options specific to resources managed by Keystone (Domain, User, etc)."""
   14 
   15 from keystone.common import validation
   16 from keystone.i18n import _
   17 
   18 
   19 def _validator(value):
   20     return
   21 
   22 
   23 def boolean_validator(value):
   24     if value not in (True, False):
   25         raise TypeError(_('Expected boolean value, got %r') % type(value))
   26 
   27 
   28 def ref_mapper_to_dict_options(ref):
   29     """Convert the values in _resource_option_mapper to options dict.
   30 
   31     NOTE: this is to be called from the relevant `to_dict` methods or
   32           similar and must be called from within the active session context.
   33 
   34     :param ref: the DB model ref to extract options from
   35     :returns: Dict of options as expected to be returned out of to_dict in
   36               the `options` key.
   37     """
   38     options = {}
   39     for opt in ref._resource_option_mapper.values():
   40         if opt.option_id in ref.resource_options_registry.option_ids:
   41             r_opt = ref.resource_options_registry.get_option_by_id(
   42                 opt.option_id)
   43             if r_opt is not None:
   44                 options[r_opt.option_name] = opt.option_value
   45     return options
   46 
   47 
   48 def get_resource_option(model, option_id):
   49     """Get the resource option information from the model's mapper."""
   50     if option_id in model._resource_option_mapper.keys():
   51         return model._resource_option_mapper[option_id]
   52     return None
   53 
   54 
   55 def resource_options_ref_to_mapper(ref, option_class):
   56     """Convert the _resource_options property-dict to options attr map.
   57 
   58     The model must have the resource option mapper located in the
   59     ``_resource_option_mapper`` attribute.
   60 
   61     The model must have the resource option registry located in the
   62     ``resource_options_registry`` attribute.
   63 
   64     The option dict with key(opt_id), value(opt_value) will be pulled from
   65     ``ref._resource_options``.
   66 
   67     NOTE: This function MUST be called within the active writer session
   68           context!
   69 
   70     :param ref: The DB model reference that is actually stored to the
   71                 backend.
   72     :param option_class: Class that is used to store the resource option
   73                          in the DB.
   74     """
   75     options = getattr(ref, '_resource_options', None)
   76     if options is not None:
   77         # To ensure everything is clean, no lingering refs.
   78         delattr(ref, '_resource_options')
   79     else:
   80         # _resource_options didn't exist. Work from an empty set.
   81         options = {}
   82 
   83     # NOTE(notmorgan): explicitly use .keys() here as the attribute mapper
   84     # has some oddities at times. This guarantees we are working with keys.
   85     set_options = set(ref._resource_option_mapper.keys())
   86     # Get any options that are not registered and slate them for removal from
   87     # the DB. This will delete unregistered options.
   88     clear_options = set_options.difference(
   89         ref.resource_options_registry.option_ids)
   90     options.update({x: None for x in clear_options})
   91 
   92     # Set the resource options for user in the Attribute Mapping.
   93     for r_opt_id, r_opt_value in options.items():
   94         if r_opt_value is None:
   95             # Delete any option set explicitly to None, ignore unset
   96             # options.
   97             ref._resource_option_mapper.pop(r_opt_id, None)
   98         else:
   99             # Set any options on the user_ref itself.
  100             opt_obj = option_class(
  101                 option_id=r_opt_id,
  102                 option_value=r_opt_value)
  103             ref._resource_option_mapper[r_opt_id] = opt_obj
  104 
  105 
  106 class ResourceOptionRegistry(object):
  107     def __init__(self, registry_name):
  108         self._registered_options = {}
  109         self._registry_type = registry_name
  110 
  111     @property
  112     def option_names(self):
  113         return set([opt.option_name for opt in self.options])
  114 
  115     @property
  116     def options_by_name(self):
  117         return {opt.option_name: opt
  118                 for opt in self._registered_options.values()}
  119 
  120     @property
  121     def options(self):
  122         return self._registered_options.values()
  123 
  124     @property
  125     def option_ids(self):
  126         return set(self._registered_options.keys())
  127 
  128     def get_option_by_id(self, opt_id):
  129         return self._registered_options.get(opt_id, None)
  130 
  131     def get_option_by_name(self, name):
  132         for option in self._registered_options.values():
  133             if name == option.option_name:
  134                 return option
  135         return None
  136 
  137     @property
  138     def json_schema(self):
  139         schema = {'type': 'object',
  140                   'properties': {},
  141                   'additionalProperties': False}
  142         for opt in self.options:
  143             if opt.json_schema is not None:
  144                 # NOTE(notmorgan): All options are nullable. Null indicates
  145                 # the option should be reset and removed from the DB store.
  146                 schema['properties'][opt.option_name] = validation.nullable(
  147                     opt.json_schema)
  148             else:
  149                 # NOTE(notmorgan): without 'type' being specified, this
  150                 # can be of any-type. We are simply specifying no interesting
  151                 # values beyond that the property may exist here.
  152                 schema['properties'][opt.option_name] = {}
  153         return schema
  154 
  155     def register_option(self, option):
  156         if option in self.options:
  157             # Re-registering the exact same option does nothing.
  158             return
  159 
  160         if option.option_id in self._registered_options:
  161             raise ValueError(_('Option %(option_id)s already defined in '
  162                                '%(registry)s.') %
  163                              {'option_id': option.option_id,
  164                               'registry': self._registry_type})
  165         if option.option_name in self.option_names:
  166             raise ValueError(_('Option %(option_name)s already defined in '
  167                                '%(registry)s') %
  168                              {'option_name': option.option_name,
  169                               'registry': self._registry_type})
  170         self._registered_options[option.option_id] = option
  171 
  172 
  173 class ResourceOption(object):
  174 
  175     def __init__(self, option_id, option_name, validator=_validator,
  176                  json_schema_validation=None):
  177         """The base object to define the option(s) to be stored in the DB.
  178 
  179         :param option_id: The ID of the option. This will be used to lookup
  180                           the option value from the DB and should not be
  181                           changed once defined as the values will no longer
  182                           be correctly mapped to the keys in the user_ref when
  183                           retrieving the data from the DB.
  184         :type option_id: str
  185         :param option_name: The name of the option. This value will be used
  186                             to map the value from the user request on a
  187                             resource update to the correct option id to be
  188                             stored in the database. This value should not be
  189                             changed once defined as it will change the
  190                             resulting keys in the user_ref.
  191         :type option_name: str
  192         :param validator: A callable that raises TypeError if the value to be
  193                           persisted is incorrect. A single argument of the
  194                           value to be persisted will be passed to it. No return
  195                           value is expected.
  196         :type validator: callable
  197         :param json_schema_validation: Dictionary defining the JSON schema
  198                                        validation for the option itself. This
  199                                        is used to generate the JSON Schema
  200                                        validator(s) used at the API layer
  201         :type json_schema_validation: dict
  202         """
  203         if not isinstance(option_id, str) and len(option_id) == 4:
  204             raise TypeError(_('`option_id` must be a string, got %r')
  205                             % option_id)
  206         elif len(option_id) != 4:
  207             raise ValueError(_('`option_id` must be 4 characters in '
  208 
  209                                'length. Got %r') % option_id)
  210         if not isinstance(option_name, str):
  211             raise TypeError(_('`option_name` must be a string. '
  212                               'Got %r') % option_name)
  213 
  214         self._option_id = option_id
  215         self._option_name = option_name
  216         self.validator = validator
  217         self._json_schema_validation = json_schema_validation
  218 
  219     @property
  220     def json_schema(self):
  221         return self._json_schema_validation or None
  222 
  223     @property
  224     def option_name(self):
  225         # NOTE(notmorgan) Option IDs should never be set outside of definition
  226         # time.
  227         return self._option_name
  228 
  229     @property
  230     def option_id(self):
  231         # NOTE(notmorgan) Option IDs should never be set outside of definition
  232         # time.
  233         return self._option_id