On Sat, Nov 20, 2010 at 6:20 AM, <[email protected]> wrote:
> Forum: Cfengine Help
> Subject: replace_patterns bug?
> Author: babudro
> Link to topic: https://cfengine.com/forum/read.php?3,19347,19347#msg-19347
>
> Hello Cfengineers.
>
> Like Michael Potter's post on 9 November, I am also running into some strange
> behaviour with replace_patterns. I wonder if someone can spot if I am doing
> something wrong so I don't file an erroneous bug report.
>
> All I am trying to do is replace a parameter line in a file. I created this
> rule to toggle the setting:
>
>
> bundle edit_line yum_plugins(x) {
> replace_patterns:
> "^enabled\s*=\s*[^$(x)]" replace_with => value("enabled = $(x)");
> }
>
>
> The idea is that if I pass x=0 then it searches for "enabled" not equal to
> zero and, if it finds a match, changes it to be zero.
>
> When I run this promise, I get this:
>
>
> -> Promised replacement "enabled = 00000000000000000000" on line "enabled =
> 1" for pattern "^enabled\s*=\s*[^0]" is not convergent while editing
> /etc/yum/pluginconf.d/rhnplugin.conf
> Because the regular expression "^enabled\s*=\s*[^0]" still matches the
> replacement string "enabled = 00000000000000000000"
> Promise (version 8) belongs to bundle 'yum_plugins' in file './yum.cf' near
> line 215
> -> Promised replacement "enabled = 00000000000000000000" on line "enabled =
> 1" for pattern "^enabled\s*=\s*[^0]" is not convergent while editing
> /etc/yum/pluginconf.d/rhnplugin.conf
>
>
> How weird is that?
Replace patterns in continually evaluated until it reaches a state of
convergence, i.e. the pattern to be replaced no longer exists in the
file. It does not just stop after the first replace - this has always
been the case and is not new to 3.1.0. My issue report was that
insert_lines should not insert multiple times - this is new to 3.1.0.
>
> I understand how "enabled = 00" does not match the pattern
>"^enabled\s*=\s*[^0]" since I only have a single zero, but how did it ever get
>that second >(and third and fourth &c.) zero? It should have made the first
>replacement and then stopped since the match is no longer true.
How? First, you need to understand the regular expressions always
*attempt* to match. In your case, the \s* after the = matches nothing,
then the [^0] matches a space. Then that string is replaced with your
replacement pattern, hence you get an infinite loop of zeroed being
created.
>
> If I put a dollar-sign at the end of the match string, it works. But I
> shouldn't have to do that.
Actually, you do need to write your regex to ensure that it no longer
matches after the first replacement. Putting a $ at the end is one way
to do that, because now you are *forcing* the regex parser to compare
0 to [^0] (which obviously doesn't match) - so the whole expression
doesnt match and the replace terminates.
There are probably other ways you can write the regex to get the same
effect - but whatever you do it is your responsibility to ensure the
regex does not match after the replace_patterns is applied.
>
> Am I missing something?
>
> Here is a self-contained policy file to demonstrate this apparent bug:
>
>
> body common control {
> bundlesequence => { "yum" };
> }
> bundle agent yum {
> files:
> redhat::
> "/tmp/test.conf"
> comment => "Demonstrate pattern bug",
> create => "false",
> edit_line => yum_plugins("0");
>
> reports:
> plugins_toggled::
> "Toggled 'enabled' flag in test.conf.";
> }
> bundle edit_line yum_plugins(x) {
> replace_patterns:
> "^enabled\s*=\s*[^$(x)]" replace_with => value("enabled = $(x)");
> }
> body replace_with value(x) {
> replace_value => "$(x)";
> occurrences => "all";
> }
>
> # vim:ts=2
>
>
> Create the file /tmp/test.conf with just this one line:
>
>
> enabled = 1
>
>
> Now watch it explode:
>
>
> $ cf-agent -f ./pattern_bug.cf
> -> Promised replacement "enabled = 00000000000000000000" on line "enabled =
> 1" for pattern "^enabled\s*=\s*[^0]" is not convergent while editing
> /tmp/test.conf
> I: Made in version 'not specified' of './pattern_bug.cf' near line 18
> Because the regular expression "^enabled\s*=\s*[^0]" still matches the
> replacement string "enabled = 00000000000000000000"
> Promise (version not specified) belongs to bundle 'yum_plugins' in file
> './pattern_bug.cf' near line 18
> -> Promised replacement "enabled = 00000000000000000000" on line "enabled =
> 1" for pattern "^enabled\s*=\s*[^0]" is not convergent while editing
> /tmp/test.conf
> I: Made in version 'not specified' of './pattern_bug.cf' near line 18
> Because the regular expression "^enabled\s*=\s*[^0]" still matches the
> replacement string "enabled = 00000000000000000000"
> Promise (version not specified) belongs to bundle 'yum_plugins' in file
> './pattern_bug.cf' near line 18
> -> Promised replacement "enabled = 00000000000000000000" on line "enabled =
> 1" for pattern "^enabled\s*=\s*[^0]" is not convergent while editing
> /tmp/test.conf
> I: Made in version 'not specified' of './pattern_bug.cf' near line 18
> Because the regular expression "^enabled\s*=\s*[^0]" still matches the
> replacement string "enabled = 00000000000000000000"
> Promise (version not specified) belongs to bundle 'yum_plugins' in file
> './pattern_bug.cf' near line 18
>
>
> _______________________________________________
> Help-cfengine mailing list
> [email protected]
> https://cfengine.org/mailman/listinfo/help-cfengine
>
_______________________________________________
Help-cfengine mailing list
[email protected]
https://cfengine.org/mailman/listinfo/help-cfengine