ternary clarification needed

28 views
Skip to first unread message

Davide Scrimieri

unread,
Mar 26, 2020, 2:54:58 AM3/26/20
to Ansible Project
Hello,

Whenever a ternary is used are both conditions evaluated regardless ?

For example, I want to convert "my_other_var" to an object only if it is passed as as string, otherwise I don't want to touch the object, and leave it as it is.

- set_fact:
    my_var: "{{  ( my_other_var | type_debug == 'str' ) | ternary (my_other_var | from_json, my_other_var }}"

What happens right now is this:

if my_other_var is str -> It works
if my_other_var is dict -> it gives me the error saying that my_other_var should be a string to be converted from_json. But I would expect that being the condition on the left = False, it would ignore the left condition on the ternary and only consider the rightmost condition.

I also tried using when:

-- name: Set fact for string  object
  set_fact:
     my_var: "{{ my_other_var | from_json }}"
  when: (my_other_var | type_debug == 'str')
 

- name: Set fat for dict  object
  set_fact:
    my_var: "{{ my_other_var | from_json }}"
  when: (my_other_var | type_debug == 'dict')

However, if "my_other_var" is dict, the first block (named set fact for string object) gives me the same error as before. I was actually expecting that being the when statement equals to false, it would simply ignore it.
 

Davide Scrimieri

unread,
Mar 26, 2020, 3:01:48 AM3/26/20
to Ansible Project

UPDATE: PLEASE, DISCARD what I said about the when statement at the end of my post, in my original code I had a typo, and was not working for other reasons. The first part of the post about the ternary statement still stands

Karl Auer

unread,
Mar 26, 2020, 3:07:34 AM3/26/20
to ansible-project

Whenever a ternary is used are both conditions evaluated regardless ?

A ternary filter consists of three parts:

a) the condition
b) the statement to be evaluated if the condition is true
c) the statement to be evaluted if the condition is false.
Only one of b) and c) will be evaluated, but the condition will always be evaluated IF the ternary statement itself is evaluated.

Regards, K.

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/3e0c7994-6e18-44bb-afc5-807607fa2a88%40googlegroups.com.


--

Karl Auer { manager, systems support }
P: 1300 759 975
E: ka...@2pisoftware.com
2pisoftware.com

GPG/PGP : DF6A 43E5 FB9D D884 C6CA CD7F 5278 212D E80F C107
Previous: 301B 1F4E 624D AD99 242C 7A68 EC24 7113 E854 4A4E

Vladimir Botka

unread,
Mar 26, 2020, 4:13:21 AM3/26/20
to Davide Scrimieri, ansible...@googlegroups.com
On Wed, 25 Mar 2020 23:54:57 -0700 (PDT)
Davide Scrimieri <dscr...@redhat.com> wrote:

> I want to convert "my_other_var" to an object only if it is
> passed as as string, otherwise I don't want to touch the object, and leave
> it as it is.
>
> - set_fact:
> my_var: "{{ ( my_other_var | type_debug == 'str' ) | ternary
> (my_other_var | from_json, my_other_var }}"

I'd rather use "from_yaml". JSON is a subset of YAML. How to test types see
https://jinja.palletsprojects.com/en/master/templates/#list-of-builtin-tests

For example

vars:
my_other_var1: "'my': {'other': {'var1': 'var1'}}"
my_other_var2:
my:
other:
var2: var2

tasks:
- debug:
msg: "{{ item is string|ternary(item|from_yaml, item) }}"
loop:
- "{{ my_other_var1 }}"
- "{{ my_other_var2 }}"

gives

ok: [localhost] => (item='my': {'other': {'var1': 'var1'}}) => {
"msg": {
"my": {
"other": {
"var1": "var1"
}
}
}
}
ok: [localhost] => (item={u'my': {u'other': {u'var2': u'var2'}}}) => {
"msg": {
"my": {
"other": {
"var2": "var2"
}
}
}
}

HTH,

-vlado

Martin Krizek

unread,
Mar 26, 2020, 4:27:07 AM3/26/20
to ansible...@googlegroups.com
On Thu, Mar 26, 2020 at 7:55 AM Davide Scrimieri <dscr...@redhat.com> wrote:
>
> Hello,
>
> Whenever a ternary is used are both conditions evaluated regardless ?
>
> For example, I want to convert "my_other_var" to an object only if it is passed as as string, otherwise I don't want to touch the object, and leave it as it is.
>
> - set_fact:
> my_var: "{{ ( my_other_var | type_debug == 'str' ) | ternary (my_other_var | from_json, my_other_var }}"
>

Yes, this is how the ternary filter works. To work around that you can
use a ternary statement:

- set_fact:
my_var: "{{ my_other_var | from_json if (my_other_var |
type_debug == 'str') else my_other_var }}"

That should result in desired behavior.

M.

> What happens right now is this:
>
> if my_other_var is str -> It works
> if my_other_var is dict -> it gives me the error saying that my_other_var should be a string to be converted from_json. But I would expect that being the condition on the left = False, it would ignore the left condition on the ternary and only consider the rightmost condition.
>
> I also tried using when:
>
> -- name: Set fact for string object
> set_fact:
> my_var: "{{ my_other_var | from_json }}"
> when: (my_other_var | type_debug == 'str')
>
>
> - name: Set fat for dict object
> set_fact:
> my_var: "{{ my_other_var | from_json }}"
> when: (my_other_var | type_debug == 'dict')
>
> However, if "my_other_var" is dict, the first block (named set fact for string object) gives me the same error as before. I was actually expecting that being the when statement equals to false, it would simply ignore it.
>
>
> --
> You received this message because you are subscribed to the Google Groups "Ansible Project" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/8e08a7c9-9f2a-4c83-a7c4-ab9aa389b4e2%40googlegroups.com.

Davide Scrimieri

unread,
Mar 26, 2020, 4:32:56 AM3/26/20
to ansible...@googlegroups.com
Thank you all for the answers. I used the solution "from_yaml" provided by Vladimir and it works like a charm, and it's also cleaner. However, if this is the case, I don't believe this is an issue of how ternary works, but of how "from_json" works. My gut feeling is that it shouldn't behave that way.

Reply all
Reply to author
Forward
0 new messages