1.. include:: ../README.rst
2
3Clients
4-------
5
6This library is designed to be easily adapted for a number of clients.
7Particularly asynchronous clients. The following clients are currently
8supported.
9
10Standard
11~~~~~~~~
12
13This is a standard blocking python client. It isn't particularly useful for
14creating server components - but it does serve as a base. It makes use of the
15`requests`_ library for http requests.
16
17.. code:: python
18
19    >>> import consul
20
21    >>> c = consul.Consul()
22
23    >>> c.kv.put('foo', 'bar')
24    True
25
26    >>> index, data = c.kv.get('foo')
27    >>> data['Value']
28    'bar'
29
30    # this will block until there's an update or a timeout
31    >>> index, data = c.kv.get('foo', index=index)
32
33Vanilla
34~~~~~~~
35
36An asynchronous `Vanilla`_ plugin based on this library is available at:
37https://github.com/cablehead/vanilla.consul
38
39gevent
40~~~~~~
41
42The terribly awful thing about `gevent`_ is that anything that uses the socket
43library from the python standard lib, including the `requests`_ library can be
44made non-blocking via monkey patching. This means the standard python-consul
45client will just work asynchronously with `gevent`_.
46
47Tornado
48~~~~~~~
49
50There is a `Tornado`_ client which makes use of `gen.coroutine`_. The API for
51this client is identical to the standard python-consul client except that you
52need to *yield* the result of each API call. This client is available in
53*consul.tornado*.
54
55.. code:: python
56
57    from tornado.ioloop import IOLoop
58    from tornado.gen import coroutine
59    from consul.base import Timeout
60    from consul.tornado import Consul
61
62
63    class Config(object):
64        def __init__(self, loop):
65            self.foo = None
66            loop.add_callback(self.watch)
67
68        @coroutine
69        def watch(self):
70            c = Consul()
71
72            # asynchronously poll for updates
73            index = None
74            while True:
75                try:
76                    index, data = yield c.kv.get('foo', index=index)
77                    if data is not None:
78                        self.foo = data['Value']
79                except Timeout:
80                    # gracefully handle request timeout
81                    pass
82
83    if __name__ == '__main__':
84        loop = IOLoop.instance()
85        _ = Config(loop)
86        loop.start()
87
88
89asyncio
90~~~~~~~
91
92There is a `asyncio`_ (using aiohttp_) client which works with `Python3.4` and
93makes use of `asyncio.coroutine`_. The API for this client is identical to
94the standard python-consul client except that you need to ``yield from`` the
95result of each API call. This client is available in *consul.aio*.
96
97.. code:: python
98
99    import asyncio
100    import consul.aio
101
102
103    loop = asyncio.get_event_loop()
104
105    @asyncio.coroutine
106    def go():
107
108        # always better to pass ``loop`` explicitly, but this
109        # is not mandatory, you can relay on global event loop
110        c = consul.aio.Consul(port=consul_port, loop=loop)
111
112        # set value, same as default api but with ``yield from``
113        response = yield from c.kv.put(b'foo', b'bar')
114        assert response is True
115
116        # get value
117        index, data = yield from c.kv.get(b'foo')
118        assert data['Value'] == b'bar'
119
120        # delete value
121        response = yield from c.kv.delete(b'foo2')
122        assert response is True
123
124    loop.run_until_complete(go())
125
126
127Wanted
128~~~~~~
129
130Adaptors for `Twisted`_ and a `thread pool`_ based adaptor.
131
132Tools
133-----
134
135Handy tools built on python-consul.
136
137`ianitor`_
138~~~~~~~~~~
139
140`ianitor`_ is a doorkeeper for your services discovered using consul. It can
141automatically register new services through consul API and manage TTL health
142checks.
143
144Example Uses
145------------
146
147ACLs
148~~~~
149
150.. code:: python
151
152    import consul
153
154    # master_token is a *management* token, for example the *acl_master_token*
155    # you started the Consul server with
156    master = consul.Consul(token=master_token)
157
158    master.kv.put('foo', 'bar')
159    master.kv.put('private/foo', 'bar')
160
161    rules = """
162        key "" {
163            policy = "read"
164        }
165        key "private/" {
166            policy = "deny"
167        }
168    """
169    token = master.acl.create(rules=rules)
170
171    client = consul.Consul(token=token)
172
173    client.kv.get('foo')          # OK
174    client.kv.put('foo', 'bar2')  # raises ACLPermissionDenied
175
176    client.kv.get('private/foo')  # returns None, as though the key doesn't
177                                  # exist - slightly unintuitive
178    client.kv.put('private/foo', 'bar2')  # raises ACLPermissionDenied
179
180API Documentation
181-----------------
182
183Check
184~~~~~
185
186.. autoclass:: consul.Check
187
188Check.docker
189++++++++++++
190
191.. automethod:: consul.Check.docker
192
193Check.script
194++++++++++++
195
196.. automethod:: consul.Check.script
197
198Check.http
199++++++++++
200
201.. automethod:: consul.Check.http
202
203Check.tcp
204+++++++++
205
206.. automethod:: consul.Check.tcp
207
208Check.ttl
209+++++++++
210
211.. automethod:: consul.Check.ttl
212
213
214Consul
215~~~~~~
216
217.. autoclass:: consul.Consul
218
219Consul.acl
220++++++++++
221
222.. autoclass:: consul.base::Consul.ACL()
223   :members:
224   :undoc-members:
225
226Consul.agent
227++++++++++++
228
229.. autoclass:: consul.base::Consul.Agent()
230   :members:
231   :exclude-members: Service
232
233.. autoclass:: consul.base::Consul.Agent.Service()
234   :members:
235
236.. autoclass:: consul.base::Consul.Agent.Check()
237   :members:
238
239Consul.catalog
240++++++++++++++
241
242.. autoclass:: consul.base::Consul.Catalog()
243   :members:
244   :undoc-members:
245
246Consul.event
247++++++++++++
248
249.. autoclass:: consul.base::Consul.Event()
250   :members:
251   :undoc-members:
252
253Consul.coordinate
254+++++++++++++++++
255
256.. autoclass:: consul.base::Consul.Coordinate()
257   :members:
258   :undoc-members:
259
260Consul.health
261+++++++++++++
262
263.. autoclass:: consul.base::Consul.Health()
264   :members:
265   :undoc-members:
266   :exclude-members: Check
267
268Consul.kv
269+++++++++
270
271.. autoclass:: consul.base::Consul.KV()
272   :members:
273   :undoc-members:
274
275Consul.query
276++++++++++++
277
278.. autoclass:: consul.base::Consul.Query()
279   :members:
280   :undoc-members:
281
282Consul.session
283++++++++++++++
284
285.. autoclass:: consul.base::Consul.Session()
286   :members:
287   :undoc-members:
288
289Consul.status
290+++++++++++++
291
292.. autoclass:: consul.base::Consul.Status()
293   :members:
294   :undoc-members:
295
296Consul.txn
297++++++++++
298
299.. autoclass:: consul.base::Consul.Txn()
300   :members:
301   :undoc-members:
302
303
304.. _ACL Token: http://www.consul.io/docs/internals/acl.html
305.. _HCL: https://github.com/hashicorp/hcl/
306.. _requests: http://python-requests.org
307.. _Vanilla: https://github.com/cablehead/vanilla
308.. _gevent: http://www.gevent.org
309.. _Tornado: http://www.tornadoweb.org
310.. _gen.coroutine: https://tornado.readthedocs.io/en/latest/gen.html
311.. _asyncio.coroutine: https://docs.python.org/3/library/asyncio-task.html#coroutines
312.. _aiohttp: https://github.com/KeepSafe/aiohttp
313.. _asyncio: https://docs.python.org/3/library/asyncio.html
314.. _Twisted: https://twistedmatrix.com/trac/
315.. _thread pool: https://docs.python.org/2/library/threading.html
316
317.. _ianitor: https://github.com/ClearcodeHQ/ianitor
318