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
?