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