Search code examples
ansiblejinja2

Ansible replace value with previous valid list value(s)


Hello community folks,

Let's imagine I have a list of strings that are either valid strings or spaces / non valid strings.

    mylist:
        -"First"
        -"                          "
        -"Second"
        -"                          "
        -"                          "
        -"                          "
        -"Third"
        -"Last"

What I am trying to achieve is replacing those non valid string elements of the list with the closest previous valid string, so the result would be something like this:

    finalgoal:
        -"First"
        -"First"
        -"Second"
        -"Second"
        -"Second"
        -"Second"
        -"Third"
        -"Last"

Is there any simple way to do this on ansible ? I think I am overcomplicating myself because the way I would do it on other languages is iterating to the previous element until the valid string condition is met. However doing these kind of nested loops on ansible seems the wrong idea to me. Is there any filter than can achieve my desired finalgoal list ?

This is where I am struggling so far. I can get the previous element as long as it exists on the original list 'mylist' but as soon as the previous element is a non valid string my task will not work the way I want.

tasks:
  - name: Fix list
    set_fact:
      fixedlist: "{{ fixedlist | default([]) +  [item if ' ' not in item else mylist[my_idx-1]]}}"
    loop: "{{ mylist }}"
    loop_control:
      index_var: my_idx
  
  - debug:
      var: fixedlist

And this would be the result of the task

    "fixedlist": [
        "First",
        "First",
        "Second",
        "Second",
        "                          ",
        "                          ",
        "Third",
        "Last"
    ]

Cheers and have a nice day if you read it this far.


Solution

  • Use Jinja

        finalgoal: |
          {% filter from_yaml %}
          {% set ns = namespace(default='default') %}
          {% for i in mylist %}
          {% if i | trim | length != 0 %}
          {% set ns.default = i %}
          {% endif %}
          - {{ ns.default }}
          {% endfor %}
          {% endfilter %}
    

    For example,

    - hosts: localhost
    
      vars:
    
        mylist:
          - "                          "
          - "First"
          - "                          "
          - "Second"
          - "                          "
          - "                          "
          - "                          "
          - "Third"
          - "Last"
    
        finalgoal: |
          {% filter from_yaml %}
          {% set ns = namespace(default='default') %}
          {% for i in mylist %}
          {% if i | trim | length != 0 %}
          {% set ns.default = i %}
          {% endif %}
          - {{ ns.default }}
          {% endfor %}
          {% endfilter %}
    
      tasks:
    
        - debug:
            var: finalgoal
    

    gives abridged

      finalgoal:
      - default
      - First
      - First
      - Second
      - Second
      - Second
      - Second
      - Third
      - Last