Skip to content

Instantly share code, notes, and snippets.

@justinstoller
Last active February 21, 2019 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinstoller/db1b9b761aa43e55615d787a49b7f9e7 to your computer and use it in GitHub Desktop.
Save justinstoller/db1b9b761aa43e55615d787a49b7f9e7 to your computer and use it in GitHub Desktop.
# To be used within the Puppet::Server::Master initialize method
# Outpus to be used when calling find, save, etc on termini
# e.g.
#
# require 'puppet/indirector/indirection'
# require 'puppet/indirector/terminus'
# ...
#
# class Puppet::Server::Master
# ...
#
# def initialize(puppet_config, puppet_server_config)
# ...
# @env_loader = Puppet.lookup(:environments)
#
# @indirection_info = find_indirection_info
# end
#
# ...
#
# def get_facts_from_pdb(nodename, environment)
# if @indirection_info[:facts][:actual_cache_name] == "puppetdb"
# pdb_terminus = @indirection_info[:facts][:actual_cache_class].new
#
# ...
# end
# end
#
#
def find_indirection_info
indirections = {}
Puppet::Indirector::Indirection.instances.each do |indirection|
# Above `Indirection.instances` returns an array of symbols for
# registered indirections, e.g. :facts
#
# The below is an instance of that indirected class, eg
# `Puppet::Node::Facts.new` which contains some information about
# its configuration
indirection_instance = Puppet::Indirector::Indirection.instance(indirection)
# An actual class ref of what will be indirected, eg `Puppet::Node::Facts`
indirected_class_reference = indirection_instance.model
# Symbol, eg :store_configs or may be `nil` (uncached)
# symbol can be used to look up class ref via
# `Terminus.terminus_class(:catalog, :store_configs)`
cache_terminus_name = indirection_instance.cache_class
# The symbol, eg :compiler that can be given to
# `Terminus.terminus_class` same as cache_class
# May be `nil`, if so terminus_setting should be consulted
primary_terminus_name = indirection_instance.terminus_class
# Where to find any configuration for what default terminus to use
# Will be a symbol that can be passed into `Puppet.setting[<here>]`
terminus_setting = indirection_instance.terminus_setting
# This has an analog within the indirection instance however it
# appears to be lazily populated, full information on all
# available termini are availble through
# `Puppet::Indirector::Terminus.terminus_classes(indirection)`
termini = {}
Puppet::Indirector::Terminus.terminus_classes(indirection).each do |term_name|
# The above returns an array of symbols similar to Indirection.instances
termini[term_name] =
Puppet::Indirector::Terminus.terminus_class(indirection, term_name)
end
if cache_terminus_name
cache_terminus_class =
Puppet::Indirector::Terminus.terminus_class(indirection,
cache_terminus_name)
else
cache_terminus_class = nil
end
if cache_terminus_name == :store_configs
actual_cache_name = Puppet.settings[:storeconfigs_backend]
actual_cache_class =
Puppet::Indirector::Terminus.terminus_class(indirection,
actual_cache_name)
else
actual_cache_name = cache_terminus_name
actual_cache_class = cache_terminus_class
end
primary_terminus_name ||= Puppet.settings[terminus_setting]
if primary_terminus_name
primary_terminus_class =
Puppet::Indirector::Terminus.terminus_class(indirection,
primary_terminus_name)
else
primary_terminus_class = nil
end
if primary_terminus_name == :store_configs
actual_terminus_name = Puppet.settings[:storeconfigs_backend]
actual_terminus_class =
Puppet::Indirector::Terminus.terminus_class(indirection,
actual_terminus_name)
else
actual_terminus_name = primary_terminus_name
actual_terminus_class = primary_terminus_class
end
indirections[indirection] = {
indirected_class: indirected_class_reference,
cache_terminus_name: cache_terminus_name,
actual_cache_name: actual_cache_name,
primary_terminus_name: primary_terminus_name,
actual_terminus_name: actual_terminus_name,
cache_terminus_class: cache_terminus_class,
actual_cache_class: actual_cache_class,
primary_terminus_class: primary_terminus_class,
actual_terminus_class: actual_terminus_class,
terminus_setting: terminus_setting,
termini: termini,
}
end
indirections
end
#
# find_indirection_info
# => {:facts=>
# {:indirected_class=>Puppet::Node::Facts,
# :cache_terminus_name=>"yaml",
# :actual_cache_name=>"yaml",
# :primary_terminus_name=>"puppetdb",
# :actual_terminus_name=>"puppetdb",
# :cache_terminus_class=>Puppet::Node::Facts::Yaml,
# :actual_cache_class=>Puppet::Node::Facts::Yaml,
# :primary_terminus_class=>Puppet::Node::Facts::Puppetdb,
# :actual_terminus_class=>Puppet::Node::Facts::Puppetdb,
# :terminus_setting=>:facts_terminus,
# :termini=>
# {:facter=>Puppet::Node::Facts::Facter,
# :memory=>Puppet::Node::Facts::Memory,
# :network_device=>Puppet::Node::Facts::NetworkDevice,
# :rest=>Puppet::Node::Facts::Rest,
# :store_configs=>Puppet::Node::Facts::StoreConfigs,
# :yaml=>Puppet::Node::Facts::Yaml,
# :puppetdb=>Puppet::Node::Facts::Puppetdb,
# :puppetdb_apply=>Puppet::Node::Facts::PuppetdbApply}},
# :node=>
# {:indirected_class=>Puppet::Node,
# :cache_terminus_name=>nil,
# :actual_cache_name=>nil,
# :primary_terminus_name=>:classifier,
# :actual_terminus_name=>:classifier,
# :cache_terminus_class=>nil,
# :actual_cache_class=>nil,
# :primary_terminus_class=>Puppet::Node::Classifier,
# :actual_terminus_class=>Puppet::Node::Classifier,
# :terminus_setting=>:node_terminus,
# :termini=>
# {:exec=>Puppet::Node::Exec,
# :ldap=>Puppet::Node::Ldap,
# :memory=>Puppet::Node::Memory,
# :msgpack=>Puppet::Node::Msgpack,
# :plain=>Puppet::Node::Plain,
# :rest=>Puppet::Node::Rest,
# :store_configs=>Puppet::Node::StoreConfigs,
# :write_only_yaml=>Puppet::Node::WriteOnlyYaml,
# :yaml=>Puppet::Node::Yaml,
# :puppetdb=>Puppet::Node::Puppetdb,
# :classifier=>Puppet::Node::Classifier}},
# :report=>
# {:indirected_class=>Puppet::Transaction::Report,
# :cache_terminus_name=>nil,
# :actual_cache_name=>nil,
# :primary_terminus_name=>:processor,
# :actual_terminus_name=>:processor,
# :cache_terminus_class=>nil,
# :actual_cache_class=>nil,
# :primary_terminus_class=>Puppet::Transaction::Report::Processor,
# :actual_terminus_class=>Puppet::Transaction::Report::Processor,
# :terminus_setting=>nil,
# :termini=>
# {:msgpack=>Puppet::Transaction::Report::Msgpack,
# :processor=>Puppet::Transaction::Report::Processor,
# :rest=>Puppet::Transaction::Report::Rest,
# :yaml=>Puppet::Transaction::Report::Yaml}},
# :catalog=>
# {:indirected_class=>Puppet::Resource::Catalog,
# :cache_terminus_name=>:store_configs,
# :actual_cache_name=>:puppetdb,
# :primary_terminus_name=>:compiler,
# :actual_terminus_name=>:compiler,
# :cache_terminus_class=>Puppet::Resource::Catalog::StoreConfigs,
# :actual_cache_class=>Puppet::Resource::Catalog::Puppetdb,
# :primary_terminus_class=>Puppet::Resource::Catalog::Compiler,
# :actual_terminus_class=>Puppet::Resource::Catalog::Compiler,
# :terminus_setting=>:catalog_terminus,
# :termini=>
# {:compiler=>Puppet::Resource::Catalog::Compiler,
# :json=>Puppet::Resource::Catalog::Json,
# :msgpack=>Puppet::Resource::Catalog::Msgpack,
# :rest=>Puppet::Resource::Catalog::Rest,
# :store_configs=>Puppet::Resource::Catalog::StoreConfigs,
# :yaml=>Puppet::Resource::Catalog::Yaml,
# :puppetdb=>Puppet::Resource::Catalog::Puppetdb}},
# ...snip...
#
@Magisus
Copy link

Magisus commented Feb 21, 2019

What is the difference between primary and actual terminus? Seems kind of like unprocessed vs. processed, but I notice in your output they're always the same. Is there maybe another name that makes this relationship clearer?

I think in the example we would be using actual_terminus_* instead of actual_cache_*, right?

So thinking about the end-game here, when we keep talking about removing the indirector, are we hoping to replace it with something equally configurable, but thread safe and less opaque? Or are we planning to remove some of the configurability and cement the moving parts a bit? An approach like this seems to insulate us from a change like the former, but still allows for complete run-time configuration of the system, which, so long as that's the goal, seems good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment