Ansible playbook replace module doesn’t behave as expected

The replace module by default replaces all occurances of the regexp found in path. Quoting from official documentation:

  • This module will replace all instances of a pattern within a file.
  • It is up to the user to maintain idempotence by ensuring that the same pattern would never match any replacements made.

To limit this, we can use before and after.

Now my interpretation of this:

While the documentation doesn’t say anything about whether before and after are references in the same line or n lines above and below. In my opinion, for replace to work reliably the before and after expressions should be on the same line.

We can demonstrate this with below example:

Let’s consider a sample.txt with below contents:

ruby ansible chef
foo ansible baz
python ansible saltstack

Now let’s say I wanted to change ansible to bar only on the line foo ansible baz, then I would have a task like:

  - replace:
      path: "sample.txt"
      regexp: "ansible"
      replace: "bar"
      after: "foo"
      before: "baz"

Now when we run this task:

 ruby ansible chef
-foo ansible baz
+foo bar baz
 python ansible saltstack

Also there is a bug in Ansible replace mentioned in the Notes And this affects versions lower than 2.7.10.

  • As of Ansible 2.7.10, the combined use of before and after works properly. If you were relying on the previous incorrect behavior, you may be need to adjust your tasks. See for details.

Now the solution

As I commented on the question, there are better options to achieve your objective. Apart from the lineinfile module, you can use the ini_file module:

  - ini_file:
      path: '/path/to/grafana_config_template.ini'
      section: "server"
      option: "{{ item.opt }}"
      value: "{{ item.val }}"
    - { opt: "domain", val: "foo" }
    - { opt: "enforced_domain", val: "true" }

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top