summaryrefslogtreecommitdiffstats
path: root/lib/puppet/string
diff options
context:
space:
mode:
authorDaniel Pittman <daniel@puppetlabs.com>2011-03-28 10:47:09 -0700
committerDaniel Pittman <daniel@puppetlabs.com>2011-03-28 10:47:09 -0700
commit2ad8c96935ec53c2d98201ad77fd070dc40dadb6 (patch)
treef8f4d581c3b0445df836d5e55945f62547239598 /lib/puppet/string
parent88aeb04a50d8997b5e1e0ed7a5a2239508b174ee (diff)
parentb859baa04737644e40002f511c5941d002a956e3 (diff)
downloadpuppet-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.rb26
-rw-r--r--lib/puppet/string/action_builder.rb27
-rw-r--r--lib/puppet/string/action_manager.rb45
-rw-r--r--lib/puppet/string/indirector.rb79
-rw-r--r--lib/puppet/string/string_collection.rb98
-rw-r--r--lib/puppet/string/v0.0.1/catalog.rb40
-rw-r--r--lib/puppet/string/v0.0.1/catalog/select.rb10
-rw-r--r--lib/puppet/string/v0.0.1/certificate.rb28
-rw-r--r--lib/puppet/string/v0.0.1/certificate_request.rb4
-rw-r--r--lib/puppet/string/v0.0.1/certificate_revocation_list.rb4
-rw-r--r--lib/puppet/string/v0.0.1/config.rb11
-rw-r--r--lib/puppet/string/v0.0.1/configurer.rb12
-rw-r--r--lib/puppet/string/v0.0.1/facts.rb18
-rw-r--r--lib/puppet/string/v0.0.1/file.rb5
-rw-r--r--lib/puppet/string/v0.0.1/key.rb4
-rw-r--r--lib/puppet/string/v0.0.1/node.rb5
-rw-r--r--lib/puppet/string/v0.0.1/report.rb15
-rw-r--r--lib/puppet/string/v0.0.1/resource.rb4
-rw-r--r--lib/puppet/string/v0.0.1/resource_type.rb4
-rw-r--r--lib/puppet/string/v0.0.1/status.rb4
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