import six
from . import ConfigSource
import requests
[docs]class EtcdStore(ConfigSource):
def __init__(self, baseurl="http://127.0.0.1:2379/v2/",
**kwargs):
"""Loads configuration from a `etcd store
<https://github.com/coreos/etcd>`_.
:param baseurl: The main endpoint of the etcd store
``etcd`` has no concept of typed values, so all data from this
source are returned as strings.
"""
super(EtcdStore, self).__init__(**kwargs)
if kwargs.get('source'):
# subsection
self.source = kwargs['source']
self.sectionkey = kwargs['sectionkey']
else:
self.source = baseurl + "keys"
self.sectionkey = "/"
resp = requests.get(self.source + self.sectionkey)
self.values = resp.json()['node']['nodes']
self.dirtyvalues = {}
self.writable = kwargs.get("writable", True)
self.subsectioncache = {}
[docs] def has(self, key):
for child in self.values:
if 'dir' not in child and self.sectionkey + key == child['key']:
return True
return False
[docs] def get(self, key):
for child in self.values:
if self.sectionkey + key == child['key']:
return child['value']
raise KeyError(key)
[docs] def keys(self):
for child in self.values:
if 'dir' not in child:
yield child['key'][len(self.sectionkey):]
[docs] def typed(self, key):
return False # in etcd, all keys seem to be strings. Or can
# they be ints, bools and lists (JSON supported
# types) maybe?
[docs] def subsections(self):
for child in self.values:
if 'dir' in child:
yield child['key'][len(self.sectionkey):]
[docs] def subsection(self, key):
if key not in self.subsectioncache:
prefix = self.sectionkey
if not prefix.endswith("/"):
prefix += "/"
self.subsectioncache[key] = EtcdStore(source=self.source,
parent=self,
sectionkey=prefix+key+"/")
return self.subsectioncache[key]
[docs] def set(self, key=None, value=None):
self.dirty = True
if self.parent:
self.parent.set()
if key and value:
self.dirtyvalues[key] = value
def _strvalue(self, value):
if isinstance(value, bool):
return str(value).lower()
else:
return super(EtcdStore, self)._strvalue(value)
[docs] def save(self):
for k in self.dirtyvalues:
requests.put(self.source+self.sectionkey+k,
data={'value': self._strvalue(self.dirtyvalues[k])})
self.dirtyvalues = {}
for subsection in self.subsections():
self.subsection(subsection).save()
self.dirty = False