Calling methods repeatedly

54 views
Skip to first unread message

jon.k...@gmail.com

unread,
Dec 11, 2016, 2:38:10 PM12/11/16
to help-cfengine
Hello,

I'm a bit confused by the behaviour of methods. According to the manual, "Methods are useful for encapsulating repeatedly used configuration issues and iterating over parameters.". So, in my understanding, if I have repeated tasks, then I use methods.

Now, taking the following example:

body common control
{
    bundlesequence => { test1,test2 };
}

bundle agent test_method
{
    reports
:
        any
::
           
"XXXXXXXXXXXXXXXXXXXXXXXX";
}

bundle agent test1
{
    methods
:
        any
::
           
"daemon1"
                usebundle    
=> test_method;
           
"daemon2"
                usebundle    
=> test_method;
}

bundle agent test2
{
    methods:
        any::
            "daemon3"
                usebundle    => test_method;
}

I would expect the output to be:


cf-agent -K
R
: XXXXXXXXXXXXXXXXXXXXXXXX
R
: XXXXXXXXXXXXXXXXXXXXXXXX
R
: XXXXXXXXXXXXXXXXXXXXXXXX

because the method is called three times giving the report three times.


But instead, the method is only called one time:

cf
-agent -K
R
: XXXXXXXXXXXXXXXXXXXXXXXX

Why is this? And how can I make sure that the method is called each and every single time?

Jon

Bas van der Vlies

unread,
Dec 11, 2016, 3:29:21 PM12/11/16
to jon.k...@gmail.com, help-cfengine
Cfengine will not report the lime due to locking. The line is the same.  For cfengine is has already done the promise. If you had $(sys.date) to the line it will be unique 

--
Bas van der Vlies

--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengin...@googlegroups.com.
To post to this group, send email to help-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/help-cfengine.
For more options, visit https://groups.google.com/d/optout.

mike.w...@verticalsysadmin.com

unread,
Dec 12, 2016, 1:30:34 AM12/12/16
to help-cfengine
The most common stumbling block I've seen amongst learners of the CFEngine 3 policy language is the assumption that methods are somehow equivalent to function calls in other, procedural languages.  They are not; they are entirely different.  (I ran up against this myself when first learning CFEngine 3.)

As for your question, "how can I make sure that the method is called each and every single time?" it actually carries an incorrect assumption: That there is such a thing as "each time" for a CFEngine policy.  A declarative language is not associated, properly speaking, with a sequence of actions taken across time.  It is associated with an end result.

(Unfortunately, the CFEngine 3 language is not fully declarative.  I've written more on this subject elsewhere.  The theory is that one needn't concern oneself with sequence and procedural thought in writing CFEngine policies.  In actual fact, for all but the most straightforward policies, one must think about sequence much, much more than in a language wherein instructions are simply carried out one after another.)

Incidentally, @Bas van der Vlies, in my testing, including sys.date in the report does not result in multiple reports being output.  Try the following, which produces only two reports:

bundle agent main {
  methods:
    "date_report";
    "date_report";
    "static_report";
    "static_report";
    "date_report";
}

bundle agent date_report {
  reports:
    "$(sys.date)";
}

bundle agent static_report {
  reports:
    "This report is static.";
}

jon.k...@gmail.com

unread,
Dec 12, 2016, 2:27:37 AM12/12/16
to help-cfengine
I assumed that the -K option tells cfengine to ignore locking?

Yes the Cfengine-thinking is unfamiliar, but it makes sense. However, I'm currently stumbling over this non-sequential logic:

One of the strengths of Cfengine is, as far as I can see, that it encourages abstraction and modularization. So I've implemented a generic service_reload method, that, as the name implies, reloads a given service whenever called.
Now I've got two independent bundles that require the reloading of the same service when something has changed. While a change in the first bundle triggers the reload, a subsequent change in the second one does not, because cfengine has already done the reload of this service and thinks it has converged already. Unfortunately the next time Cfengine runs, the second reload does not get triggered anymore, because the change has already occured in the previous Cfengine run. So the service is left running with an old configuration.

How to deal with situations like these without inventing unnecessary ballast/complexity? For modularization and isolation reasons I don't want to combine these two bundles as from a logical perspective, this doesn't make sense.
'ifelapsed' does not seem to help here.

@Mike, doesn't $(sys.date) always contain the date/time of the beginning of the Cfengine run?

Jon

mike.w...@verticalsysadmin.com

unread,
Dec 12, 2016, 2:54:31 AM12/12/16
to jon.k...@gmail.com, help-cfengine
Writing from iPod now so will be brief.

Would suggest setting a class for service restart--same class from either point--and placing the single restart promise in a bundle later in bundle sequence, conditional on that class.

-K ignores existing locks; I.e. it unlocks promises that were locked from prior runs.  Not in the current run.

You are likely correct about sys.date.

--Mike Weilgart

Sent from my iPod
--
You received this message because you are subscribed to a topic in the Google Groups "help-cfengine" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/help-cfengine/0mPddg8ICqY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to help-cfengin...@googlegroups.com.

Aleksey Tsalolikhin

unread,
Dec 12, 2016, 7:08:15 AM12/12/16
to mike.w...@verticalsysadmin.com, help-cfengine, jon.k...@gmail.com

You are likely correct about sys.date.

--Mike Weilgart

Sent from my iPod

On Dec 11, 2016, at 11:27 PM, jon.k...@gmail.com wrote:

I assumed that the -K option tells cfengine to ignore locking?

Yes the Cfengine-thinking is unfamiliar, but it makes sense. However, I'm currently stumbling over this non-sequential logic:

One of the strengths of Cfengine is, as far as I can see, that it encourages abstraction and modularization. So I've implemented a generic service_reload method, that, as the name implies, reloads a given service whenever called.
Now I've got two independent bundles that require the reloading of the same service when something has changed. While a change in the first bundle triggers the reload, a subsequent change in the second one does not, because cfengine has already done the reload of this service and thinks it has converged already. Unfortunately the next time Cfengine runs, the second reload does not get triggered anymore, because the change has already occured in the previous Cfengine run. So the service is left running with an old configuration.

How to deal with situations like these without inventing unnecessary ballast/complexity? For modularization and isolation reasons I don't want to combine these two bundles as from a logical perspective, this doesn't make sense.
'ifelapsed' does not seem to help here.

@Mike, doesn't $(sys.date) always contain the date/time of the beginning of the Cfengine run?

Jon

--
You received this message because you are subscribed to a topic in the Google Groups "help-cfengine" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/help-cfengine/0mPddg8ICqY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to help-cfengine+unsubscribe@googlegroups.com.

To post to this group, send email to help-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/help-cfengine.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengine+unsubscribe@googlegroups.com.

Neil Watson

unread,
Dec 12, 2016, 9:46:18 AM12/12/16
to help-cfengine
Methods are for reusable code, where each call differs by parameters.

methods:
"daemon1" usebundle => test_method( @{daemon1} );
"daemon2" usebundle => test_method( @{daemon2} );

--
Neil H Watson @neil_h_watson
CFEngine reporting: https://github.com/neilhwatson/delta_reporting
CFEngine policy: https://github.com/neilhwatson/evolve_cfengine_freelib
CFEngine and vim: https://github.com/neilhwatson/vim_cf3

Moore, Joe

unread,
Dec 13, 2016, 12:37:51 PM12/13/16
to Neil Watson, help-cfengine
CFengine optimizes those identical promises away because they are 100% redundant.

With --debug, you get the following lines in the log:

verbose: P: BEGIN un-named promise of type "methods" (pass 1)
verbose: P: Promiser/affected object: 'daemon2'
verbose: P: Part of bundle: test1
verbose: P: Base context class: any
verbose: P: Container path : '/default/test1/methods/'daemon2'[0]'
verbose: P: .........................................................
verbose:
verbose: B: *****************************************************************
verbose: B: BEGIN bundle test_method
verbose: B: *****************************************************************
debug: Resolving variables in bundle 'agent' 'test_method'
debug: This promise has already been verified
debug: This promise has already been verified
debug: This promise has already been verified

Note that "This promise" refers to the underlying reports: promise of "XXXXXXXXXXXXXXXXXX", NOT about the methods: promise that incorporates it. You don't get multiple XXX...'s in the log because the promise (put XXX... in the report) has been met already.

--Joe
--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengin...@googlegroups.com.

Marco Marongiu

unread,
Dec 13, 2016, 12:43:07 PM12/13/16
to Moore, Joe, Neil Watson, help-c...@googlegroups.com
I would not say it's an optimisation. Rather, it's about promises. Cfengine tries to apply the promises in a policy until they are kept. When a promise is kept, cfe is done with that promise. It seems a subtlety, but I'm not sure that one can make sense of how it works using concepts other than promises. 

-- M

To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengine+unsubscribe@googlegroups.com.

To post to this group, send email to help-c...@googlegroups.com.
Visit this group at https://groups.google.com/group/help-cfengine.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "help-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to help-cfengine+unsubscribe@googlegroups.com.

jon.k...@gmail.com

unread,
Jan 3, 2017, 5:20:58 AM1/3/17
to help-cfengine
Alright, got it. It's all about promises, where Cfengine promises the specified outcome and handles the way to that itself.

Thanks!
Reply all
Reply to author
Forward
0 new messages