diff --git a/awx_collection/plugins/doc_fragments/auth.py b/awx_collection/plugins/doc_fragments/auth.py index 3cab718a7d..763fe94dcd 100644 --- a/awx_collection/plugins/doc_fragments/auth.py +++ b/awx_collection/plugins/doc_fragments/auth.py @@ -50,6 +50,11 @@ options: - If value not set, will try environment variable C(CONTROLLER_VERIFY_SSL) and then config files type: bool aliases: [ tower_verify_ssl ] + request_timeout: + description: + - Specify the timeout Ansible should use in requests to the controller host. + - Defaults to 10s, but this is handled by the shared module_utils code + type: float controller_config_file: description: - Path to the controller config file. diff --git a/awx_collection/plugins/doc_fragments/auth_plugin.py b/awx_collection/plugins/doc_fragments/auth_plugin.py index 5a3a12b0e0..b46eaf6bbf 100644 --- a/awx_collection/plugins/doc_fragments/auth_plugin.py +++ b/awx_collection/plugins/doc_fragments/auth_plugin.py @@ -68,6 +68,14 @@ options: why: Collection name change alternatives: 'CONTROLLER_VERIFY_SSL' aliases: [ validate_certs ] + request_timeout: + description: + - Specify the timeout Ansible should use in requests to the controller host. + - Defaults to 10 seconds + - This will not work with the export or import modules. + type: float + env: + - name: CONTROLLER_REQUEST_TIMEOUT notes: - If no I(config_file) is provided we will attempt to use the tower-cli library diff --git a/awx_collection/plugins/module_utils/controller_api.py b/awx_collection/plugins/module_utils/controller_api.py index 19ce497852..0c5c191655 100644 --- a/awx_collection/plugins/module_utils/controller_api.py +++ b/awx_collection/plugins/module_utils/controller_api.py @@ -51,6 +51,7 @@ class ControllerModule(AnsibleModule): controller_username=dict(required=False, aliases=['tower_username'], fallback=(env_fallback, ['CONTROLLER_USERNAME', 'TOWER_USERNAME'])), controller_password=dict(no_log=True, aliases=['tower_password'], required=False, fallback=(env_fallback, ['CONTROLLER_PASSWORD', 'TOWER_PASSWORD'])), validate_certs=dict(type='bool', aliases=['tower_verify_ssl'], required=False, fallback=(env_fallback, ['CONTROLLER_VERIFY_SSL', 'TOWER_VERIFY_SSL'])), + request_timeout=dict(type='float', required=False, fallback=(env_fallback, ['CONTROLLER_REQUEST_TIMEOUT'])), controller_oauthtoken=dict( type='raw', no_log=True, aliases=['tower_oauthtoken'], required=False, fallback=(env_fallback, ['CONTROLLER_OAUTH_TOKEN', 'TOWER_OAUTH_TOKEN']) ), @@ -63,12 +64,14 @@ class ControllerModule(AnsibleModule): 'username': 'controller_username', 'password': 'controller_password', 'verify_ssl': 'validate_certs', + 'request_timeout': 'request_timeout', 'oauth_token': 'controller_oauthtoken', } host = '127.0.0.1' username = None password = None verify_ssl = True + request_timeout = 10 oauth_token = None oauth_token_id = None authenticated = False @@ -304,7 +307,7 @@ class ControllerAPIModule(ControllerModule): kwargs['supports_check_mode'] = True super().__init__(argument_spec=argument_spec, direct_params=direct_params, error_callback=error_callback, warn_callback=warn_callback, **kwargs) - self.session = Request(cookies=CookieJar(), validate_certs=self.verify_ssl) + self.session = Request(cookies=CookieJar(), timeout=self.request_timeout, validate_certs=self.verify_ssl) if 'update_secrets' in self.params: self.update_secrets = self.params.pop('update_secrets') @@ -500,7 +503,14 @@ class ControllerAPIModule(ControllerModule): data = dumps(kwargs.get('data', {})) try: - response = self.session.open(method, url.geturl(), headers=headers, validate_certs=self.verify_ssl, follow_redirects=True, data=data) + response = self.session.open( + method, url.geturl(), + headers=headers, + timeout=self.request_timeout, + validate_certs=self.verify_ssl, + follow_redirects=True, + data=data + ) except (SSLValidationError) as ssl_err: self.fail_json(msg="Could not establish a secure connection to your host ({1}): {0}.".format(url.netloc, ssl_err)) except (ConnectionError) as con_err: @@ -612,6 +622,7 @@ class ControllerAPIModule(ControllerModule): 'POST', api_token_url, validate_certs=self.verify_ssl, + timeout=self.request_timeout, follow_redirects=True, force_basic_auth=True, url_username=self.username, @@ -988,6 +999,7 @@ class ControllerAPIModule(ControllerModule): 'DELETE', api_token_url, validate_certs=self.verify_ssl, + timeout=self.request_timeout, follow_redirects=True, force_basic_auth=True, url_username=self.username, diff --git a/awx_collection/tests/integration/targets/project/tasks/main.yml b/awx_collection/tests/integration/targets/project/tasks/main.yml index f622af8e6f..407292ec23 100644 --- a/awx_collection/tests/integration/targets/project/tasks/main.yml +++ b/awx_collection/tests/integration/targets/project/tasks/main.yml @@ -53,6 +53,23 @@ that: - result is not changed + - name: Create a git project and wait with short request timeout. + project: + name: "{{ project_name1 }}" + organization: Default + scm_type: git + scm_url: https://github.com/ansible/test-playbooks + wait: true + state: exists + request_timeout: .001 + register: result + ignore_errors: true + + - assert: + that: + - result is failed + - "'timed out' in result.msg" + - name: Delete a git project without credentials and wait project: name: "{{ project_name1 }}"