Add socket timeout to uri module.

The uri module can be configured to abort after a specified timeout if
it cannot connect to the configured uri. This prevents a uri action from
hanging indefinitely when the remote endpoint cannot be reached because
it is unavailable, there is a firewall in place etc. The default behavior
is left unchanged: timeout=None

This change also introduces a new type for module_parameters: int
Code was added to perform conversion from string -> int type in
module_common.py.

The new type was required in order to play nice with httplib2 which
refuses to accept (and convert) anything other than a numeric type for
the timeout value.
This commit is contained in:
Grant Gavares 2013-03-02 17:27:09 -08:00
parent b130716b61
commit cd51c7f234
2 changed files with 16 additions and 3 deletions

View file

@ -597,6 +597,12 @@ class AnsibleModule(object):
self.params[k] = self.boolean(value) self.params[k] = self.boolean(value)
else: else:
is_invalid = True is_invalid = True
elif wanted == 'int':
if not isinstance(value, int):
if isinstance(value, basestring):
self.params[k] = int(value)
else:
is_invalid = True
else: else:
self.fail_json(msg="implementation error: unknown type %s requested for %s" % (wanted, k)) self.fail_json(msg="implementation error: unknown type %s requested for %s" % (wanted, k))

View file

@ -103,6 +103,11 @@ options:
- A valid, numeric, HTTP status code that signifies success of the request. - A valid, numeric, HTTP status code that signifies success of the request.
required: false required: false
default: 200 default: 200
timeout:
description:
- The socket level timeout in seconds
required: false
default: no timeout
HEADER_: HEADER_:
description: Any parameter starting with "HEADER_" is a sent with your request as a header. For example, HEADER_Content-Type="application/json" would send the header "Content-Type" along with your request with a value of "application/json". description: Any parameter starting with "HEADER_" is a sent with your request as a header. For example, HEADER_Content-Type="application/json" would send the header "Content-Type" along with your request with a value of "application/json".
required: false required: false
@ -217,12 +222,12 @@ def url_filename(url):
return fn return fn
def uri(module, url, dest, user, password, body, method, headers, redirects): def uri(module, url, dest, user, password, body, method, headers, redirects, socket_timeout):
# To debug # To debug
#httplib2.debug = 4 #httplib2.debug = 4
# Create a Http object and set some default options. # Create a Http object and set some default options.
h = httplib2.Http(disable_ssl_certificate_validation=True) h = httplib2.Http(disable_ssl_certificate_validation=True, timeout=socket_timeout)
h.follow_all_redirects = redirects h.follow_all_redirects = redirects
h.forward_authorization_headers = True h.forward_authorization_headers = True
@ -273,6 +278,7 @@ def main():
creates = dict(required=False, default=None), creates = dict(required=False, default=None),
removes = dict(required=False, default=None), removes = dict(required=False, default=None),
status_code = dict(required=False, default="200"), status_code = dict(required=False, default="200"),
timeout = dict(required=False, default=None, type='int'),
), ),
check_invalid_arguments=False, check_invalid_arguments=False,
add_file_common_args=True add_file_common_args=True
@ -295,6 +301,7 @@ def main():
creates = module.params['creates'] creates = module.params['creates']
removes = module.params['removes'] removes = module.params['removes']
status_code = module.params['status_code'] status_code = module.params['status_code']
socket_timeout = module.params['timeout']
# Grab all the http headers. Need this hack since passing multi-values is currently a bit ugly. (e.g. headers='{"Content-Type":"application/json"}') # Grab all the http headers. Need this hack since passing multi-values is currently a bit ugly. (e.g. headers='{"Content-Type":"application/json"}')
dict_headers = {} dict_headers = {}
@ -340,7 +347,7 @@ def main():
dest = os.path.join(dest, url_filename(url)) dest = os.path.join(dest, url_filename(url))
# Make the request # Make the request
resp, content = uri(module, url, dest, user, password, body, method, dict_headers, redirects) resp, content = uri(module, url, dest, user, password, body, method, dict_headers, redirects, socket_timeout)
# Write the file out if requested # Write the file out if requested
if dest is not None: if dest is not None: