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