Floren
Floren

Reputation: 541

Replace string in file, if exists with Ansible playbook

I have a file, containing a single line of multiple space separated strings:

$ cat /tmp/strings.txt
alpha beta gamma zeta omega

My goal is to check if delta string is not present inside /tmp/strings.txt, and if not, add it after gamma string:

$ cat /tmp/strings.txt
alpha beta gamma delta zeta omega

What I think would be a solution:

    - name: Check if delta string is present
      ansible.builtin.command: grep 'delta' /tmp/strings.txt | wc -l
      register: delta_string

    - name: Add delta string
      ansible.builtin.blockinfile:
        block: gamma delta
        path: /tmp/strings.txt
      when: delta_string.stdout == 0

Is this a proper use of string replacements in Ansible? Not sure how ansible.builtin.blockinfile block works, will it insert the gamma delta string if is not found, as replacement for gamma, or will it add it at the end of file?

Is there a solution which does require a when check?

Upvotes: 1

Views: 1855

Answers (2)

U880D
U880D

Reputation: 12111

From your description I understand that you like to have a file with a single line of "text" only.

Since Ansible is a Configuration Management Tool with which you declare the Desired State, that is all what you would need to do. There is no need for any CHECK IF THEN INSERT (ELSE) WHEN contruct.

For an input file of

~/test$ cat strings.txt
alpha beta gamma zeta omega

a minimal example playbook

---
- hosts: localhost
  become: false
  gather_facts: false

  tasks:

  - name: Make sure lineinfile is in Desired State
    lineinfile:
      path: strings.txt
      line: alpha beta gamma delta zeta omega
      regexp: '^alpha' # or even '^alpha beta gamma zeta omega'

will result into an output file

~/test$ cat strings.txt
alpha beta gamma delta zeta omega

Further Documentation

Most likely would work too

Upvotes: 0

Vladimir Botka
Vladimir Botka

Reputation: 68124

Put the twins into a dictionary, e.g.

  twins:
    gamma: delta
    foo: bar

Read the file and split the items. Declare the variable

  strings: "{{ out.content|b64decode|split() }}"

The task below

    - slurp:
        src: /tmp/strings.txt
      register: out

gives the list of the strings

  strings: [alpha, beta, gamma, zeta, omega]

Iterate strings and add the twins if missing

  update_str: |
    [
    {% for i in strings %}
    {% if i in twins and strings[loop.index]|d(None) != twins[i] %}
    {{ i }}, {{ twins[i] }},
    {% else %}
    {{ i }},
    {% endif %}
    {% endfor %}
    ]

gives valid YAML

  update_str: |-
    [
    alpha,
    beta,
    gamma, delta,
    zeta,
    omega,
    ]

Convert the string to the list

  update: "{{ update_str|from_yaml }}"

gives

  update: [alpha, beta, gamma, delta, zeta, omega]

Join the items and write the file

    - copy:
        dest: /tmp/strings.txt
        content: "{{ update|join(' ') }}"

gives

shell> cat /tmp/strings.txt 
alpha beta gamma delta zeta omega

Example of a complete playbook for testing

- hosts: localhost

  vars:

    twins:
      gamma: delta
      foo: bar

    strings: "{{ out.content|b64decode|split() }}"
    update_str: |
      [
      {% for i in strings %}
      {% if i in twins and strings[loop.index]|d(None) != twins[i] %}
      {{ i }}, {{ twins[i] }},
      {% else %}
      {{ i }},
      {% endif %}
      {% endfor %}
      ]
    update: "{{ update_str|from_yaml }}"

  tasks:

    - slurp:
        src: /tmp/strings.txt
      register: out
    - debug:
        var: strings
    - debug:
        var: update_str
    - debug:
        var: update
    - copy:
        dest: /tmp/strings.txt
        content: "{{ update|join(' ') }}"

Upvotes: 1

Related Questions