Don't have to parse/comprehend configuration format – Clever dynamic actions are possible • Cons – Service has to be up – Authentication may need to be working – Performance – API may be complex – API may be in an unknown language
resources • Resolve CLI – manifest authentication bootstrapping • Configure the githuboauth plugin • Manage user API tokens so that githuboauth does not cut off swarm slaves
puppetlabsaws relies on awssdk to pull credentials from the environment • DSL has resource defaults – Scope issues :( • Providers are limited to facts and introspecting on the catalog
not attached to a resource is difficult – Adrien/Hunter axis-of-evil-puppet-constructs pointed out that ::prefetch is called with a list of resources – resources are linked to the catalog
do |prov| if resource = resources[prov.name] resource.provider = prov end end end end Puppet::Type.type(:jenkins_user).provide(:cli, :parent => PuppetX::Jenkins::Provider::Cli) do def self.instances(catalog = nil) all = user_info_all(catalog) all.collect {|info| from_hash(info)} end end
• ::commands is ultimately a ::confine • This is kludged around in the core providers Puppet::Type.type(:package).provide :rpm, :source => :rpm, :parent => Puppet::Provider::Package do commands :rpm => "rpm" end Puppet::Type.type(:package).provide :yum, :parent => :rpm, :source => :rpm do commands :yum => "yum", :rpm => "rpm" end
the class confines into the subclass # this includes the confine(s) needed for commands # # The subclass seems to function with an empty @commands and any # value we try to push in will get reselt by ::initvars. def self.inherited(subclass) subclass.instance_variable_set(:@confine_collection, @confine_collection.dup) end commands :java => 'java' confine :feature => :retries end
= {}) ... # we already know that auth is required if class_variable_get(:@@cli_auth_required) return execute_exceptionify(auth_cmd, options) end begin # try first with no auth return execute_exceptionify(cli_cmd, options) rescue AuthError # retry with auth result = execute_exceptionify(auth_cmd, options) class_variable_set(:@@cli_auth_required, true) return result end end end `
& puppet_helper to be converged • Implemented with a simple wrapper around Puppet::Type::newtype() module PuppetX::Jenkins::Type::Cli def self.newtype(*args, &block) type = Puppet::Type.newtype(*args, &block) type.autorequire(:service) do ['jenkins'] end ... end end PuppetX::Jenkins::Type::Cli.newtype(:jenkins_job) do @doc = "Manage Jenkins' jobs" … end
class as a data source – Use ::prefetch to access the catalog and implement ::instances with a catalog argument – Fall back on facts to support puppet resource • Provider base class – “fixes” inheritance of confine – Shared state via class variables • Type factory wrapper for common autorequire
coming “real soon” • Need real-world usage feedback • Still needs to be integrated with existing defined types – Some semantics have changed (fixed) • Need acceptance tests that cover interaction with puppet_helper.groovy
catalog • No formal means of sharing information between providers • Accessing the catalog can be difficult from a provider • Singleton resources – DSL has classes – No core mechanism for types • Attempting to limit type/provider instances causes fallout • Provider inheritance is funky • Understanding ::prefetch, ::flush, ::instances, etc. requires reading the source – Beware newtype meta-dragons • Types can not be made private to a module • Types are not namespaces - jenkins_credentials instead of jenkins::credentials – Prevents direct conversion between DSL and native types