🌐 AI搜索 & 代理 主页
Skip to content
This repository was archived by the owner on Apr 15, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ Example
# in another process
c.kv.put('foo', 'bar')


Alternatively you can create a client from the same `environment variables`_ that
the consul command line client uses. e.g. CONSUL_HTTP_ADDR, CONSUL_HTTP_TOKEN.

.. code:: python

import consul

c = consul.Consul.from_env()

c.agent.self()


Installation
------------

Expand All @@ -45,6 +58,7 @@ Installation
image:: https://img.shields.io/coveralls/cablehead/python-consul.svg?style=flat-square
:target: https://coveralls.io/r/cablehead/python-consul?branch=master
.. _Read the Docs: https://python-consul.readthedocs.io/
.. _environment variables: https://www.consul.io/docs/commands/index.html#environment-variables

Status
------
Expand Down
18 changes: 13 additions & 5 deletions consul/aio.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import asyncio
import warnings

from six.moves import urllib

import aiohttp
from consul import base

Expand All @@ -17,8 +19,14 @@ class HTTPClient(base.HTTPClient):
def __init__(self, *args, loop=None, **kwargs):
super(HTTPClient, self).__init__(*args, **kwargs)
self._loop = loop or asyncio.get_event_loop()
connector = aiohttp.TCPConnector(loop=self._loop,
verify_ssl=self.verify)
if 'unix://' in self.base_uri:
pr = urllib.parse.urlparse(self.base_uri)
self.base_uri = 'http://consul'
connector = aiohttp.UnixConnector(loop=self._loop,
path=pr.path)
else:
connector = aiohttp.TCPConnector(loop=self._loop,
verify_ssl=self.verify)
self._session = aiohttp.ClientSession(connector=connector)

@asyncio.coroutine
Expand Down Expand Up @@ -64,9 +72,9 @@ def __init__(self, *args, loop=None, **kwargs):
self._loop = loop or asyncio.get_event_loop()
super().__init__(*args, **kwargs)

def connect(self, host, port, scheme, verify=True, cert=None):
return HTTPClient(host, port, scheme, loop=self._loop,
verify=verify, cert=None)
def connect(self, base_uri, verify=True, cert=None, auth=None):
return HTTPClient(base_uri, loop=self._loop,
verify=verify, cert=cert, auth=auth)

def close(self):
"""Close all opened http connections"""
Expand Down
95 changes: 71 additions & 24 deletions consul/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,14 +246,11 @@ def cb(response):


class HTTPClient(six.with_metaclass(abc.ABCMeta, object)):
def __init__(self, host='127.0.0.1', port=8500, scheme='http',
verify=True, cert=None):
self.host = host
self.port = port
self.scheme = scheme
def __init__(self, base_uri, verify=True, cert=None, auth=None):
self.base_uri = base_uri
self.verify = verify
self.base_uri = '%s://%s:%s' % (self.scheme, self.host, self.port)
self.cert = cert
self.auth = auth

def uri(self, path, params=None):
uri = self.base_uri + urllib.parse.quote(path, safe='/:')
Expand Down Expand Up @@ -288,7 +285,9 @@ def __init__(
consistency='default',
dc=None,
verify=True,
cert=None):
cert=None,
auth=None,
addr=None):
"""
*token* is an optional `ACL token`_. If supplied it will be used by
default for all requests made with this client session. It's still
Expand All @@ -305,27 +304,19 @@ def __init__(

*verify* is whether to verify the SSL certificate for HTTPS requests

*cert* client side certificates for HTTPS requests
*cert* tuple containing client certificate and key for HTTPS requests

*addr* url to use instead of host, port and scheme.
e.g. unix:///var/run/consul/http.sock, http://localhost:8500/
"""

# TODO: Status

if os.getenv('CONSUL_HTTP_ADDR'):
try:
host, port = os.getenv('CONSUL_HTTP_ADDR').split(':')
except ValueError:
raise ConsulException('CONSUL_HTTP_ADDR (%s) invalid, '
'does not match <host>:<port>'
% os.getenv('CONSUL_HTTP_ADDR'))
use_ssl = os.getenv('CONSUL_HTTP_SSL')
if use_ssl is not None:
scheme = 'https' if use_ssl == 'true' else 'http'
if os.getenv('CONSUL_HTTP_SSL_VERIFY') is not None:
verify = os.getenv('CONSUL_HTTP_SSL_VERIFY') == 'true'

self.http = self.connect(host, port, scheme, verify, cert)
self.token = os.getenv('CONSUL_HTTP_TOKEN', token)
self.scheme = scheme
if not addr:
addr = '{0}://{1}:{2}'.format(scheme, host, port)

self.http = self.connect(addr, verify=verify, cert=cert, auth=auth)
self.token = token
self.dc = dc
assert consistency in ('default', 'consistent', 'stale'), \
'consistency must be either default, consistent or state'
Expand All @@ -344,6 +335,62 @@ def __init__(
self.coordinate = Consul.Coordinate(self)
self.operator = Consul.Operator(self)

@classmethod
def from_env(cls, consistency='default', dc=None):
"""
Return a client configured from environment variables.
The environment variables used are the same as those used by the
consul command-line client. Refer to the consul documentation [1] for
a list of existing environment variables.

Additionally all supported given keyword arguments are passed on the
client constructor.

[1] https://www.consul.io/docs/commands/index.html#environment-variables # noqa: E501
"""
oe = os.environ
kwargs = {
'consistency': consistency,
'dc': dc,
'token': oe.get('CONSUL_HTTP_TOKEN', None),
}

addr = oe.get('CONSUL_HTTP_ADDR', None)
if addr:
if not addr.startswith('http'):
# Ensure addr starts with a scheme.
ssl = oe.get('CONSUL_HTTP_SSL', False)
if ssl == 'false':
ssl = False
elif ssl == 'true':
ssl = True

if ssl:
scheme = 'https'
else:
scheme = 'http'
addr = '%s://%s' % (scheme, addr)
kwargs['addr'] = addr

verify = oe.get('CONSUL_CACERT',
oe.get('CONSUL_HTTP_SSL_VERIFY', None))
if verify:
if verify == 'false':
verify = False
elif verify == 'true':
verify = True
kwargs['verify'] = verify

if 'CONSUL_CLIENT_CERT' in oe \
and 'CONSUL_CLIENT_KEY' in oe:
kwargs['cert'] = (oe['CONSUL_CLIENT_CERT'],
oe['CONSUL_CLIENT_KEY'])

if 'CONSUL_HTTP_AUTH' in oe:
kwargs['auth'] = oe['CONSUL_HTTP_AUTH'].split(':')

return cls(**kwargs)

class Event(object):
"""
The event command provides a mechanism to fire a custom user event to
Expand Down
20 changes: 17 additions & 3 deletions consul/std.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import requests

from six.moves import urllib

from consul import base


Expand All @@ -9,7 +11,19 @@
class HTTPClient(base.HTTPClient):
def __init__(self, *args, **kwargs):
super(HTTPClient, self).__init__(*args, **kwargs)
self.session = requests.session()
if 'unix://' in self.base_uri:
pr = urllib.parse.urlparse(self.base_uri)
netloc = urllib.parse.quote_plus(pr.path)
self.base_uri = 'http+unix://{0}'.format(netloc)
try:
import requests_unixsocket
self.session = requests_unixsocket.Session()
except ImportError:
raise base.ConsulException('To use a unix socket to connect to'
' Consul you need to install the'
' "requests_unixsocket" package.')
else:
self.session = requests.session()

def response(self, response):
response.encoding = 'utf-8'
Expand Down Expand Up @@ -40,5 +54,5 @@ def post(self, callback, path, params=None, data=''):


class Consul(base.Consul):
def connect(self, host, port, scheme, verify=True, cert=None):
return HTTPClient(host, port, scheme, verify, cert)
def connect(self, base_uri, verify=True, cert=None, auth=None):
return HTTPClient(base_uri, verify=verify, cert=cert, auth=auth)
5 changes: 3 additions & 2 deletions consul/tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
class HTTPClient(base.HTTPClient):
def __init__(self, *args, **kwargs):
super(HTTPClient, self).__init__(*args, **kwargs)
# TODO: support for unix:// uris
self.client = httpclient.AsyncHTTPClient()

def response(self, response):
Expand Down Expand Up @@ -53,5 +54,5 @@ def post(self, callback, path, params=None, data=''):


class Consul(base.Consul):
def connect(self, host, port, scheme, verify=True, cert=None):
return HTTPClient(host, port, scheme, verify=verify, cert=cert)
def connect(self, base_uri, verify=True, cert=None, auth=None):
return HTTPClient(base_uri, verify=verify, cert=cert, auth=auth)
8 changes: 4 additions & 4 deletions consul/twisted.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def getContext(self, hostname, port):
class HTTPClient(base.HTTPClient):
def __init__(self, contextFactory, *args, **kwargs):
super(HTTPClient, self).__init__(*args, **kwargs)
# TODO: support for unix:// uris
agent_kwargs = dict(
reactor=reactor, pool=HTTPConnectionPool(reactor))
if contextFactory is not None:
Expand Down Expand Up @@ -125,13 +126,12 @@ def delete(self, callback, path, params=None):

class Consul(base.Consul):
@staticmethod
def connect(host,
port,
scheme,
def connect(base_uri,
verify=True,
cert=None,
auth=None,
contextFactory=None,
**kwargs):
return HTTPClient(
contextFactory, host, port, scheme, verify=verify, cert=cert,
contextFactory, base_uri, verify=verify, cert=cert, auth=auth,
**kwargs)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
requests>=2.0
requests-unixsocket>=0.1.5
six>=1.4
Loading