Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse async response in async action. #16534

Merged
merged 5 commits into from
Jul 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 0 additions & 9 deletions lib/ansible/executor/task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,15 +458,6 @@ def _execute(self, variables=None):
vars_copy[self._task.register] = wrap_var(result.copy())

if self._task.async > 0:
# the async_wrapper module returns dumped JSON via its stdout
# response, so we parse it here and replace the result
try:
if 'skipped' in result and result['skipped'] or 'failed' in result and result['failed']:
return result
result = json.loads(result.get('stdout'))
except (TypeError, ValueError) as e:
return dict(failed=True, msg=u"The async task did not return valid JSON: %s" % to_unicode(e))

if self._task.poll > 0:
result = self._poll_async_result(result=result, templar=templar)

Expand Down
7 changes: 7 additions & 0 deletions lib/ansible/plugins/action/async.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,11 @@ def run(self, tmp=None, task_vars=None):

result['changed'] = True

if 'skipped' in result and result['skipped'] or 'failed' in result and result['failed']:
return result

# the async_wrapper module returns dumped JSON via its stdout
# response, so we parse it here and replace the result
result = self._parse_returned_data(result)

return result
9 changes: 8 additions & 1 deletion test/integration/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ UNAME := $(shell uname | tr '[:upper:]' '[:lower:]')

all: setup other non_destructive destructive

other: test_test_infra parsing test_var_precedence unicode test_templating_settings environment test_connection includes blocks pull check_mode test_hash test_handlers test_group_by test_vault test_tags test_lookup_paths no_log test_gathering_facts test_binary_modules
other: test_test_infra parsing test_var_precedence unicode test_templating_settings environment test_connection includes blocks pull check_mode test_hash test_handlers test_group_by test_vault test_tags test_lookup_paths no_log test_gathering_facts test_binary_modules test_async

test_test_infra:
# ensure fail/assert work locally and can stop execution with non-zero exit code
Expand Down Expand Up @@ -302,3 +302,10 @@ test_binary_modules:
cd ..; \
rm -rf $$mytmpdir; \
ANSIBLE_HOST_KEY_CHECKING=false ansible-playbook test_binary_modules.yml -i $(INVENTORY) -v $(TEST_FLAGS)

test_async:
# Verify that extra data before module JSON output during async call is ignored.
LC_ALL=bogus ansible-playbook test_async.yml -i $(INVENTORY) -e outputdir=$(TEST_DIR) -v $(TEST_FLAGS)
# Verify that the warning exists by examining debug output.
ANSIBLE_DEBUG=1 LC_ALL=bogus ansible-playbook test_async.yml -i $(INVENTORY) -e outputdir=$(TEST_DIR) -v $(TEST_FLAGS) \
| grep -q 'bash: warning: setlocale: LC_ALL: cannot change locale (bogus)'
10 changes: 10 additions & 0 deletions test/integration/test_async.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- hosts: testhost3
gather_facts: false
tasks:
# make sure non-JSON data before module output is ignored
- name: async ping with invalid locale via ssh
ping:
async: 3
poll: 1
register: result
- debug: var=result
6 changes: 4 additions & 2 deletions test/units/executor/test_task_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from ansible.executor.task_executor import TaskExecutor
from ansible.playbook.play_context import PlayContext
from ansible.plugins import action_loader, lookup_loader
from ansible.parsing.yaml.objects import AnsibleUnicode

from units.mock.loader import DictDataLoader

Expand Down Expand Up @@ -375,6 +376,7 @@ def test_task_executor_execute(self):
# here: on Python 2 comparing MagicMock() > 0 returns True, and the
# other reason is that if I specify 0 here, the test fails. ;)
mock_task.async = 1
mock_task.poll = 0

mock_play_context = MagicMock()
mock_play_context.post_validate.return_value = None
Expand Down Expand Up @@ -408,11 +410,11 @@ def test_task_executor_execute(self):
mock_action.run.return_value = dict(ansible_facts=dict())
res = te._execute()

mock_task.changed_when = "1 == 1"
mock_task.changed_when = MagicMock(return_value=AnsibleUnicode("1 == 1"))
res = te._execute()

mock_task.changed_when = None
mock_task.failed_when = "1 == 1"
mock_task.failed_when = MagicMock(return_value=AnsibleUnicode("1 == 1"))
res = te._execute()

mock_task.failed_when = None
Expand Down