Frequently Asked Questions¶
Why does oslo.config have a CONF object? Global objects SUCK!¶
Indeed. Well, it’s a long story and well documented in mailing list archives if anyone cares to dig up some links.
Around the time of the Folsom Design Summit, an attempt was made to remove our dependence on a global object like this. There was massive debate and, in the end, the rough consensus was to stick with using this approach.
Nova, through its use of the gflags library, used this approach from commit zero. Some OpenStack projects didn’t initially use this approach, but most now do. The idea is that having all projects use the same approach is more important than the objections to the approach. Sharing code between projects is great, but by also having projects use the same idioms for stuff like this it makes it much easier for people to work on multiple projects.
This debate will probably never completely go away, though. See this latest discussion in August, 2014
Why are configuration options not part of a library’s API?¶
Configuration options are a way for deployers to change the behavior of OpenStack. Applications are not supposed to be aware of the configuration options defined and used within libraries, because the library API is supposed to work transparently no matter which backend is configured.
Configuration options in libraries can be renamed, moved, and
deprecated just like configuration options in applications. However,
if applications are allowed to read or write the configuration options
directly, treating them as an API, the option cannot be renamed
without breaking the application. Instead, libraries should provide a
programmatic API (usually a set_defaults()
function) for setting
the defaults for configuration options. For example, this function
from oslo.log
lets the caller change the format string and default
logging levels:
def set_defaults(logging_context_format_string=None,
default_log_levels=None):
"""Set default values for the configuration options used by oslo.log."""
# Just in case the caller is not setting the
# default_log_level. This is insurance because
# we introduced the default_log_level parameter
# later in a backwards in-compatible change
if default_log_levels is not None:
cfg.set_defaults(
_options.log_opts,
default_log_levels=default_log_levels)
if logging_context_format_string is not None:
cfg.set_defaults(
_options.log_opts,
logging_context_format_string=logging_context_format_string)
If the name of either option changes, the API of set_defaults()
can be updated to allow both names, and warn if the old one is
provided. Using a supported API like this is better than having an
application call set_default()
on the configuration object
directly, such as:
cfg.CONF.set_default('default_log_levels', default_log_levels)
This form will trigger an error if the logging options are moved out
of the default option group into their own section of the
configuration file. It will also fail if the default_log_levels
option is not yet registered, or if it is renamed. All of those cases
can be protected against with a set_defaults()
function in the
library that owns the options.
Similarly, code that does not own the configuration option definition should not read the option value. An application should never, for example, do something like:
log_file = cfg.CONF.log_file
The type, name, and existence of the log_file
configuration option
is subject to change. oslo.config
makes it easy to communicate
that change to a deployer in a way that allows their old configuration
files to continue to work. It has no mechanism for doing that in
application code, however.