programmatically created global variables (and classes)?

198 views
Skip to first unread message

Kermit Short

unread,
Jan 7, 2015, 12:08:55 PM1/7/15
to help-c...@googlegroups.com
I apologize for the subject.  It probably makes no sense at all.  Essentially, I'm trying to create global (body common) variables & soft classes by reading data from a json file.  I'd really like to be at a point where the policy files do nothing but configuration, and all the data for our environment is kept in JSON files.

Would cfengine allow global variables to be created locally?

Given the following example JSON data:

{
  "cfdirs": [
              "/var/cfengine/masterfiles",
              "/var/cfengine/inputs",
              "/var/cfengine/modules",
              "/var/cfengine/plugins",
              "/var/cfengine/files"
            ]

Could I then create a global variable that I can reference using the following?

bundle common ees_def
{
  vars:
    "vardata"   data => readjson("$(sys.workdir)/files/eesdef_vars.json", 4000); # this is the above JSON data
    "varkeys"   slist => getindices("ees_def.vardata");
    "$(varkeys)" slist => "vardata[varkeys]";
}

I apologize for my lack of clarity.  It's hard to put into words what I want, but separating my data from my operating machinery is fairly crucial to me.

Thanks for your help!
-Kermit

Neil Watson

unread,
Jan 7, 2015, 12:18:11 PM1/7/15
to help-c...@googlegroups.com

Kermit Short

unread,
Jan 15, 2015, 10:31:14 AM1/15/15
to help-c...@googlegroups.com, cfen...@watson-wilson.ca
Fantastic stuff, Neil, and thanks a lot for sharing this!!  I was getting hung up on the idea that the variables and classes needed to be defined globally, but tighter scoping makes better sense anyway.  Thank you again!
-Kermit

Kermit Short

unread,
Jan 15, 2015, 11:08:24 AM1/15/15
to help-c...@googlegroups.com, cfen...@watson-wilson.ca
Neil,
  Can you explain the difference between => and ->?  In your policy code, you've got the -> shown a few times, and I've never seen that in cfengine before.

Thanks!
-Kermit

Nick Anderson

unread,
Jan 15, 2015, 11:11:54 AM1/15/15
to Kermit Short, help-c...@googlegroups.com, cfen...@watson-wilson.ca
On 01/15/2015 10:08 AM, Kermit Short wrote:
> Neil,
> Can you explain the difference between => and ->? In your policy
> code, you've got the -> shown a few times, and I've never seen that in
> cfengine before.

-> is to document the promisee aka the stakeholder or who cares about
the promise.

Its a list, and its super duper useful.

promise_type:
class_expression::
"promisor" -> { "promisee", "stakeholder" }
attribute (aka body) => value,
comment => "dont forget to use this one",
handle => "or this one, your future self will thank you";

Neil Watson

unread,
Jan 15, 2015, 11:14:25 AM1/15/15
to help-c...@googlegroups.com
-> is sole used for promisee syntax. => is used for all other
attributes. The promisee is a freehand list for documenting your
promises, it signifies who the promise is for.

files:
"/etc/ssh/sshd_config" -> { "syadmin", "infosec" }

EFL uses promisee data to logically join data in separate files and in
Delta Reporting for central reports.

Kermit Short

unread,
Jan 15, 2015, 11:20:50 AM1/15/15
to help-c...@googlegroups.com
Thank you, gentlemen!  I am not good about doing that sort of thing.  I think once I have a better handle on cfengine, it will be something I explore further.

Nick Anderson

unread,
Jan 15, 2015, 11:22:23 AM1/15/15
to Kermit Short, help-c...@googlegroups.com
On 01/15/2015 10:20 AM, Kermit Short wrote:
> Thank you, gentlemen! I am not good about doing that sort of thing. I
> think once I have a better handle on cfengine, it will be something I
> explore further.

Just remember to stop for 10 seconds and think if there is anything you
can document in a few words about WHY this promise is important and WHO
might care if its broken. Trust me any bits of knowledge you leave
behind are useful in 3 years.

Kermit Short

unread,
Jan 15, 2015, 1:26:18 PM1/15/15
to help-c...@googlegroups.com, cfen...@watson-wilson.ca
OK, I guess I'm not entirely straight in my head yet.  When you set a soft class, is it available globally?  I guess what I'm asking is, are classes like variables?  Do they have lexical scope, or is a class a class, and once it is set, it is set and the agent can evaluate against it throughout any of the 3 run cycles, in any bundle or body?


And Nick, you're right, of course.  I guess it would be better to start documenting what I've got while the body of policies is small, so I don't have such an arduous task if I saved it for later.  I hate doing documentation, but this seems pretty light on effort, so I better build good habits up front!

Thanks, and sorry for all the traffic on this issue!
-Kermit

Nick Anderson

unread,
Jan 15, 2015, 1:56:33 PM1/15/15
to Kermit Short, help-c...@googlegroups.com, cfen...@watson-wilson.ca
On 01/15/2015 12:26 PM, Kermit Short wrote:
> OK, I guess I'm not entirely straight in my head yet. When you set a
> soft class, is it available globally? I guess what I'm asking is, are
> classes like variables? Do they have lexical scope, or is a class a
> class, and once it is set, it is set and the agent can evaluate against
> it throughout any of the 3 run cycles, in any bundle or body?

Classes do have scopes.

Classes promises may be made in any bundle. By default Classes that are
set in common bundles are global in scope, while classes in all other
bundles are local.
https://docs.cfengine.com/latest/reference-promise-types-classes.html#scope

Classes set as the result of a promise outcome by default are global in
scope.
https://docs.cfengine.com/latest/reference-promise-types.html#scope


Note: global and namespace are used interchangeably.

By default a global class will persist until the end of the agent run or
it is specifically undefined.
https://docs.cfengine.com/latest/reference-promise-types-classes.html#persistence
https://docs.cfengine.com/latest/reference-promise-types.html#cancel_kept

>
> And Nick, you're right, of course. I guess it would be better to start
> documenting what I've got while the body of policies is small, so I
> don't have such an arduous task if I saved it for later. I hate doing
> documentation, but this seems pretty light on effort, so I better build
> good habits up front!

That's the idea, you don't have to write a huge document. Just add bits
of information so that later you can trace it.

> Thanks, and sorry for all the traffic on this issue!

Thats what the list is for!

Neil Watson

unread,
Jan 15, 2015, 1:57:46 PM1/15/15
to help-c...@googlegroups.com
In an agent bundle a classes promise is locally scoped, not visible to
other bundles, unless the promise uses the scope => 'namespace'
attribute.

https://docs.cfengine.com/latest/reference-promise-types-classes.html#scope

Classes attribute in other promises e.g.

files:
"/etc/resolv.conf"
classes => if_repaired( "myclass" )

Are namespace scoped, visible everywhere, but this can be changed to
local scope if you choose.

Classes promises in common bundles are namespace scoped, visible everywhere.

https://docs.cfengine.com/latest/guide-language-concepts-classes.html#global-and-local-classes

Classes, once set, cannot be unset.

Nick Anderson

unread,
Jan 15, 2015, 1:59:34 PM1/15/15
to Neil Watson, help-c...@googlegroups.com
On 01/15/2015 12:57 PM, Neil Watson wrote:
> Classes, once set, cannot be unset.

Actually, you can cancel classes using the
cancel_{kept,repaired,notkept} classes body attributes. But it feels
weird to use it. I never do.

Kermit Short

unread,
Jan 15, 2015, 2:43:44 PM1/15/15
to cfen...@watson-wilson.ca
OK I'm probably getting pedantic here, but Neil mentioned that I can add the
scope => 'namespace'

attribute to a classes promise in an agent bundle.  Can I do the same thing to a vars promise in a common bundle?  This way I could separate out variables I'm using that, from a best practice/style standpoint, should not be global.

Between the information I've gotten in this thread and the reading the references given by Nick, I feel like I have a much firmer understanding of common vs agent bundles, classes, and scope.  Thank you both so much!!

-Kermit


On Thursday, January 15, 2015 at 11:57:46 AM UTC-7, Neil Watson wrote:
In an agent bundle a classes promise is locally scoped, not visible to
other bundles, unless the promise uses the scope => 'namespace'
attribute.

https://docs.cfengine.com/latest/reference-promise-types-classes.html#scope

Classes attribute in other promises e.g.

files:
   "/etc/resolv.conf"
      classes => if_repaired( "myclass" )

Are namespace scoped, visible everywhere, but this can be changed to
local scope if you choose.

Classes promises in common bundles are namespace scoped, visible everywhere.

https://docs.cfengine.com/latest/guide-language-concepts-classes.html#global-and-local-classes

Classes, once set, cannot be unset.

Nick Anderson

unread,
Jan 15, 2015, 2:50:31 PM1/15/15
to Kermit Short, help-c...@googlegroups.com, cfen...@watson-wilson.ca
On 01/15/2015 01:43 PM, Kermit Short wrote:
> OK I'm probably getting pedantic here, but Neil mentioned that I can add the
> scope => 'namespace'
>
> attribute to a classes promise in an agent bundle. Can I do the same
> thing to a vars promise in a common bundle? This way I could separate
> out variables I'm using that, from a best practice/style standpoint
> should not be global.

Not really, you can access any variable in cfengine.

$(myvar) - myvar in the current bundle
$(somewhere.myvar) - myvar in bundle somewhere
$(default:somewhere.myvar) - myvar in bundle somewhere in namespace default.


Kermit Short

unread,
Jan 15, 2015, 2:53:50 PM1/15/15
to help-c...@googlegroups.com, heral...@gmail.com, cfen...@watson-wilson.ca
Yeah I suppose that's true, and considering it's a common bundle, I'd be limiting scope to a global namespace anyway...

OK, I think I've got my mind wrapped around it!!  Thanks a lot guys, I really  appreciate your time and patience!!
Reply all
Reply to author
Forward
0 new messages