Search code examples
loopsdictionaryansibleslurp

Ansible: Adding values to variable in a loop


I'm working on a playbook that does the following:

  1. Goes into a specified path on each Windows server
  2. Slurps text from a file and adds it to a variable
  3. Performs a check on the variable to see if a string of text exists
  4. Writes the results to a file based on the outcome.

Here is the code I have for this:

---
- name: Slurps text from file on Windows server
  hosts: win
  gather_facts: false

  tasks:    
    - name: Get text
      slurp:
        src: D:\testsearch.ini
      register: norequest

    - name: Check for norequest=false in variable
      lineinfile:
        dest: ./norequest.csv
        line: "{{ inventory_hostname }} There is a false value"
        state: present
        create: true
        insertafter: EOF
      when: '"''NoRequest = False'' in norequest.content|b64decode"|lower'
      delegate_to: localhost

    - name: Check for norequest=true in variable
      lineinfile:
        dest: ./norequest.csv
        line: "{{ inventory_hostname }} There is a true value."
        state: present
        create: true
        insertafter: EOF
      when: '"''NoRequest = True'' in norequest.content|b64decode"|lower'
      delegate_to: localhost

Based on my results, it looks like the playbook slurps the text from the files on both test servers and adds it all to the variable, then performs the conditional check against one of the servers (since the task itself is being delegated to localhost) and outputs the results to the file as though they all came from SERVER1 (the last part seems to be due to the delegation).

PLAY [Slurps text from file on Windows server] *******************************

TASK [Delete previous norequest file] *******************************
changed: [SERVER1 -> localhost]

TASK [Get text] ***************************************
ok: [SERVER2]
ok: [SERVER1]

TASK [Check for norequest=false in variable] ********************************
changed: [SERVER1 -> localhost]

TASK [Check for norequest=true in variable] *******************************
changed: [SERVER1 -> localhost]

PLAY RECAP *******************************
SERVER1  : ok=4    changed=3    unreachable=0    failed=0
SERVER2  : ok=1    changed=0    unreachable=0    failed=0

Here are the contents of the file after the playbook is run:

SERVER1 There is a false value
SERVER1 There is a true value.

This is what the outcome should be if the playbook worked as I want it to:

SERVER1 There is a false value
SERVER2 There is a true value.

I feel like part (or all) of my issue might be that I'm looking at this through a PowerShell lens; as in, "FOR EACH server, get the text from the file, perform a conditional check, write the output to the outfile, then move on to the next server." Is something like that possible in an Ansible playbook? I've looked into dictionaries as a way to solve this, but the only good examples I could find used pre-existing dictionaries or dictionaries populated at runtime with basic server info.


Solution

  • Seems to me, that the when: condition was wrong. Matching is now done via a regexp. Tested it with this playbook:

    ---
    - name: Slurps text from file on Windows server
      hosts:
        - SERVER1
        - SERVER2
      gather_facts: false
    
      tasks:
        - name: Get text
          slurp:
            src: D:\testsearch.ini
          register: norequest
    
        - name: Check for norequest=false in variable
          lineinfile:
            dest: ./norequest.csv
            line: "{{ inventory_hostname }} There is a false value"
            state: present
            create: true
            insertafter: EOF
          when: 'norequest["content"] | b64decode | lower | regex_search("norequest *= *false")'
          delegate_to: localhost
    
        - name: Check for norequest=true in variable
          lineinfile:
            dest: ./norequest.csv
            line: "{{ inventory_hostname }} There is a true  value"
            state: present
            create: true
            insertafter: EOF
          when: 'norequest["content"] | b64decode | lower | regex_search("norequest *= *true")'
          delegate_to: localhost
    

    The file testsearch.ini has the following contents on the systems:

    SERVER1

    NoRequest = False
    

    SERVER2

    NoRequest = True
    

    Executing the playbook with ansible-playbook -i hosts play.yml gives the following output:

    PLAY [SERVER1,SERVER2] *********************************************************
    
    TASK [Get text] ****************************************************************
    ok: [SERVER1]
    ok: [SERVER2]
    
    TASK [Check for norequest=false in variable] ***********************************
    skipping: [SERVER2]
    ok: [SERVER1 -> localhost]
    
    TASK [Check for norequest=true in variable] ************************************
    skipping: [SERVER1]
    ok: [SERVER2 -> localhost]
    
    PLAY RECAP *********************************************************************
    SERVER1                  : ok=2    changed=0    unreachable=0    failed=0
    SERVER2                  : ok=2    changed=0    unreachable=0    failed=0
    

    The contents of norequest.csv after the run is

    SERVER1 There is a false value
    SERVER2 There is a true  value