From 366f163495911bf987f7f315b25130bc80e0b32d Mon Sep 17 00:00:00 2001 From: Steve Gargan Date: Mon, 27 Apr 2015 13:40:21 +0100 Subject: [PATCH] use module.fail_json to report import errors. document valid duration units --- lib/ansible/modules/extras/clustering/consul | 20 +++++++--- .../modules/extras/clustering/consul_acl | 31 +++++++++----- .../modules/extras/clustering/consul_kv | 19 ++++++--- .../modules/extras/clustering/consul_session | 40 +++++++++++++------ 4 files changed, 78 insertions(+), 32 deletions(-) diff --git a/lib/ansible/modules/extras/clustering/consul b/lib/ansible/modules/extras/clustering/consul index fec55726539..5db79e20c40 100644 --- a/lib/ansible/modules/extras/clustering/consul +++ b/lib/ansible/modules/extras/clustering/consul @@ -37,6 +37,9 @@ description: result this does not attempt to determine changes and will always report a changed occurred. An api method is planned to supply this metadata so at that stage change management will be added. +requirements: + - python-consul + - requests version_added: "1.9" author: Steve Gargan (steve.gargan@gmail.com) options: @@ -172,13 +175,11 @@ except ImportError: try: import consul + from requests.exceptions import ConnectionError + python_consul_installed = True except ImportError, e: - print "failed=True msg='python-consul required for this module. "\ - "see http://python-consul.readthedocs.org/en/latest/#installation'" - sys.exit(1) - -from requests.exceptions import ConnectionError - + python_consul_installed = False + def register_with_consul(module): state = module.params.get('state') @@ -462,6 +463,10 @@ class ConsulCheck(): except: pass +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(): module = AnsibleModule( @@ -485,6 +490,9 @@ def main(): ), supports_check_mode=False, ) + + test_dependencies(module) + try: register_with_consul(module) except ConnectionError, e: diff --git a/lib/ansible/modules/extras/clustering/consul_acl b/lib/ansible/modules/extras/clustering/consul_acl index 5e50c54431e..c481b780a64 100644 --- a/lib/ansible/modules/extras/clustering/consul_acl +++ b/lib/ansible/modules/extras/clustering/consul_acl @@ -23,7 +23,11 @@ short_description: "manipulate consul acl keys and rules" description: - allows the addition, modification and deletion of ACL keys and associated rules in a consul cluster via the agent. For more details on using and - configuring ACLs, see https://www.consul.io/docs/internals/acl.html + configuring ACLs, see https://www.consul.io/docs/internals/acl.html. +requirements: + - python-consul + - pyhcl + - requests version_added: "1.9" author: Steve Gargan (steve.gargan@gmail.com) options: @@ -91,17 +95,16 @@ import urllib2 try: import consul + from requests.exceptions import ConnectionError + python_consul_installed = True except ImportError, e: - print "failed=True msg='python-consul required for this module. "\ - "see http://python-consul.readthedocs.org/en/latest/#installation'" - sys.exit(1) + python_consul_installed = False try: import hcl + pyhcl_installed = True except ImportError: - print "failed=True msg='pyhcl required for this module."\ - " see https://pypi.python.org/pypi/pyhcl'" - sys.exit(1) + pyhcl_installed = False from requests.exceptions import ConnectionError @@ -271,6 +274,7 @@ class Rule: def __str__(self): return '%s %s' % (self.key, self.policy) + def get_consul_api(module, token=None): if not token: token = token = module.params.get('token') @@ -278,6 +282,14 @@ def get_consul_api(module, token=None): port=module.params.get('port'), token=token) +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") + + if not pyhcl_installed: + module.fail_json( msg="pyhcl required for this module."\ + " see https://pypi.python.org/pypi/pyhcl") def main(): argument_spec = dict( @@ -291,9 +303,10 @@ def main(): token_type=dict( required=False, choices=['client', 'management'], default='client') ) + module = AnsibleModule(argument_spec, supports_check_mode=False) - module = AnsibleModule(argument_spec, supports_check_mode=True) - + test_dependencies(module) + try: execute(module) except ConnectionError, e: diff --git a/lib/ansible/modules/extras/clustering/consul_kv b/lib/ansible/modules/extras/clustering/consul_kv index a9132a3d1c2..e5a010a8c18 100644 --- a/lib/ansible/modules/extras/clustering/consul_kv +++ b/lib/ansible/modules/extras/clustering/consul_kv @@ -27,6 +27,9 @@ description: the indices, flags and session are returned as 'value'. If the key represents a prefix then Note that when a value is removed, the existing value if any is returned as part of the results. +requirements: + - python-consul + - requests version_added: "1.9" author: Steve Gargan (steve.gargan@gmail.com) options: @@ -126,10 +129,10 @@ except ImportError: try: import consul + from requests.exceptions import ConnectionError + python_consul_installed = True except ImportError, e: - print """failed=True msg='python-consul required for this module. \ - see http://python-consul.readthedocs.org/en/latest/#installation'""" - sys.exit(1) + python_consul_installed = False from requests.exceptions import ConnectionError @@ -222,7 +225,11 @@ def get_consul_api(module, token=None): port=module.params.get('port'), token=module.params.get('token')) - +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( @@ -238,8 +245,10 @@ def main(): value=dict(required=False) ) - module = AnsibleModule(argument_spec, supports_check_mode=True) + module = AnsibleModule(argument_spec, supports_check_mode=False) + test_dependencies(module) + try: execute(module) except ConnectionError, e: diff --git a/lib/ansible/modules/extras/clustering/consul_session b/lib/ansible/modules/extras/clustering/consul_session index 7088dc275ba..8e6516891d2 100644 --- a/lib/ansible/modules/extras/clustering/consul_session +++ b/lib/ansible/modules/extras/clustering/consul_session @@ -25,6 +25,9 @@ description: 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-consul + - requests version_added: "1.9" author: Steve Gargan (steve.gargan@gmail.com) options: @@ -50,7 +53,8 @@ options: 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. + acquired until this delay has expired. Valid units for delays + include 'ns', 'us', 'ms', 's', 'm', 'h' default: 15s required: false node: @@ -99,7 +103,7 @@ EXAMPLES = ''' - name: register a session with lock_delay consul_session: name: session_with_delay - delay: 20 + delay: 20s - name: retrieve info about session by id consul_session: id=session_id state=info @@ -113,12 +117,10 @@ import urllib2 try: import consul + from requests.exceptions import ConnectionError + python_consul_installed = True except ImportError, e: - print "failed=True msg='python-consul required for this module. see "\ - "http://python-consul.readthedocs.org/en/latest/#installation'" - sys.exit(1) - -from requests.errors import ConnectionError + python_consul_installed = False def execute(module): @@ -182,11 +184,11 @@ def update_session(module): changed = True try: - + session = consul.session.create( name=name, node=node, - lock_delay=delay, + lock_delay=validate_duration('delay', delay), dc=datacenter, checks=checks ) @@ -219,15 +221,27 @@ def remove_session(module): module.fail_json(msg="Could not remove session with id '%s' %s" % ( session_id, e)) +def validate_duration(name, duration): + if duration: + duration_units = ['ns', 'us', 'ms', 's', 'm', 'h'] + if not any((duration.endswith(suffix) for suffix in duration_units)): + raise Exception('Invalid %s %s you must specify units (%s)' % + (name, duration, ', '.join(duration_units))) + return duration 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), + delay=dict(required=False,type='str', default='15s'), host=dict(default='localhost'), port=dict(default=8500, type='int'), id=dict(required=False), @@ -237,8 +251,10 @@ def main(): choices=['present', 'absent', 'info', 'node', 'list']) ) - module = AnsibleModule(argument_spec, supports_check_mode=True) - + module = AnsibleModule(argument_spec, supports_check_mode=False) + + test_dependencies(module) + try: execute(module) except ConnectionError, e: