Browse Source

Initial version

master
Chris Smith 8 years ago
commit
3674071eba
3 changed files with 121 additions and 0 deletions
  1. 8
    0
      Dockerfile
  2. 9
    0
      README.md
  3. 104
    0
      etcdlib.py

+ 8
- 0
Dockerfile View File

@@ -0,0 +1,8 @@
1
+FROM python:3.5.1-alpine 
2
+MAINTAINER Chris Smith <chris87@gmail.com> 
3
+
4
+RUN \
5
+  pip install \
6
+    python-etcd==0.4.3
7
+
8
+COPY etcdlib.py /

+ 9
- 0
README.md View File

@@ -0,0 +1,9 @@
1
+# Docker service reporter library 
2
+
3
+This is a docker image intended as a base layer for things interacting with my
4
+[service reporter container](https://github.com/csmith/docker-service-reporter).
5
+
6
+It provides a python library for interacting with etcd, with convenience
7
+functions for retrieving the higher-level data structures (such as containers
8
+and labels) that the reporter service creates.
9
+

+ 104
- 0
etcdlib.py View File

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

Loading…
Cancel
Save