Thoughts on syntax shortcuts for class expressions

57 views
Skip to first unread message

Nick Anderson

unread,
Apr 26, 2016, 10:46:11 AM4/26/16
to help-cfengine, dev-cfengine
Curious for thoughts about a syntax suggestion from Ted.

https://github.com/cfengine/documentation/pull/1453#issuecomment-214758700

classes:
"myclass" ===> "any";

instead of

classes:
"myclass" expression => "any";

Note this only shortens for expression => not or => or and =>.


signature.asc

Christian Linden

unread,
Apr 26, 2016, 1:05:18 PM4/26/16
to help-cfengine, dev-cf...@googlegroups.com
I won't use it but if Ted will be lucky with it you could grant him this alias =)

Dimitrios Apostolou

unread,
Apr 27, 2016, 6:57:10 AM4/27/16
to dev-cfengine, help-c...@googlegroups.com
On Wed, Apr 27, 2016 at 11:38 AM, Ted Zlatanov <t...@lifelogs.com> wrote:
>
> classes:
> "myclass"; # always defined, easy to implement


This one looks good IMHO.


Dimitris

Aleksey Tsalolikhin

unread,
Apr 27, 2016, 12:16:06 PM4/27/16
to Nick Anderson, help-cfengine, dev-cfengine
I'm happy to see CF3 as a living language, with additions (such as the recent jq addition).

However, about this feature -- part of the improvement of CF3 over CF2 is the regularity of the languge.  CF3 has a very regular syntax pattern: promiser, context, promise body.  The promise body consists of constraint expressions (keyword/value pairs).   This pattern is maintained over all the different promise types.  

I recommend against departing from this regularity.  CFEngine is hard enough to learn without adding quirks.

If anything, I'd like to simplify the language by being able to define a class with

  classes:
   "myclass";

Not being able to do this is on par with having to have a class in reports promises (which language constraint was lifted in the last few years).

I do encourage innovation.  

Sincerely,
Aleksey




--
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.



--
Aleksey Tsalolikhin
CFEngine Training & Consulting

Moore, Joe

unread,
Apr 27, 2016, 3:34:13 PM4/27/16
to Nick Anderson, help-cfengine, dev-cfengine
Am I reading this correctly--
A triple-equals-arrow means the same as the word expression followed by a regular =>?

So now we can define classes in several ways:

"stayhome" expression => "Friday" . "Day13" , persist => "4320" ;
"goout" ===> "!raining" . "have_umbrella" ;
"feed_fish" or => { "Monday", "Wednesday", "Friday" } , scope=> "bundle" ;
"feed_cats" expression => "have_cats.(Tuesday|Thursday|Saturday)";
have_dogs:: "feed_dogs" ===> { classmatch("Day[0-9][0-9]?") }, scope => "namespace";

And cfengine will avoid Friday the 13th, not get wet in the rain, and feed the fish, cats (if I have any) on their correct schedules, and dogs in this namespace every day (if I have any).

But this won't work:
"i_win" => or { "lucky", "higher_score", "forfeit" } ;

nor this:
"everybody" => any;

This seems too complicated.

--Joe

Ted Zlatanov

unread,
Apr 27, 2016, 5:50:09 PM4/27/16
to help-c...@googlegroups.com
On Wed, 27 Apr 2016 17:43:33 -0400 Ted Zlatanov <t...@lifelogs.com> wrote:

TZ> I proposed like 10 different ways and everyone is complaining about the
TZ> triple arrow. Read my earlier post please! There are more things to
TZ> complain about!

Oh, wow. OK, Google Groups doesn't show my post for some reason. I was
wondering what was up. Here's a link to it: http://permalink.gmane.org/gmane.comp.sysutils.cfengine.devel/595

For future reference: cross-posting to two mailing lists confuses Google
Groups' web interface. Geez.

Ted

Moore, Joe

unread,
Apr 27, 2016, 6:22:20 PM4/27/16
to help-c...@googlegroups.com
No offense intended. I wanted to highlight‎ where the syntax is currently a bit... convoluted? for a beginning user.

Of the other proposals, I would support the "class"; syntax. It makes sense, it matches the Reports: section where there are often no key-value additions (except for class guards)

The others looked too much like trying to remember bash variable expansion editing rules... ${{PATH:-${HOME-/usr/local}}/bin##/*} or reading an old perl homework assignment. (Ok, it isn't _that_ bad)

Classes:
Foo::
"Bar‎";
Basically makes bar an alias of foo. Harmless enough.

--Joe

Original Message
From: Ted Zlatanov
Sent: Wednesday, April 27, 2016 5:50 PM
To: help-c...@googlegroups.com
Reply To: help-c...@googlegroups.com
Subject: Re: [help-cfengine] Thoughts on syntax shortcuts for class expressions

Ted Zlatanov

unread,
Apr 27, 2016, 9:13:57 PM4/27/16
to help-c...@googlegroups.com
On Wed, 27 Apr 2016 22:22:15 +0000 "Moore, Joe" <joe....@siemens.com> wrote:

MJ> No offense intended. I wanted to highlight‎ where the syntax is currently a bit... convoluted? for a beginning user.

I wasn't offended at all! Humor doesn't carry well across e-mail unfortunately...

MJ> Of the other proposals, I would support the "class"; syntax. It makes sense, it matches the Reports: section where there are often no key-value additions (except for class guards)

Yeah, that one has been popular. It's ready to be tested and merged: https://github.com/cfengine/core/pull/2596

MJ> The others looked too much like trying to remember bash variable expansion editing rules... ${{PATH:-${HOME-/usr/local}}/bin##/*} or reading an old perl homework assignment. (Ok, it isn't _that_ bad)

OK. Can you think of a way to avoid the pain of

"x" expression => "y"

please? I've typed it a million times. I think most people would be
happy with something shorter.

Ted

Nick Anderson

unread,
Apr 27, 2016, 9:43:57 PM4/27/16
to help-c...@googlegroups.com
For me simply dropping expression allowing that to be the default feels most natural. 


"class" => "expression";
"class"  => function();

Sent from my mobile device.

Diego Zamboni

unread,
Apr 28, 2016, 1:46:17 AM4/28/16
to help-cfengine
Hi everyone,

I’m not sure about this, and I think the reason is that I agree with Aleksey - one of the nice things of the CFEngine syntax is its regularity:

promise_type::
   promiser
      [ attribute => value … ]

The attribute => value pairs are optional - if we start making the “attribute” part optional, the syntax will get confusing (not to mention making the parsing more complicated). This is, if “expression” is optional for classes, what’s the default attribute for vars, for files, or for other promise types? While I can see the appeal in terms of shorter code, I fear it’s a slippery slope that could easily lead to confusing code:

files:
   “/foo/bar” => og(“root”, “wheel”);   # “mode" by default?
commands:
  “/bin/foo” => “/etc”;      # “chdir” by default?
etc.

I do like the part about class:: “foo” being equivalent to class:: “foo” expression => “any”, because it doesn’t break the syntax model.

Cheers,
—Diego

Brian Bennett

unread,
Apr 28, 2016, 4:39:12 AM4/28/16
to Aleksey Tsalolikhin, Nick Anderson, help-cfengine, dev-cfengine
+1 everything Aleksey said.

-- 
Brian Bennett
Looking for CFEngine training?
You received this message because you are subscribed to the Google Groups "dev-cfengine" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dev-cfengine...@googlegroups.com.
To post to this group, send email to dev-cf...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dev-cfengine/CANNWuVUuN6dgq%3DPYpHyHUcw-QmoT40HrSzb9%2Bs3HCWCbZvagdA%40mail.gmail.com.

Brian Bennett

unread,
Apr 28, 2016, 4:42:18 AM4/28/16
to Moore, Joe, Ted Zlatanov
> On Apr 27, 2016, at 3:22 PM, Moore, Joe <joe....@siemens.com> wrote:
>
> Classes:
> Foo::
> "Bar‎";
> Basically makes bar an alias of foo. Harmless enough.

But you can also do:

classes:
foo.bar::
"foobar"

Etc... Which is awesome.

Dimitrios Apostolou

unread,
Apr 28, 2016, 4:47:19 AM4/28/16
to Brian Bennett, Moore, Joe, Ted Zlatanov
On Thu, Apr 28, 2016 at 10:42 AM, Brian Bennett
<brian....@verticalsysadmin.com> wrote:
> But you can also do:
>
> classes:
> foo.bar::
> "foobar"
>
> Etc... Which is awesome.


I like this. :-)

Aleksey Tsalolikhin

unread,
Apr 28, 2016, 7:29:34 AM4/28/16
to help-cfengine
On Thu, Apr 28, 2016 at 1:42 AM, Brian Bennett <brian....@verticalsysadmin.com> wrote:

[...] You can also do:


    classes:
      foo.bar::
        "foobar"

Etc... Which is awesome.


Yep! And putting class expressions in the promise context would address Ted's concern about typing "expression" over and over again. 

Ted, what do you think?

Yours fondly,
-at

Ted Zlatanov

unread,
Apr 28, 2016, 7:51:04 AM4/28/16
to help-c...@googlegroups.com
On Thu, 28 Apr 2016 04:29:13 -0700 Aleksey Tsalolikhin <ale...@verticalsysadmin.com> wrote:

AT> On Thu, Apr 28, 2016 at 1:42 AM, Brian Bennett <
AT> brian....@verticalsysadmin.com> wrote:

>> [...] You can also do:
>>
>> classes:
>> foo.bar::
>> "foobar"
>>
>> Etc... Which is awesome.
>>

AT> Yep! And putting class expressions in the promise context would address
AT> Ted's concern about typing "expression" over and over again.

AT> Ted, what do you think?

Good point! And then you can even say:

classes: "x.y.$(z)":: "foobar_$(z)";

which will work as you'd expect. It's a clever trick.

Another shortcut that will be possible (internally the code works the
same as the above):

classes: "foobar_$(z)" if => "x.y.$(z)";

That's a whole lot shorter than "expression"! And it requires no
language or parser changes beyond that one minor patch I've submitted.

Thanks
Ted

Aleksey Tsalolikhin

unread,
Apr 28, 2016, 7:58:42 AM4/28/16
to help-cfengine
I love it!  Thanks, Ted!

On Thu, Apr 28, 2016 at 4:50 AM, Ted Zlatanov <t...@lifelogs.com> wrote:

And then you can even say:

    classes: "x.y.$(z)":: "foobar_$(z)";

which will work as you'd expect. It's a clever trick.

Another shortcut that will be possible (internally the code works the
same as the above):

    classes: "foobar_$(z)" if => "x.y.$(z)";

That's a whole lot shorter than "expression"! And it requires no
language or parser changes beyond that one minor patch I've submitted.

Thanks
Ted
--
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.

Bas van der Vlies

unread,
Apr 28, 2016, 10:20:56 AM4/28/16
to Aleksey Tsalolikhin, help-cfengine
A bit late -). +1 for the class shortcut . For me the rest of the language improvements suggestions was not my cup of tea.
---
Bas van der Vlies
| Operations, Support & Development | SURFsara | Science Park 140 | 1098 XG Amsterdam
| T +31 (0) 20 800 1300 | bas.van...@surfsara.nl | www.surfsara.nl |

Dimitrios Apostolou

unread,
Apr 29, 2016, 9:17:26 AM4/29/16
to dev-cfengine, help-c...@googlegroups.com
On Wed, Apr 27, 2016 at 11:38 AM, Ted Zlatanov <t...@lifelogs.com> wrote:
>
> classes:
> "myclass"; # always defined, easy to implement


The consensus on this one was great, and since it was quickly coded by
Ted, and it has also been cherry-picked to the upcoming 3.9.0 Beta
release. Thanks everyone!


Dimitris

mike.w...@verticalsysadmin.com

unread,
May 13, 2016, 7:30:34 PM5/13/16
to help-cfengine, dev-cf...@googlegroups.com
One further thought on this:

Looking down the road a bit, we may want to consider handling the "if" attribute of a classes promise the same way as the "expression" attribute, or vice versa.

I would imagine that newcomers to CFEngine will have no particular reason to ever use the "expression" attribute at all, when the default expression is "any" and they can express the more complex conditionals they will need with an "if" attribute (or an "and" attribute, or "or" attribute, etc.) without ever learning "expression."

Currently, the verbose output based on "expression" is different from that based on "if" (example shown is running 3.7.1):

[root@hub tmp]# cat classes.cf
bundle agent main {
  classes:
    any::
      "set_by_expression"
        expression => "any";


      "set_by_if_and_expression"
        if => "any",
        expression => "any";


      "unset_by_if"
        expression => "any",
        if => "!any";


      "unset_by_expression"
        expression => "!any";
}
[root@hub tmp]# cf-agent -f ./classes.cf -vKC | sed -n '/pass 1/,/pass 2/p'
 verbose: C: BEGIN classes / conditions (pass 1)
 verbose: C: .........................................................
 verbose: C:     +  Private class: set_by_expression
 verbose: C:     +  Private class: set_by_if_and_expression
 verbose: Skipping promise 'unset_by_if', for if/ifvarclass is not in scope
 verbose: C: .........................................................
 verbose: C: BEGIN classes / conditions (pass 2)
[root@hub tmp]#


As illustrated above, a class whose "expression" is false is not even mentioned in the verbose output, whereas a class whose "expression" is true but whose "if" is false *is* shown.

Perhaps the handling should be the same?  (This would be a special case for the "if" attribute for classes promises only, to make it behave the same as an "expression" attribute.)

--Mike Weilgart

Kristian Amlie

unread,
May 18, 2016, 2:29:24 AM5/18/16
to mike.w...@verticalsysadmin.com, help-cfengine, dev-cf...@googlegroups.com
On 14. mai 2016 01:30, mike.w...@verticalsysadmin.com wrote:
> One further thought on this:
>
> Looking down the road a bit, we may want to consider handling the "if"
> attribute of a classes promise the same way as the "expression"
> attribute, or vice versa.
>
> I would imagine that newcomers to CFEngine will have no particular
> reason to ever use the "expression" attribute at all, when the default
> expression is "any" and they can express the more complex conditionals
> they will need with an "if" attribute (or an "and" attribute, or "or"
> attribute, etc.) without ever learning "expression."

Good point, I never even considered that these two are essentially doing
exactly the same thing. It would be possible to deprecate "expression"
entirely, and it wouldn't even require introducing anything new.

> Currently, the verbose output based on "expression" is different from
> that based on "if" (example shown is running 3.7.1):

Under the hood, the execution paths are different, so this is not
surprising. I wouldn't be surprised if there are other, subtle
differences as well, but this requires more investigation.

--
Kristian
Reply all
Reply to author
Forward
0 new messages