With our cfengine setup I keep wanting to define classes consisting of groups of hosts, and we have lots of hosts with 4-part hostnames in which the short name is non-unique. I've repeatedly read docs that say not to use dots in hostnames, but it seems like sometimes in certain cases, it works to use xxx_yyy_domain_com, for instance:
in a roles file we define an array with a bunch of machines to be nameservers:
bundle agent tfn_roles {
vars:
# DNS servers
"dns_servers" slist => {
"hetzner8", # ns-frk
"ubiquity1", # ns-lax
"ns_ubi3_domain_org",
"vps001_dfw_domain_org", # ns-dfw
"tagadab2", # ns-lcy
"atlantic1", # ns-mco
};
and then in a bind9.cf promise file:
bundle agent service_bind9 {
meta:
"tags" slist => { "autorun" };
classes:
"dns_servers" or => { "@(tfn_roles.dns_servers)" };
and a bunch of promises for that class seem to correctly get executed for those 2 hosts that have FQDNs with underscores.
however we have another class that is defined by only a string, in that same roles file:
# Server running the daily tasks - should only be one.
"daily_tasks_server" string => "vps007_dfw_domain_org";
and then in a daily tasks promise file:
bundle agent service_daily_tasks {
meta:
"tags" slist => { "autorun" };
classes:
"daily_task_server" expression => "$(tfn_roles.daily_tasks_server)";
And this doesn't seem to work.
Can someone explain why, and a way around it? do i have to say instead:
"daily_task_server" or => "$(tfn_roles.daily_tasks_server)";
and if so why? am i misunderstanding some fundamental cfengine syntax rule??
UPDATE: no, making the change above still doesn't work.
(btw I have already read Host group on CFEngine - please don't tell me i have to read Mr. Zamboni's book. Although I'd love to at some point, when i have time...)
The error would be in your use of the "expression" attribute (also the "or" attribute) of your classes promises. You're using
"$(tfn_roles.daily_tasks_server)"
, which evaluates to"vps007_dfw_domain_org"
in your example. Then CFEngine parses that as a class expression, sees that there is no class set with the namevps007_dfw_domain_org
and so evaluates the whole class expression as false. Since the expression attribute of the classes promise evaluates to false ("!any"
if you look under the hood), the class"daily_task_server"
is not set.I'm not quite understanding what you're expecting to do with the
"daily_task_server"
class, to be honest. Classes are booleans, and you seem to be trying to stuff a string into a class. Perhaps you should be using a vars promise? But without seeing what you're ultimately trying to accomplish it's hard for me to be sure.http://www.cfenginetutorial.org/ has recently come online; you may find it helpful in clearing up CFEngine syntax and definitions of terms. (Full disclosure: I work closely with the author. ;)
EDIT: Based on your comment that you want one value for one specific server and a different (default) value for all other servers, you would want code something like the following:
It doesn't matter what type of promise you are using. I haven't used packages promises very much, but something like the following could be done, again without using classes, just
ifvarclass
attribute:I haven't used packages promises much as I'm still on 3.6.6 but the
ifvarclass
attribute can be used in any promise type.