Created
July 7, 2014 06:06
-
-
Save pixie79/ef20c9c7be88a745d53c to your computer and use it in GitHub Desktop.
Consul Service module for Ansible
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# -*- mode: python -*- | |
DOCUMENTATION = ''' | |
--- | |
module: consul | |
short_description: Consul Agent API interaction with Docker | |
description: | |
- This module wraps the Consul API making calls to the Agent end points | |
to register and unregister services. | |
options: | |
docker_name: | |
description: | |
- The name of the docker file the service relates to. | |
required: True | |
default: None | |
docker_id: | |
description: | |
- The ID that relates to this service, e.g HTTP | |
required: False | |
default: {{ docker_name }} | |
port: | |
description: | |
- The port which the service to be registered runs on. | |
required: True | |
default: None | |
tags: | |
description: | |
- Any tags as a list that should be registered for the service. | |
required: False | |
default: None | |
check: | |
description: | |
- The path to a script which can check the service is working | |
required: False | |
default: None | |
check_args: | |
description: | |
- Any arguments to be passed on to the check as a string | |
required: False | |
default: None | |
docker_remove: | |
description: | |
- Should we remove or leave a failed docker container from the system | |
required: False | |
default: True | |
author: Mark Olliver | |
''' | |
EXAMPLES = ''' | |
# Example that checks if Sentinel docker is running, if it is and the service | |
# is not registered then we register the service. If the docker is not running | |
# then we deregister the service if it was registered. If the remove flag is | |
# set then we remove the docker container if it is not running to tidy up the | |
# system. | |
- consul: | |
docker_name: "sentinel{{ env_suffix }}" | |
docker_id: "sentinel{{ env_suffix }}" | |
port: 26379 | |
tags: "{{ env_suffix }}" | |
check: redis_check.py | |
check_args: "--docker_name sentinel{{ env_suffix }} --docker_id | |
sentinel{{ env_suffix }} --port 26379" | |
''' | |
''' | |
TODO(Mark): Extend to use check mode which will allow for reporting if | |
# a service is registered | |
''' | |
import urllib2 | |
import json | |
def register_service(module, docker_name, docker_id, port, | |
tags, check, check_args): | |
url = "http://localhost:8500/v1/agent/service/register" | |
if (check): | |
data = {'ID': docker_id, | |
'Name': docker_name, | |
'Port': port, | |
'Tags': [tags], | |
'Check': {'Script': "/checks/" + check + " " + check_args, | |
'Interval': "60s" | |
} | |
} | |
else: | |
data = {'ID': docker_id, | |
'Name': docker_name, | |
'Port': port, | |
'Tags': [tags] | |
} | |
req = urllib2.Request(url, json.dumps(data)) | |
try: | |
response = urllib2.urlopen(req) | |
content = (response.read()) | |
except urllib2.HTTPError, e: | |
module.fail_json(msg="Consul Registration Error") | |
module.exit_json(changed=True, msg=" Registered Service: " + docker_id) | |
def deregister_service(module, docker_id, docker_name, docker_remove): | |
url = "http://localhost:8500/v1/agent/service/deregister/" | |
req = urllib2.Request(url + docker_id) | |
try: | |
content = urllib2.urlopen(req) | |
except urllib2.HTTPError, e: | |
module.fail_json(msg="Could not deregister service: " + docker_id) | |
if (docker_remove): | |
import docker | |
try: | |
docker.remove_container(docker_name) | |
module.exit_json(changed=True, | |
msg="Deregistered Service and removed Container: \ | |
" + docker_id) | |
except: | |
pass | |
module.exit_json(changed=True, msg="Deregistered Service: " + docker_id) | |
def check_docker_running(docker_name): | |
import docker | |
c = docker.Client(base_url='unix://var/run/docker.sock', | |
version='1.11', | |
timeout=10) | |
containers = c.containers(quiet=False, all=False, trunc=True, latest=False, | |
since=None, before=None, limit=-1) | |
for x in range(len(containers)): | |
if docker_name in containers[x]["Names"][0]: | |
print containers[x]["Names"][0] | |
if "Up" in containers[x]["Status"]: | |
return True | |
def check_service_registered(module, docker_name, docker_id): | |
url = "http://localhost:8500/v1/agent/services" | |
req = urllib2.Request(url) | |
try: | |
content = json.load(urllib2.urlopen(req)) | |
except urllib2.HTTPError, e: | |
module.fail_json(msg="Could not check service: " + docker_id) | |
try: | |
if docker_name == content[docker_id]["Service"]: | |
return True | |
else: | |
return False | |
except KeyError, e: | |
return False | |
def main(): | |
module = AnsibleModule( | |
argument_spec=dict( | |
docker_name=dict(required=True), | |
docker_id=dict(required=False), | |
port=dict(required=True), | |
tags=dict(required=False), | |
check=dict(require=False), | |
check_args=dict(required=False), | |
docker_remove=dict(required=False) | |
), | |
supports_check_mode=False | |
) | |
docker_name = module.params.get('docker_name') | |
docker_id = module.params.get('docker_id') or docker_name | |
port = module.params.get('port') | |
tags = module.params.get('tags') or None | |
check = module.params.get('check') or None | |
check_args = module.params.get('check_args') or "" | |
docker_remove = module.params.get('docker_remove') or True | |
docker_running = check_docker_running(docker_name) | |
service_registered = check_service_registered(module, | |
docker_name, | |
docker_id) | |
if docker_running: | |
if service_registered: | |
module.exit_json(changed=False, | |
msg="Docker running and service registered") | |
else: | |
register_service(module, docker_name, docker_id, port, | |
tags, check, check_args) | |
else: | |
deregister_service(module, docker_id, docker_name, docker_remove) | |
# import module snippets | |
from ansible.module_utils.basic import * | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment