Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
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
Show all changes
30 commits
Select commit Hold shift + click to select a range
562b18d
Adding ACL support to std and tornado HTTP clients (still need to wor…
tolmanam Apr 2, 2018
f80efef
Missed a reference to Nomad
tolmanam Apr 2, 2018
cc00fec
Make sure to pass the token in with the connect call
tolmanam Apr 3, 2018
580c911
Add better support for configuration through environment variables - …
tolmanam Apr 5, 2018
46f4c5a
Adjust http requests to support Consul 1+
matusvalo Nov 9, 2017
c48d307
Updated unittests to support Consul 1+
matusvalo Nov 9, 2017
3b0a762
Add support for python2.6
matusvalo Nov 9, 2017
08c60c5
Use set() instead of {} literals
matusvalo Nov 9, 2017
f067791
Reconfigure test suite after each module. Fixing hanged unittests
matusvalo Nov 9, 2017
3840866
PEP 8
matusvalo Nov 9, 2017
0d05d02
Manage additional 4xx HTTP status code #186
cp-bagerard Jan 1, 2018
a6c017a
bump version to 1.0.0-dev in preperation for merging PR #182
cablehead May 17, 2018
ec86eed
drop generating coverage status. It's not working anyway
cablehead May 17, 2018
883d3ed
update changelog
cablehead May 17, 2018
bc807a3
shot in the dark to fix travis build
cablehead May 17, 2018
7ead8e4
dropping support for Python 3.4
cablehead May 17, 2018
7dda27e
drop all of the 3.4s
cablehead May 17, 2018
bbdc9c0
update python versions supported in setup.py
cablehead May 17, 2018
cb225ee
add a link to the mailing list in the readme
cablehead May 17, 2018
61ccf9a
correct bumpversion's record of the version, after manual bump
cablehead May 17, 2018
27159de
sonar as well
cablehead May 17, 2018
57c682e
Bump version: 1.0.0-dev → 1.0.0
cablehead May 17, 2018
108f155
update changelog
cablehead May 17, 2018
fb0ea62
Bump version: 1.0.0 → 1.0.1-dev
cablehead May 17, 2018
239289e
Bump version: 1.0.1-dev → 1.0.1
cablehead May 17, 2018
5c7de60
there's some sort of conflict with ver 1.0.0 at pypi, so bumping to 1…
cablehead May 17, 2018
32fd152
Adding ACL support to std and tornado HTTP clients (still need to wor…
tolmanam Apr 2, 2018
da433f1
Add more detailed error handler
tolmanam May 18, 2018
c5ec37a
Python 3 compatibility
tolmanam May 18, 2018
8c096cf
Auto generate the version numbers
tolmanam May 18, 2018
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
2 changes: 1 addition & 1 deletion 2 .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[bumpversion]
commit = True
tag = True
current_version = 0.7.3-dev
current_version = 1.0.1
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?
serialize =
{major}.{minor}.{patch}-{release}
Expand Down
1 change: 1 addition & 0 deletions 1 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ pip-log.txt
# IntelliJ project files
*.iml
.idea/
consul/consul_version.py
1 change: 0 additions & 1 deletion 1 .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ python:
- 2.6
- 2.7
- pypy-5.3.1
- 3.4
- 3.5
- 3.6

Expand Down
8 changes: 5 additions & 3 deletions 8 CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Change log
==========

0.7.3-dev
---------
1.0.1
-----

* TBD
* Support for Python 3.4 dropped (sorry)
* Add support for Consul 1.0.0 (thanks @matusvalo!)
* Expose all 400 errors and add tests for common callback handler (thanks @bagerard)

0.7.2
-----
Expand Down
14 changes: 14 additions & 0 deletions 14 Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
VERSION = $(shell git describe --tags --match '[0-9]*.[0-9]' --abbrev=0)
REV = $(shell git rev-list $(VERSION)..HEAD | wc -l)

update_version:
echo "Version $(VERSION) and Rev $(REV)"; echo '__version__ = '\''$(VERSION).$(REV)'\''' > consul/consul_version.py

build: update_version
python setup.py sdist --formats=zip

init:
pip install -r requirements.txt && pip install -r requirements-devel.txt

test:
nosetests tests
7 changes: 6 additions & 1 deletion 7 README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Documentation
Status
------

|Build Status|\ |Coverage Status|
|Build Status|

Example
-------
Expand Down Expand Up @@ -51,6 +51,11 @@ There's a few API endpoints still to go to expose all features available in
Consul v0.6.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.

Mailing List
------------

- https://groups.google.com/forum/#!forum/python-consul

Contributing
------------

Expand Down
2 changes: 1 addition & 1 deletion 2 consul/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '0.7.3-dev'
from consul.consul_version import __version__

from consul.std import Consul

Expand Down
153 changes: 95 additions & 58 deletions 153 consul/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import base64
import json
import os
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse

import six
from six.moves import urllib
Expand Down Expand Up @@ -36,6 +40,11 @@ class BadRequest(ConsulException):
pass


class ClientError(ConsulException):
"""Encapsulates 4xx Http error code"""
pass


#
# Convenience to define checks

Expand Down Expand Up @@ -158,24 +167,28 @@ def _compat(

class CB(object):
@classmethod
def __status(klass, response, allow_404=True):
def _status(klass, response, allow_404=True):
# status checking
if response.code >= 500 and response.code < 600:
if 400 <= response.code < 500:
if response.code == 400:
raise BadRequest('%d %s' % (response.code, response.body))
elif response.code == 401:
raise ACLDisabled(response.body)
elif response.code == 403:
raise ACLPermissionDenied(response.body)
elif response.code == 404:
if not allow_404:
raise NotFound(response.body)
else:
raise ClientError("%d %s" % (response.code, response.body))
elif 500 <= response.code < 600:
raise ConsulException("%d %s" % (response.code, response.body))
if response.code == 400:
raise BadRequest('%d %s' % (response.code, response.body))
if response.code == 401:
raise ACLDisabled(response.body)
if response.code == 403:
raise ACLPermissionDenied(response.body)
if response.code == 404 and not allow_404:
raise NotFound(response.body)

@classmethod
def bool(klass):
# returns True on successful response
def cb(response):
CB.__status(response)
CB._status(response)
return response.code == 200
return cb

Expand Down Expand Up @@ -204,40 +217,39 @@ def json(
*is_id* only the 'ID' field of the json object will be returned.
"""
def cb(response):
CB.__status(response, allow_404=allow_404)
if response.code == 404:
return response.headers['X-Consul-Index'], None

data = json.loads(response.body)

if decode:
for item in data:
if item.get(decode) is not None:
item[decode] = base64.b64decode(item[decode])
if is_id:
data = data['ID']
if one:
if data == []:
data = None
if data is not None:
data = data[0]
if map:
data = map(data)
CB._status(response, allow_404=allow_404)
data = None
if response.code in [200]:
data = json.loads(response.body)

if decode:
for item in data:
if item.get(decode) is not None:
item[decode] = base64.b64decode(item[decode])
if is_id:
data = data['ID']
if one:
if data == []:
data = None
if data is not None:
data = data[0]
if map:
data = map(data)
if index:
return response.headers['X-Consul-Index'], data
return response.headers['X-Nomad-Index'], data
return data
return cb


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

def uri(self, path, params=None):
uri = self.base_uri + urllib.parse.quote(path, safe='/:')
Expand Down Expand Up @@ -265,14 +277,17 @@ def post(self, callback, path, params=None, data=''):
class Consul(object):
def __init__(
self,
host='127.0.0.1',
port=8500,
host=None,
port=None,
token=None,
scheme='http',
scheme=None,
consistency='default',
dc=None,
verify=True,
cert=None):
cert=None,
ssl_key=None,
ssl_ca=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 @@ -289,26 +304,45 @@ def __init__(

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

*cert* client side certificates for HTTPS requests
*cert* is the client side certificates for HTTPS requests
*ssl_cert* is the client side certificates for HTTPS requests
*ssl_key* is the unencrypted PEM encoded private key matching the client certificate
*ssl_ca* is the path to a PEM encoded CA cert file to use to verify the Nomad server SSL certificate
"""

# 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)
for consul_host in [host, os.getenv('CONSUL_HTTP_ADDR'), '127.0.0.1']:
if consul_host is not None:
url_details = urlparse(consul_host)
address = "%s%s" % (url_details.netloc, url_details.path)
addr_list = address.split(':')
host = addr_list[0]
if port is None and len(addr_list) > 1:
port = int(addr_list[1])
if scheme is None and url_details.scheme != "":
scheme = url_details.scheme
break

port = port if port is not None else 8500

if scheme is None:
scheme = 'https' if os.getenv('CONSUL_HTTP_SSL', '').lower() in ['true', 'on'] else 'http'

verify = verify if verify is not None else os.getenv('CONSUL_HTTP_SSL_VERIFY', '').lower() in ['true', 'on']

self.token = token if token is not None else os.getenv('CONSUL_HTTP_TOKEN')

# PEM encoded client certificate for TLS authentication to the Consul server (Must also specify key)
ssl_cert = cert if cert is not None else os.getenv('CONSUL_CLIENT_CERT')

# unencrypted PEM encoded private key matching the client certificate
ssl_key = ssl_key if ssl_key is not None else os.getenv('CONSUL_CLIENT_KEY')

# Path to a PEM encoded CA cert file to use to verify the Consul server SSL certificate
ssl_ca = ssl_ca if ssl_ca is not None else os.getenv('CONSUL_CACERT')

self.http = self.connect(host, port, scheme, verify, cert, token=self.token)
self.scheme = scheme
self.dc = dc
assert consistency in ('default', 'consistent', 'stale'), \
Expand All @@ -328,6 +362,9 @@ def __init__(
self.coordinate = Consul.Coordinate(self)
self.operator = Consul.Operator(self)

def connect(self, host, port, scheme, verify, cert, token):
pass

class Event(object):
"""
The event command provides a mechanism to fire a custom user event to
Expand Down Expand Up @@ -886,7 +923,7 @@ def deregister(self, service_id):
take care of deregistering the service with the Catalog. If
there is an associated check, that is also deregistered.
"""
return self.agent.http.get(
return self.agent.http.put(
CB.bool(), '/v1/agent/service/deregister/%s' % service_id)

def maintenance(self, service_id, enable, reason=None):
Expand Down Expand Up @@ -999,7 +1036,7 @@ def deregister(self, check_id):
"""
Remove a check from the local agent.
"""
return self.agent.http.get(
return self.agent.http.put(
CB.bool(),
'/v1/agent/check/deregister/%s' % check_id)

Expand All @@ -1012,7 +1049,7 @@ def ttl_pass(self, check_id, notes=None):
if notes:
params['note'] = notes

return self.agent.http.get(
return self.agent.http.put(
CB.bool(),
'/v1/agent/check/pass/%s' % check_id,
params=params)
Expand All @@ -1027,7 +1064,7 @@ def ttl_fail(self, check_id, notes=None):
if notes:
params['note'] = notes

return self.agent.http.get(
return self.agent.http.put(
CB.bool(),
'/v1/agent/check/fail/%s' % check_id,
params=params)
Expand All @@ -1042,7 +1079,7 @@ def ttl_warn(self, check_id, notes=None):
if notes:
params['note'] = notes

return self.agent.http.get(
return self.agent.http.put(
CB.bool(),
'/v1/agent/check/warn/%s' % check_id,
params=params)
Expand Down
32 changes: 24 additions & 8 deletions 32 consul/std.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,42 @@ def response(self, response):
def get(self, callback, path, params=None):
uri = self.uri(path, params)
return callback(self.response(
self.session.get(uri, verify=self.verify, cert=self.cert)))
self.session.get(uri,
headers={"X-Consul-Token": self.token},
verify=self.verify,
cert=self.cert
)))

def put(self, callback, path, params=None, data=''):
uri = self.uri(path, params)
return callback(self.response(
self.session.put(uri, data=data, verify=self.verify,
cert=self.cert)))
self.session.put(uri,
data=data,
headers={"X-Consul-Token": self.token},
verify=self.verify,
cert=self.cert
)))

def delete(self, callback, path, params=None):
uri = self.uri(path, params)
return callback(self.response(
self.session.delete(uri, verify=self.verify, cert=self.cert)))
self.session.delete(uri,
headers={"X-Consul-Token": self.token},
verify=self.verify,
cert=self.cert
)))

def post(self, callback, path, params=None, data=''):
uri = self.uri(path, params)
return callback(self.response(
self.session.post(uri, data=data, verify=self.verify,
cert=self.cert)))
self.session.post(uri,
data=data,
headers={"X-Consul-Token": self.token},
verify=self.verify,
cert=self.cert
)))


class Consul(base.Consul):
def connect(self, host, port, scheme, verify=True, cert=None):
return HTTPClient(host, port, scheme, verify, cert)
def connect(self, host, port, scheme, verify=True, cert=None, token=None):
return HTTPClient(host, port, scheme, verify, cert, token=token)
Loading
Morty Proxy This is a proxified and sanitized view of the page, visit original site.