2
votes

ansible/ansible-playbook version: 2.1.2.0 / 2.2.0.0

I'm trying to install a package using yum/apt but as the repository for installing the package is sitting in packagecloud.io, sometimes I'm getting an error message (when I'm passing -vvv while running my ansible-playbook).

[Errno 14] curl#56 - \"TCP connection reset by peer\"\nTrying other mirror. ...some ansible verbose text here.. [Errno 256] No more mirrors to try.

This doesn't happen all the time. If I re-run the same playbook again, it works fine, so the failure (connection reset) is randomly coming.

To overcome this issue, I wanted to use Ansible's until loop which we have to use with a register variable.

So, I created this playbook action by referring Ansible doc for how to use until loop here, but using that syntax I'm getting a 'dictionary' error saying that result variable (registered) dict doesn't have any key named stdout. Then I tried to use result.rc (key field) and it worked on CentOS machine but failed on an Ubuntu 14.x trusty vagrant machine with the following result.rc dict not present error:

- name: Install telegraf agent/collector (RedHat)
  yum:
    name: "{{ agent_collector }}"
    state: "installed"
  when: ( ansible_os_family == 'RedHat' and company_install_collector == true )
  register: result
  until: result.stdout.find("Installed:") != -1
  #The following works in CentOS/RedHat
  #until: result.rc == 0  

 - debug: msg="result (redhat) = {{ result }}"

OR (Update to my question which was obvious)

- name: Install Company Proxy (Ubuntu)
  apt:
    name: "{{ company_proxy_pkg }}"
    state: "installed"
  when: ( ansible_distribution == 'Ubuntu' and company_install_proxy == true )
  register: result
  until: result.rc == 0

 - debug: msg="result (ubuntu) = {{ result }}"

Getting the following error messages (result.stdout -- dict object' has no attribute 'stdout' in both RedHat/CentOS and Ubuntu but getting dict object has no attribute 'rc' only in Ubuntu server) :

fatal: [localhost]: FAILED! => {"failed": true, "msg": "The conditional check '(result.stdout.find(\"Installed:\") != -1)' failed. The error was: error while evaluating conditional ((result.stdout.find(\"Installed:\") != -1)): 'dict object' has no attribute 'stdout'"}

and

fatal: [localhost]: FAILED! => {
    "failed": true, 
    "msg": "The conditional check 'result.rc == 0' failed. The error was: error while evaluating conditional (result.rc == 0): 'dict object' has no attribute 'rc'"
}

Why the register variable (result in my case) is not having stdout or rc dict/variables when the documentation says that those exist or if I can see them in -vvv verbose output on one OS but it doesn't show up on the other OS?

2
Thanks, but my question is valid. Thanks for your reply.AKS
I think I found the problem. To narrow down what's in result variable, I used ignore_errors: yes and in the next debug statement, I got all the output for result variable. The issue is this. In Ubuntu, there's no result.rc but result.stdout is there so I can use until with result.stdout.find("...text to search") == 0 or sometime like that. In RedHat, at least in the version of ansible that I'm using, there's NO result.stdout so I can't use the above statement so I have to use until: result.rc == 0. That's the answer, but I need more testing to prove this.AKS
In Ubuntu result.stdout is getting set only if the action is successful, for a failed action, result doesn't have .stdout dict set so I need to look for something else. In CentOS, Im getting stdout and rc set if successful but getting only rc dict set with status 1 if that action fails due to some reason.AKS

2 Answers

4
votes

Using tests as filters is deprecated. Instead of using result|succeeded use result is succeeded. This feature will be removed in version 2.9.

3
votes

Correct answer and findings:

  1. In CentOS, if the action is successful and if the registered variable result is set, then a user can see these dict variables for ex: result.rc being 0, result.stdout = "something\nsomethingEsle\netc etc etc" and/or result.stdout_lines = "...same as above..." and result.results in some cases. If the action was failed, then I couldn't see result.stdout getting set in my case for using yum module if that failed due to connection reset or other reason. In that case, the only dict variable available for a failed action was result.rc != 0. Thus, in the until loop, until: result.rc == 0 condition worked for both successful/failed case for CentOS.

  2. In Ubuntu, if the apt module action was successful, I got result.stdout and result.stdout_lines variables set but no result.rc dict variable set. For a failed operation, there's was no result.stdout or result.stdout_lines or result.rc dict variables set. SO, in case of Ubuntu, I couldn't use until loop using one of these dictionary variables.

The only workaround I can think of is, to wrap the apt-get install <pacakge> in a script and use until loop in BASH etc to do what Ansible is doing. At least, that'll be little easier to code and if the exit code is not 0, then I can use until.

But, I finally found a solution, which works in Ubuntu for both successful and failed cases:

Jinja2 filters may help i.e. when: result|failed therefore, if I have to use a registered variable result for a FAILED condition, then using with until, I'll use it (opposite of failed status) i.e. as:

until: result|succeeded

The good thing is that, the above until statement will work for both CentOS and Ubuntu and for both successful/failed states.