Now that the upgrade from 3.4 to 3.6 is advancing slowly but steadily I am starting to check the features that are new in 3.6 compared to 3.4. According to the docs namespaces were actually introduced in 3.4.0, but I didn’t take advantage of them yet, and it’s time to start.
When something is declared in a namespace (a bundle, a variable or whatnot) it must be referred to with its namespace. For example, if you declare a bundle test in the namespace nstest, you’ll refer to that bundle from outside the namespace (e.g. in the bundlesequence) as nstest:test. If you declare a variable, for example an array called conf in that bundle, that will be nstest:test.conf outside the namespace. So far so good.
Now, what happens inside the namespace? Well, I found one fact that is indeed surprising.
Consider this simple file:
body file control
{
namespace => "nstest" ;
}
bundle agent test
{
vars:
"conf[key1]" string => "value1" ;
"conf[key2]" string => "value2" ;
"conf[key3]" string => "value3" ;
classes:
"__DEBUG__"
expression => "any",
scope => "namespace" ;
methods:
"test"
usebundle => engine("test.conf") ;
}
bundle agent engine(array_name)
{
vars:
any::
"keys" slist => getindices("$(array_name)") ;
reports:
__DEBUG__::
"$(keys) == $($(array_name)[$(keys)])" ;
}
and run it with CFEngine 3.6: you’ll get a surprising effect:
# cf-agent -KC -f ./namespaces.cf -b nstest:test R: key1 == $(test.conf[key1]) R: key2 == $(test.conf[key2]) R: key3 == $(test.conf[key3])
Apparently, an non namespace-qualified name of test.conf was enough for getindices to understand and get the list of the keys for the array, but not for dereferencing the values. Replacing engine("test.conf") with engine("nstest:test.conf") yields the expected result:
# cf-agent -KC -f ./namespaces.cf -b nstest:test R: key1 == value1 R: key2 == value2 R: key3 == value3
Is this a feature? A bug in the implementation of namespaces? A bug in getindices?