Stop People Calling Private Puppet Classes
When writing puppet modules sometimes you need to ensure that certain classes are only used within your module itself. For example a class that implements functionality based on the local operating system that should only be used by your public class. While reading though the new puppetlabs-mcollective modules source I came across a new pattern I’d not seen used in puppet before that achieves this in a very elegant way and i thought it was worth a second look.
First we create our module and two classes, the publicly usable one and the internal one we want to restrict access to -
$ mkdir -p modules/internal/manifests
# add the externally usable module
$ cat << 'EOC' > modules/internal/manifests/init.pp
class internal {
notify { 'Inside internal': }
include internal::private
}
EOC
Now we add the private class and the access checking code -
$ cat << 'EOC' > modules/internal/manifests/private.pp
class internal::private {
if $caller_module_name != $module_name {
fail("Use of private class ${name} by ${caller_module_name}")
}
notify { "inside ${module_name}": }
}
EOC
We can include the public class and everything works -
$ puppet apply --modulepath modules -e 'include internal' -v
Notice: Compiled catalog for 123 in environment production in 0.06 seconds
Info: Applying configuration version 'XXX'
Notice: Inside internal
Notice: /Stage[main]/Internal/Notify[Inside internal]/message: defined 'message' as 'Inside internal'
Notice: inside internal
Notice: /Stage[main]/Internal::Private/Notify[inside internal]/message: defined 'message' as 'inside internal'
Notice: Finished catalog run in 0.23 seconds
Now we create a second module called ‘external’ and try to include the private class from the ‘internal’ module.
$ mkdir -p modules/external/manifests
$ cat << 'EOC' > modules/external/manifests/init.pp
class external {
notify { 'Hello from external': }
include internal::private
}
EOC
$ puppet apply --modulepath modules -e 'include external' -v
Error: Use of private class internal::private by external at /home/.../modules/internal/manifests/private.pp:4 on node 123
Error: Use of private class internal::private by external at /home/.../modules/internal/manifests/private.pp:4 on node 123
As you can see, this fails. The $caller_module_name
and
$module_name
variables are set in the local scope during
compilation and refer to the module in which the specific instance of the
surrounding defined type was declared and the name of the module that
contains the current class respectively. There’s also the
official
description.
I think this is an elegant way to restrict which classes in your modules are public and it’s something I’ll be sprinkling over my own modules in the future. You can download the example modules if you want to try them yourselves or go to the original module puppetlabs-mcollective on GitHub.