Python client for Consul.io

Documentation

Read the Docs

Status

Build StatusCoverage Status

Example

import consul

c = consul.Consul()

# poll a key for updates
index = None
while True:
    index, data = c.kv.get('foo', index=index)
    print data['Value']

# in another process
c.kv.put('foo', 'bar')

Installation

pip install python-consul

Status

There’s a few API endpoints still to go to expose all features available in Consul v0.5.0. If you need an endpoint that’s not in the documentation, just open an issue and I’ll try and add it straight away.

Clients

This library is designed to be easily adapted for a number of clients. Particularly asynchronous clients. The following clients are currently supported.

Standard

This is a standard blocking python client. It isn’t particularly useful for creating server components - but it does serve as a base. It makes use of the requests library for http requests.

>>> import consul

>>> c = consul.Consul()

>>> c.kv.put('foo', 'bar')
True

>>> index, data = c.kv.get('foo')
>>> data['Value']
'bar'

# this will block until there's an update or a timeout
>>> index, data = c.kv.get('foo', index=index)

Vanilla

An asynchronous Vanilla plugin based on this library is available at: https://github.com/cablehead/vanilla.consul

gevent

The terribly awful thing about gevent is that anything that uses the socket library from the python standard lib, including the requests library can be made non-blocking via monkey patching. This means the standard python-consul client will just work asynchronously with gevent.

Tornado

There is a Tornado client which makes use of gen.coroutine. The API for this client is identical to the standard python-consul client except that you need to yield the result of each API call. This client is available in consul.tornado.

import consul.tornado

class Config(object):
    def __init__(self):
        self.foo = None
        loop.add_callback(self.watch)

    @tornado.gen.coroutine
    def watch(self):
        c = consul.tornado.Consul()

        # asynchronously poll for updates
        index = None
        while True:
            index, data = yield c.kv.get('foo', index=index)
            self.foo = data['Value']

asyncio

There is a asyncio (using aiohttp) client which works with Python3.4 and makes use of asyncio.coroutine. The API for this client is identical to the standard python-consul client except that you need to yield from the result of each API call. This client is available in consul.aio.

import asyncio
import consul.aio


loop = asyncio.get_event_loop()

@asyncio.coroutine
def go():

    # always better to pass ``loop`` explicitly, but this
    # is not mandatory, you can relay on global event loop
    c = consul.aio.Consul(port=consul_port, loop=loop)

    # set value, same as default api but with ``yield from``
    response = yield from c.kv.put(b'foo', b'bar')
    assert response is True

    # get value
    index, data = yield from c.kv.get(b'foo')
    assert data['Value'] == b'bar'

    # delete value
    response = yield from c.kv.delete(b'foo2')
    assert response is True

loop.run_until_complete(go())

Wanted

Adaptors for Twisted and a thread pool based adaptor.

Tools

Handy tools built on python-consul.

ianitor

ianitor is a doorkeeper for your services discovered using consul. It can automatically register new services through consul API and manage TTL health checks.

Example Uses

ACLs

import consul

# master_token is a *management* token, for example the *acl_master_token*
# you started the Consul server with
master = consul.Consul(token=master_token)

master.kv.put('foo', 'bar')
master.kv.put('private/foo', 'bar')

rules = """
    key "" {
        policy = "read"
    }
    key "private/" {
        policy = "deny"
    }
"""
token = master.acl.create(rules=rules)

client = consul.Consul(token=token)

client.kv.get('foo')          # OK
client.kv.put('foo', 'bar2')  # raises ACLPermissionDenied

client.kv.get('private/foo')  # returns None, as though the key doesn't
                              # exist - slightly unintuitive
client.kv.put('private/foo', 'bar2')  # raises ACLPermissionDenied

API Documentation

consul.kv

consul.agent

consul.catalog

consul.health

consul.session

consul.acl

consul.event