Puppet ENC plugin development

Following up The Road to Making Puppet Optional by @tbrisker I’d like to share progress on extracting the Puppet ENC functionality to the plugin.

Puppet ENC ( External Node Classification ) means Puppet environments, classes and class variables. All of these should move to a plugin together with mechanisms of assigning those to Host and Hostgroup.


We have the process of extraction set. We are halfway through extracting ConfigGroups and SmartClassParameters. The biggest effort ahead of us is extracting the PuppetClasses itselves.

Help wanted

  • Testing: If you could help with advice or script how and what to test it would be appreciated.
  • Development: If you have any notes on the development process, or would you like to help, please let me know!


These are the main resources if you’d like to follow our progress. I’ll share the main milestones under this post.

Parent RM ticket for the effort:

GH plugin’s dashboard:

PRs to drop code from core (currently in my fork):

Extraction process

So how do we progress to make sure it goes as smooth as possible and we don’t lose functionality in the process?

We’ve broken the effort down to key areas based on menu items / rails resources to PuppetClasses, Environments, ConfigGroups and SmartClassParameters.
This is noted in the Redmine and further broken down on the Dashboard.

All the code requires some careful cleanup and changes to comply with the plugin requirements.
Some important changes made during the extraction from core to plugin:

  • Moving all code to isolated namespace
  • Getting rid of fixtures and relying on factories for testing
  • Trying not to pollute Host and Hostgroup models and move code to Facets

Apart from these and few other considered changes, we try to extract the functionality as close to AS-IS as possible.

For each of these resources, we do following:

  1. Add migrations to the plugin
  2. Add models with its tests
  3. Add UI (controllers/views) with its tests, permissions and routes, permissions and routes
  4. Add API (controllers/views) with its tests
  5. Prepare to drop API in fork
  6. Prepare to drop UI in fork
  7. Prepare to drop models in fork
  8. Prepare to drop migrations in fork
  9. Prepare to drop permissions in form

The drop PRs are made to a branch in my fork, so we keep the functionality in core until we are ready to drop it. Once the plugin is ready to use and we’ve confirmed everything works, we will open one PR from my fork to remove all the code that has been extracted from core.


Currently we have unit tests on plugin and we are running Foreman core unit tests on the extraction PRs, so we would know if something went terribly wrong.

Apart from those we are just manually testing if the basic workflows still work.

  • Import Classes/Variables from proxy
  • Class assignment to Host/Hostgroup
  • Existing Classes/Variables still available after migration to plugin