When clause with AND and OR condition does not work

Hello,

I am attempting to to use a when clause to run a task only when a string is found in 1 registered variable, and either of 2 strings are found inside of another registered variable. The contents of 2 files is registered into these respective variables.

so basically when string1 is found in var1 AND either string2 OR string3 is found in var2
when:

  • ’ “string1” in var1’
  • (’ “string2” in var2 or “string3” in var2’ )

Futile example
I want to run a debug message if the string websrv is found in /etc/hosts and either the string nfssrv1 or the string 192.168.1.1 is found in the /etc/applications file.

Contents of /etc/applications

oraclehomedir=nfsserv1:/applications/orahome

Contents of /etc/hosts

127.0.0.1 localhost
10.10.10.20 websrv1

Playbook:


- name: Register Hosts
  shell: cat /etc/hosts
  register: var_etchosts

- name: Register File Contents
  shell: cat /etc/applications
  register:   var_applications

- name: Show  msg when  websrv string found in var_etchosts AND either ip OR name found in var_applications 
  debug: 
    msg: "This webserver is pointed to the wrong nfs server"
  when: 
    - ' "websrv" in var_etchosts'
    - ( ' "nfsserv1" in var_applications or "192.168.2.100" in var_applications' )

The above does not work and I am not sure why. I am saying if this string is found in 1 var and either of 2 strings is found in another, var print a message. I can use all And logic and it works… For example


when: 
    - ' "webserv" in var_etchosts'
    -  ' "nfsserv2" not in var_applications' 
    -  ' "192.168.2.100" not in var_applications'

Hope this makes sense

1 Like

Hi, the most foolproof way to troubleshoot when a condition contains variables and it does not work as expected is, to dump the variables.

- name: Register Hosts
  shell: cat /etc/hosts
  register: var_etchosts

- name: Dump variable
  ansible.builtin.debug:
    var: var_etchosts

Perhaps you can get following output:

TASK [Dump variable] *******************************************************************
ok: [...] => {
    "var_etchosts": {
        "changed": true,
        "cmd": "cat /etc/hosts",
        "rc": 0,
        ...
        "stderr": "",
        "stderr_lines": [],
        "stdout": "127.0.0.1 localhost\n10.10.10.20 websrv1",
        "stdout_lines": [
            "127.0.0.1 localhost",
            "10.10.10.20 websrv1"
        ]
    }
}

Then you can find that any strings from the file is under stdout or stdout_lines.

So you should use <variable_name>.stdout instead.

when: 
  - '"websrv" in var_etchosts.stdout'
  - '"nfsserv1" in var_applications.stdout or "192.168.2.100" in var_applications.stdout'
2 Likes

None of your conditions are correct; did you look at the contents of the registered variables? Also, you have at least two syntax errors in your task list, which makes me wonder whether this is actually something you tried to run.

  debug: "This webserver is pointed to the wrong nfs server"

This will error out; debug takes a msg parameter, not a free-form string.

    - '"websrv" in var_etchosts

This will error out; YAML strings that start with a quote need to be terminated by a matching quote. The condition is also incorrect, because var_etchosts is a registered variable so it will have the structure of a task result and this condition will never be true (the result from shell is a dictionary that does not have websrv as a key.)

    - ( '"nfsserv1" in var_applications or "192.168.2.100" in var_applications' )

This has the same problem as the previous condition (not checking the correct place in the variable), but also a new mistake that makes it always true. When a YAML string starts with a quote that quote is YAML syntax, not part of the string value, but this string starts with( and all of its quotes are part of the string value. Non-empty strings are truthy, so this is the equivalent of when: ( true ).

- name: Show  msg when  websrv string found in var_etchosts AND either ip OR name found in var_applications 
  debug:
    msg: This webserver is pointed to the wrong nfs server
  when: 
    - '"websrv" in var_etchosts.stdout'
    - '"nfsserv1" in var_applications.stdout or "192.168.2.100" in var_applications.stdout'
2 Likes

Thank you, Mr Kurokobo.

Yes, I have also tried exactly as you suggested, using stdout. I still don’t get the expected result which I find odd since the stdout indeed includes the expected strings.

I will use the multiple AND conditions without OR. That aside, my AND with OR syntax is indeed supported as far as you can confirm?

Thanks

1 Like

Yes, it’s supported. The complete snippet of the task from @flowerysong works as expected.

To test conditionals, for example, the debug task like following is quite clear and helpful to understand how conditionals works.

- debug:
    var: conditionals
  vars:
    conditionals:
      01_websrv: '{{ "websrv" in var_etchosts.stdout }}'
      02_nfsserv1: '{{ "nfsserv1" in var_applications.stdout }}'
      03_192_168_2_100: '{{ "192.168.2.100" in var_applications.stdout }}'
      04_or: '{{ "nfsserv1" in var_applications.stdout or "192.168.2.100" in var_applications.stdout }}'
TASK [debug] ************************************************************
ok: [localhost] => {
    "conditionals": {
        "01_websrv": true,
        "02_nfsserv1": true,
        "03_192_168_2_100": false,
        "04_or": true
    }
}
2 Likes

Mr Kurokobo, thank you, I appreciate this information, this is very useful, I will use this to debug going forward.

1 Like

Hello, Flowerysong, I did not see your reply.

Apologies for the sloppy code when creating the post. I see the errors I made there, I should have proofread. I did run the code, just sloppy when posting, I will be careful in the future.

I use the builtin.debug often, I use msg: or var: , just sloppy on my part when posting.

I appreciate your feedback here, very useful. I had not considered the fact that websrv is not a key. I did try stdout and stdout_lines but I will have to read what you have written here and try to understand and apply it in test. I have much to learn.

Thank you once again

1 Like