This got me thinking about whether it is feasible to write an ENC in Python, without it messing up the entire Puppet Enterprise setup, so I thought I'd give it a try.
First things first, I should warn you that using an ENC on Puppet Enterprise is entirely possible, but not covered by your Support agreement. If you have issues with node classification, and you are using any ENC, you will be politely told that you're on your own. As well as this, you do render parts of your PE Console redundant, although the reporting sections will still be entirely functional and valid.
With that out of the way, here is what I did. I hope it may be useful to someone else starting out on writing an ENC in Python.
I used a Vagrant install of PE 2017.2.2 on an Ubuntu 14.04 server, simply because setting up Python3 on a CentOS box is just too much trouble, and Ubuntu has it pre-installed. You will also need to have the Py-yaml Python module installed. Ensure the Puppet Master node is fully functional before you start, and it is useful if you also have an Agent node spun up. In my lab, the Master's FQDN was pe-201722-master.puppetdebug.vlan and the Agent's FQDN was pe-201722-agent.puppetdebug.vlan
I used the Puppet documentation at https://puppet.com/docs/puppet/5.3/nodes_external.html as a starting point and my completed ENC can be seen at https://gist.github.com/spynappels/41699b5bcc63a742084d5fb3d023c6dc.
However, let me take you through some of the specifics.
I followed the instructions in the docs to enable the ENC, but I found that I also had to add the following keys to the common.yaml file in the production environment's hieradata directory:
puppet_enterprise::profile::master::classifier::node_terminus: 'exec' puppet_enterprise::puppet_master_host: 'pe-201722-master.puppetdebug.vlan'
I have commented the Python code to illustrate what each section does and why I've included some of the things I have. For example, in the section below, I have sliced up the FQDN to extract only the specific substring that describes the nodes role, and then added this to the parameters dictionary inside the classification dictionary:
# Parameters section # This sets the node_role based on a section of the hostname classification['parameters'].update({'node_role':node_fqdn.split(".")[0].split("-")[-1]})
The ENC script works entirely as expected now, and any changes made in Hiera to any of the puppet_enterprise profile parameters to change the default behaviour of any of the PE elements are propagated as expected and work. However, there are a few observations I have based on this test.
- This works really well if you have a bunch of data such as server role, environment and such encoded into the hostname or FQDN of your nodes somehow. If you want to use facts to classify nodes, like the "using a fact to create a rule for a Node Group in the PE Console" workflow, it is not going to work unless you find a way to allow the ENC script to also query against the PuppetDB Query API. I believe this is possible, but not with the ENC script in the Github Gist link above.
- Using an ENC may allow a slightly more automated way of classifying nodes if your workflow uses hostnames to describe node roles etc., but without a knowledge of the language the ENC is written in (Python3 in this case) it is not nearly as easy to change the classification rules. The PE Console is pretty Puppet Noob friendly, and as it is supported by Puppet Support, it is easier to get help in making changes to your classification rules.
- The choice of language in which the ENC is written may have implications for your sysadmins or Puppet admins, should the person who wrote the ENC decide to move on from your organisation.
All in all, using an ENC to manage your classification is a good strategy if you are comfortable with the limitations it imposes. I found this a valuable lesson in thinking about classification, and applying Python principles that I'm comfortable with to Puppet node classification which I've normally done using either the PE Console or Hiera. Hopefully it may prove useful to someone else starting out on the same path.