diff --git a/doc/source/reference/drivers.rst b/doc/source/reference/drivers.rst new file mode 100644 index 00000000..3790675c --- /dev/null +++ b/doc/source/reference/drivers.rst @@ -0,0 +1,12 @@ + +--------------- +Backend Drivers +--------------- + +.. automodule:: oslo_config.sources + + +Known Backend Drivers +--------------------- + +.. automodule:: oslo_config.sources._uri diff --git a/doc/source/reference/index.rst b/doc/source/reference/index.rst index 8bf214f7..ee61f914 100644 --- a/doc/source/reference/index.rst +++ b/doc/source/reference/index.rst @@ -21,4 +21,5 @@ builtins sphinxext sphinxconfiggen + drivers faq diff --git a/oslo_config/sources/__init__.py b/oslo_config/sources/__init__.py index 47565fa3..0accdeab 100644 --- a/oslo_config/sources/__init__.py +++ b/oslo_config/sources/__init__.py @@ -9,6 +9,38 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +r""" +Oslo.config's primary source of configuration data are plaintext, INI-like +style, configuration files. With the addition of backend drivers support, +it is possible to store configuration data in different places and with +different formats, as long as, exists a proper driver to connect to those +external sources and provides a way to fetch configuration values from them. + +A backend driver implementation is divided in two main classes, a driver +class of type :class:`ConfigurationSourceDriver` and a configuration source +class of type :class:`ConfigurationSource`. + +**IMPORTANT:** At this point, all backend drivers are only able to provide +unmutable values, this protects applications and services to have options +from external sources mutaded when they reload configuration files. + +Abstract Classes +---------------- + +The Driver Class +================ + +.. autoclass:: ConfigurationSourceDriver + :members: + +The Configuration Source Class +============================== + +.. autoclass:: ConfigurationSource + :members: + +""" + import abc import six @@ -20,22 +52,43 @@ _NoValue = object() @six.add_metaclass(abc.ABCMeta) class ConfigurationSourceDriver(object): - """A config driver option for Oslo.config. + """A backend driver option for oslo.config. - Represents an oslo.config driver to allow store configuration data in - other places, such as secret stores managed by a proper key management - store solution. + For each group name listed in **config_source** on the **DEFAULT** group, + a :class:`ConfigurationSourceDriver` is responsible for creating one new + instance of a :class:`ConfigurationSource`. The proper driver class to be + used is selected based on the **driver** option inside each one of the + groups listed in config_source and loaded through entry points managed by + stevedore using the namespace oslo.config.driver:: + + [DEFAULT] + config_source = source1 + config_source = source2 + ... + + [source1] + driver = remote_file + ... + + [source2] + driver = castellan + ... + + Each specific driver knows all the available options to properly instatiate + a ConfigurationSource using the values comming from the given group in the + open_source_from_opt_group() method and is able to generate sample config + through the list_options_for_discovery() method. """ @abc.abstractmethod def open_source_from_opt_group(self, conf, group_name): - """Return an open option source. + """Return an open configuration source. - Use group_name to find the configuration settings for the new - source then open the source and return it. + Uses group_name to find the configuration settings for the new + source and then open the configuration source and return it. - If a source cannot be open, raise an appropriate exception. + If a source cannot be open, raises an appropriate exception. :param conf: The active configuration option handler from which to seek configuration values. @@ -48,13 +101,14 @@ class ConfigurationSourceDriver(object): @abc.abstractmethod def list_options_for_discovery(self): - """Return a list of options used by the driver to create the source. + """Return the list of options available to configure a new source. - Drivers should advertise all supported options in this method for the - purpose of sample generation by oslo-config-generator. + Drivers should advertise all supported options in this method + for the purpose of sample generation by oslo-config-generator. - For an example on how to implement this method you can check the URI - driver at oslo_config.sources._uri.URIConfigurationSourceDriver. + For an example on how to implement this method + you can check the **remote_file** driver at + oslo_config.sources._uri.URIConfigurationSourceDriver. :returns: a list of supported options of a ConfigurationSource. """ diff --git a/oslo_config/sources/_uri.py b/oslo_config/sources/_uri.py index 0c057263..b4d5b551 100644 --- a/oslo_config/sources/_uri.py +++ b/oslo_config/sources/_uri.py @@ -9,6 +9,51 @@ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. +r""" +Remote File +----------- + +The **remote_file** backend driver is the first driver implemented by +oslo.config. It extends the previous limit of only accessing local files +to a new scenario where it is possible to access configuration data over +the network. The **remote_file** driver is based on the **requests** module +and is capable of accessing remote files through **HTTP** or **HTTPS**. + +To definition of a remote_file configuration data source can be as minimal as:: + + [DEFAULT] + config_source = external_config_group + + [external_config_group] + driver = remote_file + uri = http://mydomain.com/path/to/config/data.conf + +Or as complete as:: + + [DEFAULT] + config_source = external_config_group + + [external_config_group] + driver = remote_file + uri = https://mydomain.com/path/to/config/data.conf + ca_path = /path/to/server/ca.pem + client_key = /path/to/my/key.pem + client_cert = /path/to/my/cert.pem + +On the following sessions, you can find more information about this driver's +classes and its options. + +The Driver Class +================ + +.. autoclass:: URIConfigurationSourceDriver + +The Configuration Source Class +============================== + +.. autoclass:: URIConfigurationSource + +""" import requests import tempfile @@ -18,7 +63,7 @@ from oslo_config import sources class URIConfigurationSourceDriver(sources.ConfigurationSourceDriver): - """A configuration source driver for remote files served through http[s]. + """A backend driver for remote files served through http[s]. Required options: - uri: URI containing the file location. @@ -80,17 +125,17 @@ class URIConfigurationSourceDriver(sources.ConfigurationSourceDriver): class URIConfigurationSource(sources.ConfigurationSource): """A configuration source for remote files served through http[s]. - :uri: The Uniform Resource Identifier of the configuration to be + :param uri: The Uniform Resource Identifier of the configuration to be retrieved. - :ca_path: The path to a CA_BUNDLE file or directory with + :param ca_path: The path to a CA_BUNDLE file or directory with certificates of trusted CAs. - :client_cert: Client side certificate, as a single file path + :param client_cert: Client side certificate, as a single file path containing either the certificate only or the private key and the certificate. - :client_key: Client side private key, in case client_cert is + :param client_key: Client side private key, in case client_cert is specified but does not includes the private key. """ @@ -117,18 +162,6 @@ class URIConfigurationSource(sources.ConfigurationSource): return response.text def get(self, group_name, option_name, opt): - """Return the value of the option from the group. - - :param group_name: Name of the group. - :type group_name: str - :param option_name: Name of the option. - :type option_name: str - :param opt: The option definition. - :type opt: Opt - :returns: A tuple (value, location) where value is the option value - or oslo_config.sources._NoValue if the (group, option) is - not present in the source, and location is a LocationInfo. - """ try: return self._namespace._get_value( [(group_name, option_name)],