question on lineinfile module

111 views
Skip to first unread message

Werner Flamme

unread,
Jun 29, 2016, 2:07:36 AM6/29/16
to ansible...@googlegroups.com
Hi everyone,

I have one play that does not do what I want it to:

- name: set kernel multiversions
lineinfile:
dest: /etc/zypp/zypp.conf
line: "multiversion.kernels = latest,oldest,running"
regexp: "multiversion.kernels = latest,latest-1,running"
state: present

I expect
-> the module scans for a line matching "regex"
-> if this is found, the found line is replaced with "line"
-> if "regex" has no matches, nothing is done

The module instead scans the file, and on the first run it behaves as I
expect, the line in the file is modified. On subsequent runs, one line
(per run) is added to the file (before EOF), so that I have multiple
lines containing "line".

Is this behaviour expected? How can I make a replacement only when
"regex" matches?

When using a registered variable, this variable is shown as:

ok: [hostname] => {
"myrole_var1": {
"backup": "",
"changed": true,
"diff": [
{
"after": "",
"after_header": "/etc/zypp/zypp.conf (content)",
"before": "",
"before_header": "/etc/zypp/zypp.conf (content)"
},
{
"after_header": "/etc/zypp/zypp.conf (file attributes)",
"before_header": "/etc/zypp/zypp.conf (file attributes)"
}
],
"msg": "line added"
}
}

So nothing I could use "when" on.

I use the blockinfile module to add a line in this file, but I do not
see how to use this module to replace one line. This module runs only
once, on subsequent runs it says "OK" instead of "Changed".

Regards,
Werner

--


Kai Stian Olstad

unread,
Jun 29, 2016, 9:22:02 AM6/29/16
to ansible...@googlegroups.com
On 29. juni 2016 08:07, Werner Flamme wrote:
> The module instead scans the file, and on the first run it behaves as I
> expect, the line in the file is modified. On subsequent runs, one line
> (per run) is added to the file (before EOF), so that I have multiple
> lines containing "line".
>
> Is this behaviour expected? How can I make a replacement only when
> "regex" matches?

No, and you are not alone
https://github.com/ansible/ansible-modules-core/issues/3975

--
Kai Stian Olstad

Joanna Delaporte

unread,
Jun 29, 2016, 2:59:16 PM6/29/16
to Ansible Project
Hi Werner, 

You would want to use the backrefs feature of the lineinfile module. Here is an example that I use for deleting root password hashes from the /etc/shadow file. I use regex numbered groups (with parens and \1, etc) to capture and replay existing parts of lines as needed:

- name: delete root password
  lineinfile: 'dest=/etc/shadow
                        backup=yes
                        backrefs=yes
                        regexp="^(root):.*?:(.*)$"
                        line="\1:*:\2"'

And another example (two tasks) that update an ntp config with a new IP address:

# The following two tasks will replace existing ntp config from .135 to .133
- name: Fix ntp.conf
  lineinfile: dest=/etc/ntp.conf
                    backup=yes
                    state=present
                    backrefs=yes
                    regexp='^(.*server.*) 192.168.1.135'
                    line='\1 192.168.1.133'
- lineinfile: dest=/etc/ntp.conf
                    state=present
                    backup=yes
                    backrefs=yes
                    regexp='^(.*restrict.*) 192.168.1.135'
                    line='\1 192.168.1.133'

Werner Flamme

unread,
Jun 30, 2016, 2:20:16 AM6/30/16
to ansible...@googlegroups.com
Kai Stian Olstad [29.06.2016 15:21]:
Yes, that's exactly what happens here. Thank you for pointing me there.

I already thought of using an "absent" and a "present" task, but now I
use the replace module, and it seems to work:

- name: replace kernel multiversions
replace:
dest: /etc/zypp/zypp.conf
regexp: "^multiversion.kernels = latest,latest-1,running"
replace: "multiversion.kernels = latest,oldest,running"

BTW, I'm running ansible version 2.1.0.0, and it's the first time I use
the lineinfile module (since I'm quite new to ansible).

Regards,
Werner
--

Werner Flamme

unread,
Jun 30, 2016, 2:43:24 AM6/30/16
to ansible...@googlegroups.com
Hi Joanna,

so using lineinfile with regexp, but without backrefs will duplicate a
line and lineinfile with regexp and backrefs will not? Indeed, it seems
to be like that.

- name: another replacement attempt
lineinfile:
dest: /etc/zypp/zypp.conf
backrefs: yes
regexp: '^(multiversion.kernels = latest),(latest-1),(running)$'
line: '\1,oldest,\3'
state: present

works as expected and does not create a duplicate line if regexp is not
found. The registered variable shows '"changed": false'.

I added that to the bug report...

This behaviour is not documented on
<http://docs.ansible.com/ansible/lineinfile_module.html>, so I consider
this as an error.

Werner

Joanna Delaporte [29.06.2016 20:59]:
--


Reply all
Reply to author
Forward
0 new messages