13

I am getting a count from powershell command and registering it on variable. I have to use that count in when condition. I have changed it to int before using it in when condition too. Still that task ( mail notification) is getting skipped, eventhough the count is 0 here. Can someone tell me what I am doing wrong here. Below is the code I am executing

      - name: Get message_count
        shell:  echo "{{ (output.stdout | from_json).MessageCount  }}"
        register: message_count   #message_count is Zero here
        delegate_to: localhost
  - set_fact:
      countt: "{{ message_count | int}}"    

#tried converting to integer before passing to condition using set_fact

      - debug: var=countt
      - name: send mail notification
        mail:
           host: abc.zzzz.net
           port: 25
           from: <noreply@controlnode.com>
           to:
           - abc@xyz.com
       subject: Test mail sent from core server 
       body: Test mail sent from core server        
    delegate_to: localhost
    when: countt==0

saffron
  • 173

2 Answers2

14

here's what I did to make it work:

---
- name: answer serverfault
  hosts: all
  become: yes

tasks: - name: Get message_count shell: ls /tmp/empty | wc -l register: tmp_count delegate_to: localhost - debug: var=tmp_count.stdout - name: do something else when tmp_count.stdout == 0 shell: echo "I am doing it" delegate_to: localhost when: tmp_count.stdout | int == 0

and here's the playbook run result:

ripper@mini-ripper:~/Devel/ansible$ ansip ./test_playbook.yml  -i localhost,

PLAY [answer serverfault] **************************************************************************************************************************************************************************************

TASK [Gathering Facts] ******************************************************************************************************************************************************************************************** [WARNING]: Platform linux on host localhost is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. ok: [localhost]

TASK [Get message_count] ****************************************************************************************************************************************************************************************** changed: [localhost -> localhost]

TASK [debug] ****************************************************************************************************************************************************************************************************** ok: [localhost] => { "tmp_count.stdout": "0" }

TASK [do something else when tmp_count.stdout == 0] *************************************************************************************************************************************************************** changed: [localhost -> localhost]

PLAY RECAP ******************************************************************************************************************************************************************************************************** localhost : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

so to recap:

  • you should check if the register variable isn't more complex structure - it usually is
  • you don't need another custom fact
  • you need to convert your variable without using {{ }} in when condition
1

You can, of course, remember that the thing you wanted to be an int is actually converted to a string by Jinja2 in a set_fact. So you can perform the int conversion every time you want to use it thus, as other answers illustrate- both here and in other Stack Overflow answers.

But if you're convinced you want a genuine int, Ansible's loop construct uses more strict type checking. So you can kludge a result like this:

---
- name: Get HugePages_Total from /proc/meminfo
  shell: grep '^HugePages_Total' /proc/meminfo | awk '{print $2}'
  register: hugepages_total_line
  changed_when: False
  • name: Ensure integer conversion by looping set_fact: hugepages_total: "{{ item }}" loop: "{{ [hugepages_total_line.stdout_lines[0] | int] }}"

  • name: Verify hugepages_total type and value debug: msg: - "HUGEPAGES: {{ hugepages_total }} {{ hugepages_total | type_debug }}" - "stdout: {{ hugepages_total_line.stdout[0] }}" - "stdout type: {{ hugepages_total_line.stdout[0] | type_debug }}"

...

Here, we store hugepages_total_line.stdout_lines[0] as an int in a one-element list, and pass that to the loop. Within the loop, "{{ item }}" is thankfully not cast to a string. hugepages_total will be an int.

Obviously, hugepages_total will be set to the last element in the list, so you need to craft your list properly: make sure it has one element, is all. Using stdout_lines[0] guarantees it in this case.

The problem: You have probably noticed that Jinja2 converts all or almost all variable data to strings, when referenced thus:

set_fact:
  i_wish_it_was_an_int: "{{ var_containing_int | int }}"

i_wish_it_was_an_int will never be an int to Ansible, in this circumstance. To Jinja2's internals var_containing_int is converted to an int, but it is converted back to a string before i_wish_it_was_an_int is assigned. So the | int in this case is a no-op.

Tested using Ansible 2.9.27.

Mike S
  • 1,317