# Help Using an .stdout as a WHEN Condition

**URL:** <https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067>\
**Category:** Get Help\
**Created:** [December 26, 2023, 9:13pm UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067 "2023-12-26T21:13:18Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Symian](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/symian/32/8301_2.png) [@Symian](https://forum.ansible.com/u/Symian)\
**Post date:** [December 26, 2023, 9:13pm UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/1 "2023-12-26T21:13:18Z")

</div>

Hello. New to this wonderful Ansible thing. I am a database guy. I have an Oracle process that spits out a file that looks like this (but the value could be different at each run):

```auto
[oracle@lnx0016 scripts]$ more /tmp/impact.txt
  -12268.06

```

Then, within the same playbook, Ansible playbook parses it, and if the value is a negative (less than 0), it is supposed to kick off a whole another block.

```auto
    - name: opatch_direct | Export the Post-change Impact Score for for {{ db_name }}
      shell: 'cat /tmp/impact.txt'
      register: impact_score_literal

    - name: opatch_direct | GO / NOGO decision for {{ oracle_home }} and {{ db_name }}
      block:
...
      when: "'-' not in impact_score_literal.stdout"

```

I also tried a less than zero condition, but ignores it.  
I think there are two problems:

1. The number " -12268.06" has a heading empty space
2. The data type may be wrong? May be I should use something other than “cat”?

Here is the error

```auto
TASK [opatch_direct | Stop database ORCLCDB before rolling back 35740258 for /opt/oracle/product/21c/dbhome_1] ************************************************************************************************************************
task path: /home/oracle/ansible/playbooks/opatch_direct.yml:185
fatal: [lnx006]: FAILED! => 
  msg: |-
    The conditional check ''-' not in impact_score_literal.stdout' failed. The error was: error while evaluating conditional ('-' not in impact_score_literal.stdout): 'dict object' has no attribute 'stdout'
  
    The error appears to be in '/home/oracle/ansible/playbooks/opatch_direct.yml': line 185, column 11, but may
    be elsewhere in the file depending on the exact syntax problem.
  
    The offending line appears to be:
  
  
            - name: opatch_direct | Stop database {{db_name}} before rolling back {{ patch_id }} for {{ oracle_home }}
              ^ here
    We could be wrong, but this one looks like it might be an issue with
    missing quotes. Always quote template expression brackets when they
    start a value. For instance:
  
        with_items:
          - {{ foo }}
  
    Should be written as:
  
        with_items:
          - "{{ foo }}"

PLAY RECAP ****************************************************************************************************************************************************************************************************************************
lnx006 : ok=17 changed=12 unreachable=0 failed=1 skipped=1 rescued=0 ignored=0   

```

Here is the value of the .stdout for the condition check:

```auto
changed: [lnx006] => changed=true 
  cmd: cat /tmp/impact.txt
  delta: '0:00:00.004104'
  end: '2023-12-26 15:38:15.595984'
  invocation:
    module_args:
      _raw_params: cat /tmp/impact.txt
      _uses_shell: true
      argv: null
      chdir: null
      creates: null
      executable: null
      removes: null
      stdin: null
      stdin_add_newline: true
      strip_empty_ends: true
      warn: true
  rc: 0
  start: '2023-12-26 15:38:15.591880'
  stderr: ''
  stderr_lines: <omitted>
  stdout: ' -12268.06'
  stdout_lines: <omitted>

```

What I find interesting is that the condition works ONLY with an == sign, not \<\>. That value , if it matches the /tmp/impact.txt contents, works, meaning Ansible keeps rolling, follows the condition as it should. But that is not what I need. I need it to kick off the block only if the number is negative.

Please help  
Thanks  
Symian

---

<div class="post-metadata">

**Author:** ![Symian](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/symian/32/8301_2.png) [@Symian](https://forum.ansible.com/u/Symian)\
**Post date:** [December 26, 2023, 10:43pm UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/2 "2023-12-26T22:43:06Z")

</div>

Replying to self.  
This value in /tmp/impact.txt added by keyboard:

-6

```
  when: impact_score_literal.stdout > 0

```

It reads the -6, understands it will cause a performance degradation and then kicks off the correct block to rollback the Oracle database patch.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [December 27, 2023, 9:51am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/3 "2023-12-27T09:51:56Z")

</div>

Rather than `cat` you could use the [ansible.builtin.slurp module](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/slurp_module.html), to read the contents of the file, for example:

```yaml
- name: Slurp a base64 encoded version of the file
  ansible.builtin.slurp:
    src: /tmp/impact.txt
  register: file_b64encoded

- name: Decode the base64 encoded version of the file and set a variable
  ansible.builtin.set_fact:
    file_contents: "{{ file_b64encoded['content'] | ansible.builtin.b64decode | trim }}"

```

The `b64decode` filter is an [Ansible filter](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/b64decode_filter.html), the `trim` filter comes from [jinja2](https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.trim).

You can test the type using the [ansible.builtin.type\_debug filter](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/type_debug_filter.html):

```yaml
- name: Print the type of the file_contents variable
  ansible.builtin.debug:
    msg: "{{ file_contents | ansible.builtin.type_debug }}"

```

---

<div class="post-metadata">

**Author:** ![kurokobo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kurokobo/32/182_2.png) [@kurokobo](https://forum.ansible.com/u/kurokobo)\
**Post date:** [December 27, 2023, 1:38pm UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/4 "2023-12-27T13:38:18Z")

</div>

In addition to @chris’s comment, to be more programatic way, I think a `float` filter would be helpful: [Template Designer Documentation — Jinja Documentation (3.0.x)](https://jinja.palletsprojects.com/en/3.0.x/templates/#jinja-filters.float)  
This allows for a simple comparison of scores to `0`, rather than looking for a `-` in a string.

Example tasks:

```yaml
- name: opatch_direct | Export the Post-change Impact Score for for {{ db_name }}
  ansible.builtin.slurp:
    src: /tmp/impact.txt
  register: impact_score_b64encoded

- name: Debug values and filteres
  ansible.builtin.debug:
    var: debug_scores
  vars:
    debug_scores:
      01_source _____ : "{{ impact_score_b64encoded.content }}"
      02_b64decoded_: "{{ impact_score_b64encoded.content | ansible.builtin.b64decode }}"
      03_casted _____ : "{{ impact_score_b64encoded.content | ansible.builtin.b64decode | float }}"
      04_is_negative: "{{ impact_score_b64encoded.content | ansible.builtin.b64decode | float < 0 }}"
      05_is_positive: "{{ impact_score_b64encoded.content | ansible.builtin.b64decode | float > 0 }}"

- name: opatch_direct | GO / NOGO decision for {{ oracle_home }} and {{ db_name }}
  block:
    - name: Message if the score is nevative
      ansible.builtin.debug:
        msg: The score is negative
  when: impact_score_b64encoded.content | ansible.builtin.b64decode | float < 0

```

Result:

```bash
TASK [opatch_direct | Export the Post-change Impact Score for for hoge] ************************************
ok: [localhost]

TASK [Debug values and filteres] ***************************************************************************
ok: [localhost] => {
    "debug_scores": {
        "01_source _____": "ICAtMTIyNjguMDY=",
        "02_b64decoded_": " -12268.06",
        "03_casted _____": "-12268.06",
        "04_is_negative": true,
        "05_is_positive": false
    }
}

TASK [Message if the score is nevative] ********************************************************************
ok: [localhost] => {
    "msg": "The score is negative"
}

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

```

---

<div class="post-metadata">

**Author:** ![Symian](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/symian/32/8301_2.png) [@Symian](https://forum.ansible.com/u/Symian)\
**Post date:** [December 28, 2023, 3:18am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/5 "2023-12-28T03:18:51Z")

</div>

cannot thank you enough, both!

---

<div class="post-metadata">

**Author:** ![Symian](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/symian/32/8301_2.png) [@Symian](https://forum.ansible.com/u/Symian)\
**Post date:** [December 31, 2023, 1:09am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/6 "2023-12-31T01:09:12Z")

</div>

I put the block in the playbook, thanks. But it fires on both negative and positive numbers. For example, the below is for the value “7”. It does the same for “-7”. But it correctly says “-7” or “7” as below, but rollsback the patch even when the number is positive, which it should not.

> Blockquote

TASK [Debug values and filteres] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/oracle/ansible/playbooks/opatch\_direct.yml:214  
ok: [lnx006] =\>  
debug\_scores:  
01\_source\_\_\_\_\_: IDcK  
02\_b64decoded\_: |2-  
7  
03\_casted\_\_\_\_\_: ‘7.0’  
04\_is\_negative: false  
05\_is\_positive: true

TASK [Message if the score is nevative] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
task path: /home/oracle/ansible/playbooks/opatch\_direct.yml:227  
ok: [lnx006] =\>  
msg: The post-change improvement score is negative, the change is being rolled back now

---

<div class="post-metadata">

**Author:** ![jbericat](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jbericat/32/627_2.png) [@jbericat](https://forum.ansible.com/u/jbericat)\
**Post date:** [December 31, 2023, 3:29am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/7 "2023-12-31T03:29:10Z")

</div>

Hello @Symian, what both @chris & @kurokobo told you should be enough to achieve your goal. Anyway, I’ll tell you what I use to do on these cases, since I normally prefer the use of lookup plugins instead of modules when I have the chance (just because I’m more used to those, not for nothing in particular). For example, you may combine the use of [ansible.builtin.lookup](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_lookup.html#ansible-collections-ansible-builtin-file-lookup) and [ansible.builtin.assert](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/assert_module.html), like this:

```yaml
---
- name: Help Using an .stdout as a WHEN Condition
  hosts: localhost
  gather_facts: false
  tasks:

    - name: Asserting float sign from file lookup
      ansible.builtin.assert:
        that: impact_score | float < 0
        success_msg: NEGATIVE NUMBER
        fail_msg: NOT NEGATIVE NUMBER
      vars:
        impact_score: "{{ lookup('file', 'tmp/impact.txt', lstrim=true) }}"
      register: results

    - name: My Block
      when: not results.failed
      block:

        - name: DEBUG
          ansible.builtin.debug:
            msg: these tasks will run only when the impact_score is negative
...

```

Hope it helps!

---

<div class="post-metadata">

**Author:** ![kurokobo](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/kurokobo/32/182_2.png) [@kurokobo](https://forum.ansible.com/u/kurokobo)\
**Post date:** [December 31, 2023, 4:22am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/8 "2023-12-31T04:22:59Z")

</div>

Hmm on my side it works as expected:

```bash
TASK [Debug values and filteres] ***************************************************************************
ok: [localhost] => 
  debug_scores:
    01_source _____ : IDcK
    02_b64decoded_: |2-
       7
    03_casted _____ : '7.0'
    04_is_negative: false
    05_is_positive: true

TASK [Message if the score is nevative] ********************************************************************
skipping: [localhost]

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

```

Have you updated `when` for your `block` correctly?

> ```yaml
> when: impact_score_b64encoded.content | ansible.builtin.b64decode | float < 0
> 
> ```

For the comment from @jbericat, indeed `ansible.builtin.lookup` and `ansible.builtin.assert` are useful modules so familiarity with them will be very helpful in your future playbook development.

Note, however, that `lookup('file')` can only read local files on control node and cannot be used to read files placed on target (remote) nodes, as in this case.

---

<div class="post-metadata">

**Author:** ![jbericat](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/jbericat/32/627_2.png) [@jbericat](https://forum.ansible.com/u/jbericat)\
**Post date:** [December 31, 2023, 7:07am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/9 "2023-12-31T07:07:39Z")

</div>

> [@kurokobo](#):
>
> Note, however, that `lookup('file')` can only read local files on control node and cannot be used to read files placed on target (remote) nodes, as in this case.

My mistake, you’re totally right @kurokobo, I did oversee this ‘small’ detail indeed!

---

<div class="post-metadata">

**Author:** ![Symian](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/symian/32/8301_2.png) [@Symian](https://forum.ansible.com/u/Symian)\
**Post date:** [January 1, 2024, 2:24am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/10 "2024-01-01T02:24:09Z")

</div>

That also explains why the /tmp/impact.txt kept reporting a negative even when a positive was present. I missed the same point that it kept reading the file on the admin node which was always negative, even when I change it to a positive on the remote node. Thank you anyway.

---

<div class="post-metadata">

**Author:** ![Symian](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/symian/32/8301_2.png) [@Symian](https://forum.ansible.com/u/Symian)\
**Post date:** [January 1, 2024, 2:26am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/11 "2024-01-01T02:26:08Z")

</div>

It all works beautifully, thanks to you all @jbericat@kurokobo

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [January 31, 2024, 2:26am UTC](https://forum.ansible.com/t/help-using-an-stdout-as-a-when-condition/3067/12 "2024-01-31T02:26:42Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
