Ansible playbook gives me false positives - search for string in file (YAML file)

I have this playbook

        ---
      - name: Search String with lineinfile
        hosts: web

        tasks:
          - name: "Searching for a String"
            become: yes
            become_user: myuser
            tags: example1
            lineinfile:
              path: /home/myuser/file.txt
              line: "string_to_find"
              state: present
            check_mode: yes
            register: presence
            failed_when: presence is changed

          - name: "sample task in case the String present in the file"
            debug: msg="DEBUG is enabled in Apache Log file"
            when: presence is not changed

And this gives me false msg. even if a file doesn't exist it showed me that exist.
Can yo please help

What happens when you print the presence variable in an extra debug statement ?
Does its value correspond to the two when conditions ?

Hi @tomislav91,

you have to pay attention to which parameters you use and how to use them. If the file does not exist, the lineinfile module fails and presence.changed contains the default value false. This makes the condition presence is changed false, so the task is treated as not having failed due to failed_when: false. In addition, the debug message is printed.

If the file does not exist, you have two options: either you create it (with another task or via the create parameter), or the playbook terminates with an error.

state: present ensures that (if the file exists) the line is inserted if it does not exist. So if you just want to check whether a line is present, check_mode: yes must be set so that the file is not changed.
The ansible documentation says:

Here a slightly modified version:

- name: "Searching for a String"
  lineinfile:
    path: /home/myuser/file.txt
    line: "string_to_find"
    state: absent
  check_mode: yes
  # want to check only, so set changed explicitly to false
  changed_when: false
  register: presence

- debug: var=presence

- debug: msg="found"
  when: presence.found

- debug: msg="not found"
  when: not presence.found

See also Error handling in playbooks — Ansible Documentation and Using Variables — Ansible Documentation

2 Likes

2021-03-02 22_24_38-mRemoteNG - confCons2021.xml - Ansible

where have i got mistake there?

ERROR! Syntax Error while loading YAML.
  did not find expected key

The error appears to be in '/etc/ansible/find.yml': line 11, column 6, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


     check_mode: yes
     ^ here

It is yaml format so you need to use the correct alignment. Note that there is an alignment difference by one space on some lines, compared to @bendingrodriguez' example.

When working with YAML files, the first thing you should consider doing when you get an error is to put your file into a YAML syntax checker and "validate it". There are many YTML validators online, for example using your code @tomislav91 in your original post:

Here are many online YAML checkers on the net, here is one (not particularly recommended or not, just an example):

You will save yourself a lot of time and energy if you validate YAML files after you make changes or when you experience any errors working these "syntax picky" YAML files.

1 Like

but throwes me error again

ERROR! 'changed_when' is not a valid attribute for a Play

The error appears to be in '/etc/ansible/find.yml': line 3, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

  • changed_when: false
    ^ here

See The Following Reference on Ansible Syntax and Validation Methods:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html#playbook-syntax


Example Knowledge From Reference Above:

Verifying playbooks

You may want to verify your playbooks to catch syntax errors and other problems before you run them. The ansible-playbook command offers several options for verification, including --check, --diff, --list-hosts, list-tasks, and --syntax-check. The Tools for Validating Playbooks describes other tools for validating and testing playbooks.

ansible-lint

You can use ansible-lint for detailed, Ansible-specific feedback on your playbooks before you execute them. For example, if you run ansible-lint on the playbook called verify-apache.yml near the top of this page, you should get the following results:

$ ansible-lint verify-apache.yml [403] Package installs should not use latest verify-apache.yml:8 Task/Handler: ensure apache is at the latest version

The ansible-lint default rules page describes each error. For [403], the recommended fix is to change state: latest to state: presentin the playbook.

Thanks for that, i put ansible-lint and give me no errors
2021-03-04 23_11_10-Window

but result of
ansible-playbook --syntax-check --list-tasks find.yml
is:

ERROR! 'changed_when' is not a valid attribute for a Play

The error appears to be in '/etc/ansible/find.yml': line 2, column 3, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:


  • changed_when: false
    ^ here

find.yml is:


changed_when: false
check_mode: true
hosts: web
lineinfile:
line: something123
path: /home/myuser/file.txt
state: absent
name: "Searching for a String"
register: presence

  • debug: var=presence
  • debug: msg="found"
    when: presence.found
  • debug: "msg="not found""
    when: "not presence.found"

2021-03-04 23_14_23-Window

What is your next step in troubleshooting this error, @tomislav91 ?

Maybe you should "drill down" on the Ansible "changed_when" directive?

I'm not an Ansible user, but according to the tutorial below, comparing it to your posts, it seems your use of changed_when is quite different than in the tutorial below.

Reference:

--- 
- hosts: web
  tasks:
  - name: "Start the Apache HTTPD Server"
    become: true
    become_user: root
    register: starthttpdout
    shell: "httpd -k start"
    changed_when: "'already running' not in starthttpdout.stdout"

  - debug:
      msg: "{{starthttpdout.stdout}}"

you have to differentiate between playbooks, roles and tasks. My example was written as a role, I forgot to mention that, sorry. A playbook should look like this:

- name: "main"
  hosts: web
  tasks:
    - name: "Searching for a String"
      check_mode: true
      lineinfile:
        line: something123
        path: /home/myuser/file.txt
        state: absent
      changed_when: false
      register: presence

    - debug: var=presence

    - debug: msg="found"
      when: presence.found

    - debug: msg="not found"
      when: not presence.found

Note that presence only has the default attributes changed, failed and msg, if the file does not exist, so it will not contain the attribute found.
See also:
https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html

- name: "main"
      hosts: web
      tasks:
        - name: "Searching for a String"
          check_mode: true
          lineinfile:
            line: test
            path: /home/myuser/file.txt
            state: absent
          changed_when: false
          register: presence

        - debug: var=presence

        - debug: msg="found"
          when: presence.found

        - debug: msg="not found"
          when: not presence.found

in that /home/myuser/test.txt is only one word "test" but it showes me

> PLAY [main] ************************************************************************************************************************************************************************************************************************
> 
> TASK [Gathering Facts] *************************************************************************************************************************************************************************************************************
> ok: [10.10.20.10]
> 
> TASK [Searching for a String] ******************************************************************************************************************************************************************************************************
> ok: [10.10.20.10]
> 
> TASK [debug] ***********************************************************************************************************************************************************************************************************************
> ok: [10.10.20.10] => {
>     "presence": {
>         "changed": false,
>         "failed": false,
>         "msg": "file not present"
>     }
> }
> 
> TASK [debug] ***********************************************************************************************************************************************************************************************************************
> fatal: [10.10.20.10]: FAILED! => {"msg": "The conditional check 'presence.found' failed. The error was: error while evaluating conditional (presence.found): 'dict object' has no attribute 'found'\n\nThe error appears to be in '/etc/ansible/find.yml': line 15, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n    - debug: msg=\"found\"\n      ^ here\n"}

syntax should be ok, no errors here

ansible-playbook --syntax-check --list-tasks find.yml

Also no errors in ansible-lint

you write

but your playbook contains

path: /home/myuser/file.txt

So the result

> "msg": "file not present"

is correct, isn't it?

1 Like

its just misstype problem, filename is file.txt not test.txt.
Its just my mistake of writing here

so does the file exist on 10.10.20.10? Don't forget that the module's python code is running remotely.

Here are two other helpful options:

  • --check enables check mode globally, so you don't have to put check_mode: true in the task.
  • --diff shows the changes that were made or would be made if --check is set.

See Validating tasks: check mode and diff mode — Ansible Documentation.

yeah it is. So cant sure what is the problem here now

Normally, when I have these types of problems; my debugging technique is to comment out or remove lines, one-line-at-a-time, and run it so "it works" as expected (without a few lines) and then repeat the process, adding lines back in, one-line-at-a-time, until I can isolate the exact line causing the problem.

When you say:

The first step is not to try to "solve the problem". Your first step is to "know what exactly the problem is"; and the main way to do that is to have a step-by-step troubleshooting technique so you can learn exactly what is the problem. Knowing the problem is 80%+ of the work of solving any problem, especially problems in software.

does /home/myuser on 10.10.20.10 exist, i.e. is myuser a real user with that home dir, or is myuser just a placeholder in your playbook/your post? Do you call the playbook as root on 10.10.20.10?
What does

ssh $USER@10.10.20.10 'stat /home/myuser/file.txt'

give?

You can add stdout_callback = yaml to the [defaults] section in your ansible config, so the task's output is a bit more human readable. Also you can add -v, -vv or -vvv to the playbook command to print debug output (very much output in the latter case).

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