diff options
author | Daniel Pittman <daniel@puppetlabs.com> | 2011-03-28 10:47:09 -0700 |
---|---|---|
committer | Daniel Pittman <daniel@puppetlabs.com> | 2011-03-28 10:47:09 -0700 |
commit | 2ad8c96935ec53c2d98201ad77fd070dc40dadb6 (patch) | |
tree | f8f4d581c3b0445df836d5e55945f62547239598 /lib/puppet/string | |
parent | 88aeb04a50d8997b5e1e0ed7a5a2239508b174ee (diff) | |
parent | b859baa04737644e40002f511c5941d002a956e3 (diff) | |
download | puppet-2ad8c96935ec53c2d98201ad77fd070dc40dadb6.tar.gz puppet-2ad8c96935ec53c2d98201ad77fd070dc40dadb6.tar.xz puppet-2ad8c96935ec53c2d98201ad77fd070dc40dadb6.zip |
Merge branch 'maint/master/puppet-strings-is-the-official-api-name'
Diffstat (limited to 'lib/puppet/string')
-rw-r--r-- | lib/puppet/string/action.rb | 26 | ||||
-rw-r--r-- | lib/puppet/string/action_builder.rb | 27 | ||||
-rw-r--r-- | lib/puppet/string/action_manager.rb | 45 | ||||
-rw-r--r-- | lib/puppet/string/indirector.rb | 79 | ||||
-rw-r--r-- | lib/puppet/string/string_collection.rb | 98 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/catalog.rb | 40 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/catalog/select.rb | 10 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/certificate.rb | 28 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/certificate_request.rb | 4 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/certificate_revocation_list.rb | 4 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/config.rb | 11 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/configurer.rb | 12 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/facts.rb | 18 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/file.rb | 5 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/key.rb | 4 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/node.rb | 5 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/report.rb | 15 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/resource.rb | 4 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/resource_type.rb | 4 | ||||
-rw-r--r-- | lib/puppet/string/v0.0.1/status.rb | 4 |
20 files changed, 443 insertions, 0 deletions
diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb new file mode 100644 index 000000000..4db9e97e2 --- /dev/null +++ b/lib/puppet/string/action.rb @@ -0,0 +1,26 @@ +require 'puppet/string' + +class Puppet::String::Action + attr_reader :name + + def initialize(string, name, attrs = {}) + name = name.to_s + raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/ + + @string = string + @name = name + attrs.each do |k,v| send("#{k}=", v) end + end + + def invoke(*args, &block) + @string.method(name).call(*args,&block) + end + + def invoke=(block) + if @string.is_a?(Class) + @string.define_method(@name, &block) + else + @string.meta_def(@name, &block) + end + end +end diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb new file mode 100644 index 000000000..b3db51104 --- /dev/null +++ b/lib/puppet/string/action_builder.rb @@ -0,0 +1,27 @@ +require 'puppet/string' +require 'puppet/string/action' + +class Puppet::String::ActionBuilder + attr_reader :action + + def self.build(string, name, &block) + name = name.to_s + raise "Action '#{name}' must specify a block" unless block + builder = new(string, name, &block) + builder.action + end + + def initialize(string, name, &block) + @string = string + @action = Puppet::String::Action.new(string, name) + instance_eval(&block) + end + + # Ideally the method we're defining here would be added to the action, and a + # method on the string would defer to it, but we can't get scope correct, + # so we stick with this. --daniel 2011-03-24 + def invoke(&block) + raise "Invoke called on an ActionBuilder with no corresponding Action" unless @action + @action.invoke = block + end +end diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb new file mode 100644 index 000000000..c29dbf454 --- /dev/null +++ b/lib/puppet/string/action_manager.rb @@ -0,0 +1,45 @@ +require 'puppet/string/action_builder' + +module Puppet::String::ActionManager + # Declare that this app can take a specific action, and provide + # the code to do so. + def action(name, &block) + @actions ||= {} + name = name.to_s.downcase.to_sym + + raise "Action #{name} already defined for #{self}" if action?(name) + + action = Puppet::String::ActionBuilder.build(self, name, &block) + + @actions[name] = action + end + + # This is the short-form of an action definition; it doesn't use the + # builder, just creates the action directly from the block. + def script(name, &block) + @actions ||= {} + name = name.to_s.downcase.to_sym + raise "Action #{name} already defined for #{self}" if action?(name) + @actions[name] = Puppet::String::Action.new(self, name, :invoke => block) + end + + def actions + @actions ||= {} + result = @actions.keys + + if self.is_a?(Class) and superclass.respond_to?(:actions) + result += superclass.actions + elsif self.class.respond_to?(:actions) + result += self.class.actions + end + result.sort + end + + def get_action(name) + @actions[name].dup + end + + def action?(name) + actions.include?(name.to_sym) + end +end diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb new file mode 100644 index 000000000..15984e39e --- /dev/null +++ b/lib/puppet/string/indirector.rb @@ -0,0 +1,79 @@ +require 'puppet' +require 'puppet/string' + +class Puppet::String::Indirector < Puppet::String + def self.indirections + Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort + end + + def self.terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort + end + + action :destroy do + invoke { |*args| call_indirection_method(:destroy, *args) } + end + + action :find do + invoke { |*args| call_indirection_method(:find, *args) } + end + + action :save do + invoke { |*args| call_indirection_method(:save, *args) } + end + + action :search do + invoke { |*args| call_indirection_method(:search, *args) } + end + + # Print the configuration for the current terminus class + action :info do + invoke do |*args| + if t = indirection.terminus_class + puts "Run mode '#{Puppet.run_mode.name}': #{t}" + else + $stderr.puts "No default terminus class for run mode '#{Puppet.run_mode.name}'" + end + end + end + + attr_accessor :from + + def indirection_name + @indirection_name || name.to_sym + end + + # Here's your opportunity to override the indirection name. By default + # it will be the same name as the string. + def set_indirection_name(name) + @indirection_name = name + end + + # Return an indirection associated with an string, if one exists + # One usually does. + def indirection + unless @indirection + Puppet.info("Could not find terminus for #{indirection_name}") unless @indirection = Puppet::Indirector::Indirection.instance(indirection_name) + end + @indirection + end + + def set_terminus(from) + begin + indirection.terminus_class = from + rescue => detail + raise "Could not set '#{indirection.name}' terminus to '#{from}' (#{detail}); valid terminus types are #{terminus_classes(indirection.name).join(", ") }" + end + end + + def call_indirection_method(method, *args) + begin + result = indirection.send(method, *args) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" + end + + result + end +end diff --git a/lib/puppet/string/string_collection.rb b/lib/puppet/string/string_collection.rb new file mode 100644 index 000000000..e9cba7f55 --- /dev/null +++ b/lib/puppet/string/string_collection.rb @@ -0,0 +1,98 @@ +require 'puppet/string' + +module Puppet::String::StringCollection + SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ + + @strings = Hash.new { |hash, key| hash[key] = {} } + + def self.strings + unless @loaded + @loaded = true + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + Dir.chdir(dir) do + Dir.glob("puppet/string/v*/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| + iname = file.sub(/\.rb/, '') + begin + require iname + rescue Exception => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not load #{iname} from #{dir}/#{file}: #{detail}" + end + end + end + end + end + return @strings.keys + end + + def self.versions(name) + versions = [] + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + v_dir = File.join dir, %w[puppet string v*] + Dir.glob(File.join v_dir, "#{name}{.rb,/*.rb}").each do |f| + v = f.sub(%r[.*/v([^/]+?)/#{name}(?:(?:/[^/]+)?.rb)$], '\1') + if validate_version(v) + versions << v + else + warn "'#{v}' (#{f}) is not a valid version string; skipping" + end + end + end + return versions.uniq.sort { |a, b| compare_versions(a, b) } + end + + def self.validate_version(version) + !!(SEMVER_VERSION =~ version.to_s) + end + + def self.compare_versions(a, b) + a, b = [a, b].map do |x| + parts = SEMVER_VERSION.match(x).to_a[1..4] + parts[0..2] = parts[0..2].map { |e| e.to_i } + parts + end + + cmp = a[0..2] <=> b[0..2] + if cmp == 0 + cmp = a[3] <=> b[3] + cmp = +1 if a[3].empty? && !b[3].empty? + cmp = -1 if b[3].empty? && !a[3].empty? + end + cmp + end + + def self.[](name, version) + version = versions(name).last if version == :latest + unless version.nil? + @strings[underscorize(name)][version] if string?(name, version) + end + end + + def self.string?(name, version) + version = versions(name).last if version == :latest + return false if version.nil? + + name = underscorize(name) + + unless @strings.has_key?(name) && @strings[name].has_key?(version) + require "puppet/string/v#{version}/#{name}" + end + return @strings.has_key?(name) && @strings[name].has_key?(version) + rescue LoadError + return false + end + + def self.register(string) + @strings[underscorize(string.name)][string.version] = string + end + + def self.underscorize(name) + unless name.to_s =~ /^[-_a-z]+$/i then + raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid string name" + end + + name.to_s.downcase.split(/[-_]/).join('_').to_sym + end +end diff --git a/lib/puppet/string/v0.0.1/catalog.rb b/lib/puppet/string/v0.0.1/catalog.rb new file mode 100644 index 000000000..0ddd83176 --- /dev/null +++ b/lib/puppet/string/v0.0.1/catalog.rb @@ -0,0 +1,40 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:catalog, '0.0.1') do + action(:apply) do + invoke do |catalog| + report = Puppet::Transaction::Report.new("apply") + report.configuration_version = catalog.version + + Puppet::Util::Log.newdestination(report) + + begin + benchmark(:notice, "Finished catalog run") do + catalog.apply(:report => report) + end + rescue => detail + puts detail.backtrace if Puppet[:trace] + Puppet.err "Failed to apply catalog: #{detail}" + end + + report.finalize_report + report + end + end + + action(:download) do + invoke do |certname,facts| + Puppet::Resource::Catalog.terminus_class = :rest + facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} + catalog = nil + retrieval_duration = thinmark do + catalog = Puppet::String[:catalog, '0.0.1'].find(certname, facts_to_upload) + end + catalog = catalog.to_ral + catalog.finalize + catalog.retrieval_duration = retrieval_duration + catalog.write_class_file + catalog + end + end +end diff --git a/lib/puppet/string/v0.0.1/catalog/select.rb b/lib/puppet/string/v0.0.1/catalog/select.rb new file mode 100644 index 000000000..52c77d3ce --- /dev/null +++ b/lib/puppet/string/v0.0.1/catalog/select.rb @@ -0,0 +1,10 @@ +# Select and show a list of resources of a given type. +Puppet::String.define(:catalog, '0.0.1') do + action :select do + invoke do |host,type| + catalog = Puppet::Resource::Catalog.indirection.find(host) + + catalog.resources.reject { |res| res.type != type }.each { |res| puts res } + end + end +end diff --git a/lib/puppet/string/v0.0.1/certificate.rb b/lib/puppet/string/v0.0.1/certificate.rb new file mode 100644 index 000000000..7b2e5f397 --- /dev/null +++ b/lib/puppet/string/v0.0.1/certificate.rb @@ -0,0 +1,28 @@ +require 'puppet/string/indirector' +require 'puppet/ssl/host' + +Puppet::String::Indirector.define(:certificate, '0.0.1') do + + action :generate do + invoke do |name| + host = Puppet::SSL::Host.new(name) + host.generate_certificate_request + host.certificate_request.class.indirection.save(host.certificate_request) + end + end + + action :list do + invoke do + Puppet::SSL::Host.indirection.search("*", { + :for => :certificate_request, + }).map { |h| h.inspect } + end + end + + action :sign do + invoke do |name| + Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) + end + end + +end diff --git a/lib/puppet/string/v0.0.1/certificate_request.rb b/lib/puppet/string/v0.0.1/certificate_request.rb new file mode 100644 index 000000000..218b40b98 --- /dev/null +++ b/lib/puppet/string/v0.0.1/certificate_request.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:certificate_request, '0.0.1') do +end diff --git a/lib/puppet/string/v0.0.1/certificate_revocation_list.rb b/lib/puppet/string/v0.0.1/certificate_revocation_list.rb new file mode 100644 index 000000000..9731b4f2d --- /dev/null +++ b/lib/puppet/string/v0.0.1/certificate_revocation_list.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:certificate_revocation_list, '0.0.1') do +end diff --git a/lib/puppet/string/v0.0.1/config.rb b/lib/puppet/string/v0.0.1/config.rb new file mode 100644 index 000000000..ae1a408cf --- /dev/null +++ b/lib/puppet/string/v0.0.1/config.rb @@ -0,0 +1,11 @@ +require 'puppet/string' + +Puppet::String.define(:config, '0.0.1') do + action(:print) do + invoke do |*args| + Puppet.settings[:configprint] = args.join(",") + Puppet.settings.print_config_options + nil + end + end +end diff --git a/lib/puppet/string/v0.0.1/configurer.rb b/lib/puppet/string/v0.0.1/configurer.rb new file mode 100644 index 000000000..a6ea74b6a --- /dev/null +++ b/lib/puppet/string/v0.0.1/configurer.rb @@ -0,0 +1,12 @@ +require 'puppet/string' + +Puppet::String.define(:configurer, '0.0.1') do + action(:synchronize) do + invoke do |certname| + facts = Puppet::String[:facts, '0.0.1'].find(certname) + catalog = Puppet::String[:catalog, '0.0.1'].download(certname, facts) + report = Puppet::String[:catalog, '0.0.1'].apply(catalog) + report + end + end +end diff --git a/lib/puppet/string/v0.0.1/facts.rb b/lib/puppet/string/v0.0.1/facts.rb new file mode 100644 index 000000000..73acb0df6 --- /dev/null +++ b/lib/puppet/string/v0.0.1/facts.rb @@ -0,0 +1,18 @@ +require 'puppet/string/indirector' +require 'puppet/node/facts' + +Puppet::String::Indirector.define(:facts, '0.0.1') do + set_default_format :yaml + + # Upload our facts to the server + action(:upload) do + invoke do |*args| + Puppet::Node::Facts.indirection.terminus_class = :facter + facts = Puppet::Node::Facts.indirection.find(Puppet[:certname]) + Puppet::Node::Facts.indirection.terminus_class = :rest + Puppet::Node::Facts.indirection.save(facts) + Puppet.notice "Uploaded facts for '#{Puppet[:certname]}'" + nil + end + end +end diff --git a/lib/puppet/string/v0.0.1/file.rb b/lib/puppet/string/v0.0.1/file.rb new file mode 100644 index 000000000..cc5737f28 --- /dev/null +++ b/lib/puppet/string/v0.0.1/file.rb @@ -0,0 +1,5 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:file, '0.0.1') do + set_indirection_name :file_bucket_file +end diff --git a/lib/puppet/string/v0.0.1/key.rb b/lib/puppet/string/v0.0.1/key.rb new file mode 100644 index 000000000..95aceade5 --- /dev/null +++ b/lib/puppet/string/v0.0.1/key.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:key, '0.0.1') do +end diff --git a/lib/puppet/string/v0.0.1/node.rb b/lib/puppet/string/v0.0.1/node.rb new file mode 100644 index 000000000..bc31a2cf3 --- /dev/null +++ b/lib/puppet/string/v0.0.1/node.rb @@ -0,0 +1,5 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:node, '0.0.1') do + set_default_format :yaml +end diff --git a/lib/puppet/string/v0.0.1/report.rb b/lib/puppet/string/v0.0.1/report.rb new file mode 100644 index 000000000..55a008533 --- /dev/null +++ b/lib/puppet/string/v0.0.1/report.rb @@ -0,0 +1,15 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:report, '0.0.1') do + action(:submit) do + invoke do |report| + begin + Puppet::Transaction::Report.terminus_class = :rest + report.save + rescue => detail + puts detail.backtrace if Puppet[:trace] + Puppet.err "Could not send report: #{detail}" + end + end + end +end diff --git a/lib/puppet/string/v0.0.1/resource.rb b/lib/puppet/string/v0.0.1/resource.rb new file mode 100644 index 000000000..9838be0fa --- /dev/null +++ b/lib/puppet/string/v0.0.1/resource.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:resource, '0.0.1') do +end diff --git a/lib/puppet/string/v0.0.1/resource_type.rb b/lib/puppet/string/v0.0.1/resource_type.rb new file mode 100644 index 000000000..8ca31ea6c --- /dev/null +++ b/lib/puppet/string/v0.0.1/resource_type.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:resource_type, '0.0.1') do +end diff --git a/lib/puppet/string/v0.0.1/status.rb b/lib/puppet/string/v0.0.1/status.rb new file mode 100644 index 000000000..41de2bb99 --- /dev/null +++ b/lib/puppet/string/v0.0.1/status.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:status, '0.0.1') do +end |