Diego,

this  results from a bug that was just fixed in svn 747. No exit status was set 
for a
pattern that was not found. If the pattern was not found, then the promise is 
considered
to be kept.

See new version in SVN.

Diego Zamboni wrote:
> Hi,
> 
> I am still banging my head on this. For a brief moment I thought the
> problem would be traced to a typo in the source (reapir_denied,
> reported a few days ago on this list, and hence patched in svn), but I
> have applied the patch and the problem persists.
> 
> The problem is that when the pattern specified in replace_patterns in
> an edit_line body does not appear in the file at all, it seems none of
> the classes clauses is triggered. For reference, below is my
> self-contained example. When the pattern appears in the file,
> everything works fine, but when the pattern is not there, replace_done
> is not defined, and thus the line is not appended.
> 
> Thanks for any help,
> --Diego
> 
> body common control
> {
>   bundlesequence => { "linereplace" };
> }
> 
> bundle agent linereplace
> {
> vars:
>   "file" string => "/root/sshd_config";
>   # Pattern is automatically anchored to the beginning/end of line
>   "pattern" string => "(# *Protocol .*| *Protocol .*1.*)";
>   "line" string => "Protocol 2";
> 
> files:
>   "$(file)"
>   edit_line => replace_or_add("$(pattern)","$(line)");
> 
> }
> 
> bundle edit_line replace_or_add(pattern,line)
> {
> replace_patterns:
>   "^${pattern}$"
>   replace_with => value("${line}"),
>   classes => always("replace_done");
> 
> insert_lines:
>   replace_done::
>   "${line}";
> 
> }
> 
> body replace_with value(x)
> {
> replace_value => "$(x)";
> occurrences => "all";
> }
> 
> body classes always(x)
> {
>   promise_repaired => { "$(x)" };
>   promise_kept => { "$(x)" };
>   repair_failed => { "$(x)" };
>   repair_denied => { "$(x)" };
>   repair_timeout => { "$(x)" };
> }
> 
> 
> On Tue, Jan 26, 2010 at 4:06 PM, Diego Zamboni <di...@zzamboni.org> wrote:
>> I am sorry, I didn't realize that at some point we switched off the
>> list. I'm sending to the list now - thanks for the help.
>>
>> --Diego
>>
>>
>> On Tue, Jan 26, 2010 at 2:43 PM, Mark <m...@iu.hio.no> wrote:
>>> I don't have time to guide you through this, send it to the list
>>>
>>>
>>> Mark
>>>
>>>
>>> On 26 Jan 2010, at 19:50, Diego Zamboni <di...@zzamboni.org> wrote:
>>>
>>>> Mark,
>>>>
>>>> Thanks again for the nudge in the right direction. Here's my latest
>>>> attempt, which unfortunately still does not work:
>>>>
>>>>
>>>> bundle edit_line replace_or_add(pattern,line)
>>>> {
>>>> replace_patterns:
>>>>  "^${pattern}$"
>>>>  replace_with => value("${line}"),
>>>>  classes => always("replace_done");
>>>>
>>>> insert_lines:
>>>>  replace_done::
>>>>  "${line}";
>>>>
>>>> }
>>>>
>>>> body classes always(x)
>>>> {
>>>>  promise_repaired => { "$(x)" };
>>>>  promise_kept => { "$(x)" };
>>>>  repair_failed   => { "$(x)" };
>>>>  repair_denied   => { "$(x)" };
>>>>  repair_timeout  => { "$(x)" };
>>>> }
>>>>
>>>> If the line exists, whether commented out or not, then the correct
>>>> thing happens. But if the line does not exist, the class
>>>> "replace_done" does not get defined anyway, so the insert_lines does
>>>> not run, even on the second pass. Below is the relevant verbose
>>>> output.
>>>>
>>>> Did I miss some clause in the definition of always()? Or am I missing
>>>> something else?
>>>>
>>>> Thanks again,
>>>> --Diego
>>>>
>>>>
>>>> cf3       * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
>>>> *
>>>> cf3       BUNDLE replace_or_add( {'# *Protocol 2,1.*','Protocol 2'} )
>>>> cf3       * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
>>>> *
>>>> cf3
>>>> cf3     ? Augment scope replace_or_add with pattern
>>>> cf3     ? Augment scope replace_or_add with line
>>>> cf3      ??  Private class context
>>>> cf3
>>>> cf3
>>>> cf3       = = = = = = = = = = = = = = = = = = = = = = = = = = = =
>>>> cf3       insert_lines in bundle replace_or_add
>>>> cf3       = = = = = = = = = = = = = = = = = = = = = = = = = = = =
>>>> cf3
>>>> cf3
>>>> cf3    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
>>>> cf3    Skipping whole next edit promise, as context replace_done is not
>>>> relevant
>>>> cf3    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
>>>> cf3
>>>> cf3       = = = = = = = = = = = = = = = = = = = = = = = = = = = =
>>>> cf3       replace_patterns in bundle replace_or_add
>>>> cf3       = = = = = = = = = = = = = = = = = = = = = = = = = = = =
>>>> cf3
>>>> cf3
>>>> cf3     .........................................................
>>>> cf3     Promise handle:
>>>> cf3     Promise made by: ^# *Protocol 2,1.*$
>>>> cf3     .........................................................
>>>> cf3
>>>> cf3  -> Looking at pattern ^# *Protocol 2,1.*$
>>>> cf3      ??  Private class context
>>>> cf3
>>>> cf3
>>>> cf3       = = = = = = = = = = = = = = = = = = = = = = = = = = = =
>>>> cf3       insert_lines in bundle replace_or_add
>>>> cf3       = = = = = = = = = = = = = = = = = = = = = = = = = = = =
>>>> cf3
>>>> cf3
>>>> cf3    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
>>>> cf3    Skipping whole next edit promise, as context replace_done is not
>>>> relevant
>>>> cf3    .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
>>>>
>>>>
>>>> On Tue, Jan 26, 2010 at 8:35 AM, Mark Burgess <mark.burg...@iu.hio.no>
>>>> wrote:
>>>>> IN this case, you need to define a class regardless if what happens when
>>>>> the pattern
>>>>> replace is made.
>>>>>
>>>>>  replace_patterns:
>>>>>
>>>>>  "${p}"
>>>>>    replace_with => value("${l}"),
>>>>>    classes => always("done");
>>>>>
>>>>>  insert_lines:
>>>>>
>>>>>  done::
>>>>>
>>>>>   "${l}"; # add only if it doesn't exist
>>>>>
>>>>> This should work as long as the $(l) is always a complete line, otherwise
>>>>> your promise is
>>>>> ambiguous. What happens if the pattern matches a partial line? cfengine
>>>>> inserts the line
>>>>> because there is no complete line matching this expression. Perhaps your
>>>>> pattern should be
>>>>> "^$(p)$" ?
>>>>>
>>>>>
>>>>>
>>>>> Diego Zamboni wrote:
>>>>>> Hi Mark,
>>>>>>
>>>>>> Thanks. In fact, my very first attempt was something very similar to
>>>>>> set_variable_values(), only with a replace_patterns section instead of
>>>>>> field_edits. The problem I found was that according to normal
>>>>>> ordering, insert_lines is run before replace_patterns (whereas
>>>>>> field_edits occurs before insert_lines), which defeats the test with
>>>>>> the classes. The line is always inserted, regardless of whether the
>>>>>> replacement works or not, because the negation of a non-existing class
>>>>>> is true.
>>>>>>
>>>>>> Here's that very first version, for reference:
>>>>>>
>>>>>> bundle edit_line replace_or_add(p,l)
>>>>>> {
>>>>>> replace_patterns:
>>>>>>  "${p}"
>>>>>>  replace_with => value("${l}"),
>>>>>>  classes => if_ok("line_exists");
>>>>>>
>>>>>> insert_lines:
>>>>>>  "${l}"
>>>>>>  ifvarclass => "!line_exists";
>>>>>> }
>>>>>>
>>>>>> What am I missing?
>>>>>>
>>>>>> Thanks again,
>>>>>> --Diego
>>>>>>
>>>>>>
>>>>>> On Mon, Jan 25, 2010 at 12:29 PM, Mark Burgess <mark.burg...@iu.hio.no>
>>>>>> wrote:
>>>>>>> Try looking at the set-variable bundle in the standard library
>>>>>>>
>>>>>>> M
>>>>>>>
>>>>>>> Diego Zamboni wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> I've been working on putting together an edit_line bundle that does
>>>>>>>> the following:
>>>>>>>>
>>>>>>>> - If a certain pattern exists, replace it with a given string
>>>>>>>> - If the pattern does not exist, add the line to the file.
>>>>>>>>
>>>>>>>> Below is what I came up with, which works, but somehow feels inelegant
>>>>>>>> because I have to pass it the filename for the check using regline. I
>>>>>>>> tried doing it by setting different classes in the replace_patterns:
>>>>>>>> and insert_lines: sections, but could not get it to work.
>>>>>>>>
>>>>>>>> I would appreciate any ideas! I am just learning cfengine, so this is
>>>>>>>> as much an intellectual exercise as something I need (and maybe could
>>>>>>>> be a useful addition to the stdlib?)
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> --Diego
>>>>>>>>
>>>>>>>>
>>>>>>>> bundle edit_line replace_or_add(file,pattern,line)
>>>>>>>> {
>>>>>>>> classes:
>>>>>>>>  "lineexists" expression => regline("$(pattern)","$(file)");
>>>>>>>>
>>>>>>>> replace_patterns:
>>>>>>>>  lineexists::
>>>>>>>>  "${pattern}"
>>>>>>>>  replace_with => value("${line}");
>>>>>>>>
>>>>>>>> insert_lines:
>>>>>>>>  !lineexists::
>>>>>>>>  "${line}";
>>>>>>>>
>>>>>>>> }
>>>>>>>> _______________________________________________
>>>>>>>> Help-cfengine mailing list
>>>>>>>> Help-cfengine@cfengine.org
>>>>>>>> https://cfengine.org/mailman/listinfo/help-cfengine
>>>>>>> --
>>>>>>> Mark Burgess
>>>>>>>
>>>>>>> -------------------------------------------------
>>>>>>> Professor of Network and System Administration
>>>>>>> Oslo University College, Norway
>>>>>>>
>>>>>>> Personal Web: http://www.iu.hio.no/~mark
>>>>>>> Office Telf : +47 22453272
>>>>>>> -------------------------------------------------
>>>>>>>
>>>>> --
>>>>> Mark Burgess
>>>>>
>>>>> -------------------------------------------------
>>>>> Professor of Network and System Administration
>>>>> Oslo University College, Norway
>>>>>
>>>>> Personal Web: http://www.iu.hio.no/~mark
>>>>> Office Telf : +47 22453272
>>>>> -------------------------------------------------
>>>>>
> _______________________________________________
> Help-cfengine mailing list
> Help-cfengine@cfengine.org
> https://cfengine.org/mailman/listinfo/help-cfengine

-- 
Mark Burgess

-------------------------------------------------
Professor of Network and System Administration
Oslo University College, Norway

Personal Web: http://www.iu.hio.no/~mark
Office Telf : +47 22453272
-------------------------------------------------
_______________________________________________
Help-cfengine mailing list
Help-cfengine@cfengine.org
https://cfengine.org/mailman/listinfo/help-cfengine

Reply via email to