Skip to content

Commit

Permalink
Add support for HTTP health checks.
Browse files Browse the repository at this point in the history
  • Loading branch information
Anders Daljord Morken committed Jun 8, 2015
1 parent 3671a57 commit ffa63c7
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
52 changes: 42 additions & 10 deletions consulate/api/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,15 @@ def register(self, name,
check_id=None,
interval=None,
ttl=None,
notes=None):
notes=None,
http=None):
"""Add a new check to the local agent. Checks are either a script
or TTL type. The agent is responsible for managing the status of
the check and keeping the Catalog in sync.
The ``name`` field is mandatory, as is either ``script`` and
``interval`` or ``ttl``. Only one of ``script`` and ``interval``
``interval``, ``http`` and ``interval`` or ``ttl``.
Only one of ``script`` and ``interval``, ``http`` and ``interval``
or ``ttl`` should be provided. If an ``check_id`` is not
provided, it is set to ``name``. You cannot have duplicate
``check_id`` entries per agent, so it may be necessary to provide
Expand All @@ -75,14 +77,19 @@ def register(self, name,
If a ``script`` is provided, the check type is a script, and Consul
will evaluate the script every ``interval`` to update the status.
If a ``http`` URL is provided, Consul will poll the URL every
``interval`` to update the status - only 2xx results are considered
healthy.
If a ``ttl`` type is used, then the ``ttl`` update APIs must be
used to periodically update the state of the check.
:param str name: The check name
:param str http: The URL to poll for health checks
:param str script: The path to the script to run
:param str check_id: The optional check id
:param int interval: The interval to run the check
:param int ttl: The ttl to specify for the check
:param str notes: Administrative notes.
:rtype: bool
:raises: ValueError
Expand All @@ -93,12 +100,22 @@ def register(self, name,
elif script and ttl:
raise ValueError('Can not specify script and ttl together')

if http and not interval:
raise ValueError('Must specify interval when using http')
elif http and ttl:
raise ValueError('Can not specify http and ttl together')

if http and script:
raise ValueError('Can not specify script and http together')


# Register the check
return self._put_no_response_body(['register'], None, {
'ID': check_id,
'Name': name,
'Notes': notes,
'Script': script,
'HTTP': http,
'Interval': interval,
'TTL': ttl
})
Expand Down Expand Up @@ -161,17 +178,19 @@ def register(self, name,
tags=None,
check=None,
interval=None,
ttl=None):
ttl=None,
httpcheck=None):
"""Add a new service to the local agent.
:param str name: The name of the service
:param str service_id: The id for the service (optional)
:param str address: The service IP address
:param int port: The service port
:param list tags: A list of tags for the service
:param str check: The path to the check to run
:param str interval: The script execution interval
:param str check: The path to the check script to run
:param str interval: The check execution interval
:param str ttl: The TTL for external script check pings
:param str httpcheck: An URL to check every interval
:rtype: bool
:raises: ValueError
Expand All @@ -181,21 +200,34 @@ def register(self, name,
raise ValueError('port must be an integer')
elif tags and not isinstance(tags, list):
raise ValueError('tags must be a list of strings')
elif check and ttl:
elif (check or httpcheck) and ttl:
raise ValueError('Can not specify both a check and ttl')

if (check or httpcheck) and not interval:
raise ValueError('An interval is required for check scripts and http checks.')

check_spec = None
if check:
check_spec = {'script': check,
'interval': interval}
elif httpcheck:
check_spec = {'HTTP': httpcheck,
'interval': interval}
elif ttl:
check_spec = {'TTL': ttl}

# Build the payload to send to consul
payload = {
'id': service_id,
'name': name,
'port': port,
'address': address,
'tags': tags,
'check': {'script': check,
'interval': interval,
'ttl': ttl}
'tags': tags
}

if check_spec:
payload['check'] = check_spec

for key in list(payload.keys()):
if payload[key] is None:
del payload[key]
Expand Down
11 changes: 9 additions & 2 deletions consulate/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ def add_register_args(parser):
help='How often to run the check script')
check.add_argument('path', default=None,
help='Path to the script invoked by Consul')
httpcheck = rsparsers.add_parser('httpcheck',
help='Define an HTTP-based check')
httpcheck.add_argument('interval', default=10, type=int,
help='How often to run the check script')
httpcheck.add_argument('url', default=None,
help='HTTP URL to be polled by Consul')
rsparsers.add_parser('no-check', help='Do not enable service monitoring')
ttl = rsparsers.add_parser('ttl', help='Define a duration based TTL check')
ttl.add_argument('duration', type=int, default=10,
Expand Down Expand Up @@ -258,12 +264,13 @@ def register(consul, args):
"""
check = args.path if args.ctype == 'check' else None
interval = '%ss' % args.interval if args.ctype == 'check' else None
httpcheck = args.url if args.ctype == 'httpcheck' else None
interval = '%ss' % args.interval if 'check' in args.ctype else None
ttl = '%ss' % args.duration if args.ctype == 'ttl' else None
tags = args.tags.split(',') if args.tags else None
try:
consul.agent.service.register(args.name, args.service_id, args.address,
args.port, tags, check, interval, ttl)
args.port, tags, check, interval, ttl, httpcheck)
except exceptions.ConnectionError:
connection_error()

Expand Down

0 comments on commit ffa63c7

Please sign in to comment.