diff options
Diffstat (limited to 'lib/ansible/modules/extras/clustering/consul_session.py')
-rw-r--r-- | lib/ansible/modules/extras/clustering/consul_session.py | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/lib/ansible/modules/extras/clustering/consul_session.py b/lib/ansible/modules/extras/clustering/consul_session.py new file mode 100644 index 0000000000..4d73356139 --- /dev/null +++ b/lib/ansible/modules/extras/clustering/consul_session.py @@ -0,0 +1,282 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# (c) 2015, Steve Gargan <steve.gargan@gmail.com> +# +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see <http://www.gnu.org/licenses/>. + +DOCUMENTATION = """ +module: consul_session +short_description: "manipulate consul sessions" +description: + - allows the addition, modification and deletion of sessions in a consul + cluster. These sessions can then be used in conjunction with key value pairs + to implement distributed locks. In depth documentation for working with + sessions can be found here http://www.consul.io/docs/internals/sessions.html +requirements: + - "python >= 2.6" + - python-consul + - requests +version_added: "2.0" +author: "Steve Gargan @sgargan" +options: + state: + description: + - whether the session should be present i.e. created if it doesn't + exist, or absent, removed if present. If created, the ID for the + session is returned in the output. If absent, the name or ID is + required to remove the session. Info for a single session, all the + sessions for a node or all available sessions can be retrieved by + specifying info, node or list for the state; for node or info, the + node name or session id is required as parameter. + required: false + choices: ['present', 'absent', 'info', 'node', 'list'] + default: present + name: + description: + - the name that should be associated with the session. This is opaque + to Consul and not required. + required: false + default: None + delay: + description: + - the optional lock delay that can be attached to the session when it + is created. Locks for invalidated sessions ar blocked from being + acquired until this delay has expired. Durations are in seconds + default: 15 + required: false + node: + description: + - the name of the node that with which the session will be associated. + by default this is the name of the agent. + required: false + default: None + datacenter: + description: + - name of the datacenter in which the session exists or should be + created. + required: false + default: None + checks: + description: + - a list of checks that will be used to verify the session health. If + all the checks fail, the session will be invalidated and any locks + associated with the session will be release and can be acquired once + the associated lock delay has expired. + required: false + default: None + host: + description: + - host of the consul agent defaults to localhost + required: false + default: localhost + port: + description: + - the port on which the consul agent is running + required: false + default: 8500 + scheme: + description: + - the protocol scheme on which the consul agent is running + required: false + default: http + version_added: "2.1" + validate_certs: + description: + - whether to verify the tls certificate of the consul agent + required: false + default: True + version_added: "2.1" + behavior: + description: + - the optional behavior that can be attached to the session when it + is created. This can be set to either ‘release’ or ‘delete’. This + controls the behavior when a session is invalidated. + default: release + required: false + version_added: "2.2" +""" + +EXAMPLES = ''' +- name: register basic session with consul + consul_session: + name: session1 + +- name: register a session with an existing check + consul_session: + name: session_with_check + checks: + - existing_check_name + +- name: register a session with lock_delay + consul_session: + name: session_with_delay + delay: 20s + +- name: retrieve info about session by id + consul_session: id=session_id state=info + +- name: retrieve active sessions + consul_session: state=list +''' + +try: + import consul + from requests.exceptions import ConnectionError + python_consul_installed = True +except ImportError, e: + python_consul_installed = False + +def execute(module): + + state = module.params.get('state') + + if state in ['info', 'list', 'node']: + lookup_sessions(module) + elif state == 'present': + update_session(module) + else: + remove_session(module) + +def lookup_sessions(module): + + datacenter = module.params.get('datacenter') + + state = module.params.get('state') + consul_client = get_consul_api(module) + try: + if state == 'list': + sessions_list = consul_client.session.list(dc=datacenter) + #ditch the index, this can be grabbed from the results + if sessions_list and sessions_list[1]: + sessions_list = sessions_list[1] + module.exit_json(changed=True, + sessions=sessions_list) + elif state == 'node': + node = module.params.get('node') + if not node: + module.fail_json( + msg="node name is required to retrieve sessions for node") + sessions = consul_client.session.node(node, dc=datacenter) + module.exit_json(changed=True, + node=node, + sessions=sessions) + elif state == 'info': + session_id = module.params.get('id') + if not session_id: + module.fail_json( + msg="session_id is required to retrieve indvidual session info") + + session_by_id = consul_client.session.info(session_id, dc=datacenter) + module.exit_json(changed=True, + session_id=session_id, + sessions=session_by_id) + + except Exception, e: + module.fail_json(msg="Could not retrieve session info %s" % e) + + +def update_session(module): + + name = module.params.get('name') + delay = module.params.get('delay') + checks = module.params.get('checks') + datacenter = module.params.get('datacenter') + node = module.params.get('node') + behavior = module.params.get('behavior') + + consul_client = get_consul_api(module) + + try: + session = consul_client.session.create( + name=name, + behavior=behavior, + node=node, + lock_delay=delay, + dc=datacenter, + checks=checks + ) + module.exit_json(changed=True, + session_id=session, + name=name, + behavior=behavior, + delay=delay, + checks=checks, + node=node) + except Exception, e: + module.fail_json(msg="Could not create/update session %s" % e) + + +def remove_session(module): + session_id = module.params.get('id') + if not session_id: + module.fail_json(msg="""A session id must be supplied in order to + remove a session.""") + + consul_client = get_consul_api(module) + + try: + consul_client.session.destroy(session_id) + + module.exit_json(changed=True, + session_id=session_id) + except Exception, e: + module.fail_json(msg="Could not remove session with id '%s' %s" % ( + session_id, e)) + +def get_consul_api(module): + return consul.Consul(host=module.params.get('host'), + port=module.params.get('port')) + +def test_dependencies(module): + if not python_consul_installed: + module.fail_json(msg="python-consul required for this module. "\ + "see http://python-consul.readthedocs.org/en/latest/#installation") + +def main(): + argument_spec = dict( + checks=dict(default=None, required=False, type='list'), + delay=dict(required=False,type='int', default='15'), + behavior=dict(required=False,type='str', default='release', + choices=['release', 'delete']), + host=dict(default='localhost'), + port=dict(default=8500, type='int'), + scheme=dict(required=False, default='http'), + validate_certs=dict(required=False, default=True), + id=dict(required=False), + name=dict(required=False), + node=dict(required=False), + state=dict(default='present', + choices=['present', 'absent', 'info', 'node', 'list']), + datacenter=dict(required=False) + ) + + module = AnsibleModule(argument_spec, supports_check_mode=False) + + test_dependencies(module) + + try: + execute(module) + except ConnectionError, e: + module.fail_json(msg='Could not connect to consul agent at %s:%s, error was %s' % ( + module.params.get('host'), module.params.get('port'), str(e))) + except Exception, e: + module.fail_json(msg=str(e)) + +# import module snippets +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() |