On Sat, Nov 20, 2010 at 1:59 PM, Daniel V. Klein <d...@lonewolf.com> wrote:
> Michael, you are right and I feel like a fool.  Of course - the regex was 
> wrong!

No need - I have been using regexes forever and still find new ways to
get them wrong all the time =)

>
> But to meet you half way... the \s* matches the spaces the first time, and 
> the [^0] matches the "1".  After that, it replaces the 0 with a 1, and then 
> you're 100% right.  Doh!
>
> -Dan
>
> On Nov 19, 2010, at 5:50 PM, Michael Potter wrote:
>
>> On Sat, Nov 20, 2010 at 6:20 AM,  <no-re...@cfengine.com> 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
>>> Help-cfengine@cfengine.org
>>> https://cfengine.org/mailman/listinfo/help-cfengine
>>>
>> _______________________________________________
>> Help-cfengine mailing list
>> Help-cfengine@cfengine.org
>> https://cfengine.org/mailman/listinfo/help-cfengine
>
>
_______________________________________________
Help-cfengine mailing list
Help-cfengine@cfengine.org
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to