Library for interacting with etcd-based service reporting. Intended to be used as a base image.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

etcdlib.py 2.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/env python3
  2. import etcd
  3. import time
  4. class Connection:
  5. def __init__(self, host, port, prefix):
  6. self._client = etcd.Client(host=host, port=port)
  7. self._prefix = prefix
  8. def _read(self, key, **kwargs):
  9. try:
  10. node = self._client.read(self._prefix + key, **kwargs)
  11. return node.value if node else None
  12. except etcd.EtcdKeyNotFound:
  13. return None
  14. def _read_recursive(self, key):
  15. try:
  16. return self._client.read(self._prefix + key, recursive=True)
  17. except etcd.EtcdKeyNotFound:
  18. return None
  19. def _write(self, key, value):
  20. self._client.write(self._prefix + key, value)
  21. def _write_obj(self, prefix, obj):
  22. for key, value in obj.items():
  23. new_prefix = "%s/%s" % (prefix, key)
  24. if isinstance(value, dict):
  25. self._write_obj(new_prefix, value)
  26. else:
  27. self._write(new_prefix, str(value))
  28. def _delete(self, key):
  29. try:
  30. self._client.delete(self._prefix + key, recursive=True)
  31. except etcd.EtcdKeyNotFound:
  32. pass
  33. def wipe(self):
  34. self._delete('')
  35. def add_containers(self, new_containers):
  36. for container in new_containers:
  37. name = container['name']
  38. print('Adding container %s' % name)
  39. self._write_obj('/containers/%s' % name, container)
  40. for k, v in container['labels'].items():
  41. self._write('/labels/%s/%s' % (k, name), v)
  42. for k, v in container['net']['addr'].items():
  43. self._write('/networks/%s/%s' % (k, name), v)
  44. self._write('/hosts/%s/%s' % (container['host'], name), name)
  45. self._notify_update()
  46. def remove_containers(self, old_containers):
  47. for container in old_containers:
  48. name = container['name']
  49. print('Removing container %s' % name)
  50. self._delete('/containers/%s' % name)
  51. for k, v in container['labels'].items():
  52. self._delete('/labels/%s/%s' % (k, name))
  53. for k, v in container['net']['addr'].items():
  54. self._delete('/networks/%s/%s' % (k, name))
  55. self._delete('/hosts/%s/%s' % (container['host'], name))
  56. self._notify_update()
  57. def get_label(self, label):
  58. node = self._read_recursive('/labels/%s' % label)
  59. if node:
  60. return {child.key.split('/')[-1]: child.value for child in node.children}
  61. else:
  62. return {}
  63. def _notify_update(self):
  64. print('Update completed', flush=True)
  65. self._write('/_updated', time.time())
  66. def wait_for_update(self):
  67. original_time = self._read('/_updated')
  68. new_time = original_time
  69. while new_time == original_time:
  70. try:
  71. new_time = self._read('/_updated', wait=True)
  72. except etcd.EtcdWatchTimedOut:
  73. new_time = self._read('/_updated')
  74. time.sleep(10)