Quite a while ago I posted a thread
<https://groups.google.com/forum/#!searchin/foreman-users/"smart$20classes"|sort:relevance/foreman-users/8BMaCeDXsM4/dVv5XSPqR7kJ>
to the Foreman Users group asking about the concept of "smart classes",
i.e. the ability to dynamically assign Puppet classes (similar to smart
class parameters) depending on fact or other data. I didn't get any
responses, and ultimately, our team ended up doing something
straightforward and created hostgroups for each permutation of Puppet
classes that we had in our environment (rather than sink development time
into solving the problem in a different way). Predictably, this has become
somewhat annoying to maintain as our environment has grown.
I started thinking more about this recently, and came up with what I think
might be a workable solution to this type of requirement. Let me know what
you think.
The basic problem is that Foreman's model for categorizing hosts is a
little bit too rigid to handle certain use cases. For my environment, there
are two basic issues: assigning a class based on fact or parameter data,
and removing inherited classes based on the same. I could imagine other
scenarios as well, however, for example retrieving a class parameter value
from an external system (rather than storing it statically within Foreman).
For users who can't accomplish their host classification with the builtin
tools, there would be a "safety valve" of sorts – a Foreman administrator
could define little bits of code that mutate the Foreman-generated ENC data
arbitrarily (sort of like ENC middleware), based on fact or other data
about the host. This would work in the following way:
The admin would define ENC "mutators" in a configuration directory, e.g.
/etc/foreman/mutators.d. There would be a standard API for these mutators
that might look something like this:
Mutator.create(:some_mutator_name) do |enc, facts|
if facts[:ipaddress] =~ /^10./ and !enc[:classes].has_key?('some::class')
enc[:classes]['some::class'] = nil
end
enc
end
(where facts' is a hash of the requesting host's facts and
enc' is the
standard ENC data returned by Foreman's node classifier)
When the Foreman server boots, it would load these mutators out of the
config dir. When a Puppet server requests ENC data for a host, Foreman
would retrieve the ENC data as normal, and then run the mutators against
that data in some configurable order. Each mutator would return the mutated
ENC, and this would be passed on to the next mutator in the chain. At the
end of the chain, the final ENC data would be passed back to the Puppet
server to use for catalog compilation. (Optionally, a system could be
established to allow the web UI user to pick and choose which host,
hostgroup, etc. gets which mutator and what order the mutators should run,
but this would take a little bit more effort to implement). Ideally, the
ENC data would be exposed in the web UI along each part of the chain so
that operators can inspect and validate its correctness – at the very
least, a 'before' and 'after' image could be displayed.
Before I start building something, I'd like to get some thoughts on this
idea. Would other people find this useful? Are there other approaches
people have tried and found successful?