From 809aebec7a54be90990b9ee5fea1f85204598f17 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Sun, 30 Jan 2011 17:33:28 -0800 Subject: Moving data executables to their own module Signed-off-by: Luke Kanies --- lib/puppet/application/catalog.rb | 4 + lib/puppet/application/certificate.rb | 4 + lib/puppet/application/certificate_request.rb | 4 + .../application/certificate_revocation_list.rb | 4 + lib/puppet/application/data.rb | 84 ++++++++++++ lib/puppet/application/data_baseclass.rb | 80 ++++++++++++ lib/puppet/application/facts.rb | 4 + lib/puppet/application/file_bucket_file.rb | 4 + lib/puppet/application/inventory.rb | 4 + lib/puppet/application/key.rb | 4 + lib/puppet/application/node.rb | 4 + lib/puppet/application/report.rb | 4 + lib/puppet/application/resource_type.rb | 4 + lib/puppet/application/status.rb | 4 + lib/puppet/interface.rb | 145 +++++++++++++++++++++ lib/puppet/interface/catalog.rb | 4 + lib/puppet/interface/catalog/select.rb | 4 + lib/puppet/interface/certificate.rb | 4 + lib/puppet/interface/certificate_request.rb | 4 + .../interface/certificate_revocation_list.rb | 4 + lib/puppet/interface/facts.rb | 10 ++ lib/puppet/interface/file_bucket_file.rb | 4 + lib/puppet/interface/inventory.rb | 4 + lib/puppet/interface/key.rb | 4 + lib/puppet/interface/node.rb | 4 + lib/puppet/interface/report.rb | 4 + lib/puppet/interface/resource_type.rb | 4 + lib/puppet/interface/status.rb | 4 + 28 files changed, 415 insertions(+) create mode 100644 lib/puppet/application/catalog.rb create mode 100644 lib/puppet/application/certificate.rb create mode 100644 lib/puppet/application/certificate_request.rb create mode 100644 lib/puppet/application/certificate_revocation_list.rb create mode 100644 lib/puppet/application/data.rb create mode 100644 lib/puppet/application/data_baseclass.rb create mode 100644 lib/puppet/application/facts.rb create mode 100644 lib/puppet/application/file_bucket_file.rb create mode 100644 lib/puppet/application/inventory.rb create mode 100644 lib/puppet/application/key.rb create mode 100644 lib/puppet/application/node.rb create mode 100644 lib/puppet/application/report.rb create mode 100644 lib/puppet/application/resource_type.rb create mode 100644 lib/puppet/application/status.rb create mode 100644 lib/puppet/interface.rb create mode 100644 lib/puppet/interface/catalog.rb create mode 100644 lib/puppet/interface/catalog/select.rb create mode 100644 lib/puppet/interface/certificate.rb create mode 100644 lib/puppet/interface/certificate_request.rb create mode 100644 lib/puppet/interface/certificate_revocation_list.rb create mode 100644 lib/puppet/interface/facts.rb create mode 100644 lib/puppet/interface/file_bucket_file.rb create mode 100644 lib/puppet/interface/inventory.rb create mode 100644 lib/puppet/interface/key.rb create mode 100644 lib/puppet/interface/node.rb create mode 100644 lib/puppet/interface/report.rb create mode 100644 lib/puppet/interface/resource_type.rb create mode 100644 lib/puppet/interface/status.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/catalog.rb b/lib/puppet/application/catalog.rb new file mode 100644 index 000000000..536d79c29 --- /dev/null +++ b/lib/puppet/application/catalog.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Catalog < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb new file mode 100644 index 000000000..708de07bb --- /dev/null +++ b/lib/puppet/application/certificate.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Certificate < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/certificate_request.rb b/lib/puppet/application/certificate_request.rb new file mode 100644 index 000000000..4363fc1ae --- /dev/null +++ b/lib/puppet/application/certificate_request.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Certificate_request < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/certificate_revocation_list.rb b/lib/puppet/application/certificate_revocation_list.rb new file mode 100644 index 000000000..158ed7b20 --- /dev/null +++ b/lib/puppet/application/certificate_revocation_list.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Certificate_revocation_list < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/data.rb b/lib/puppet/application/data.rb new file mode 100644 index 000000000..cfbf4305a --- /dev/null +++ b/lib/puppet/application/data.rb @@ -0,0 +1,84 @@ +require 'puppet/application' + +class Puppet::Application::Data < Puppet::Application + + should_parse_config + run_mode :agent + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + def list(*arguments) + if arguments.empty? + arguments = %w{terminuses actions} + end + indirections.each do |ind| + str = "#{ind}:\n" + if arguments.include?("terminuses") + begin + terms = terminus_classes(ind.to_sym) + str << "\tTerminuses: #{terms.join(", ")}\n" + rescue => detail + $stderr.puts "Could not load terminuses for #{ind}: #{detail}" + end + end + + if arguments.include?("actions") + begin + actions = actions(ind.to_sym) + str << "\tActions: #{actions.join(", ")}\n" + rescue => detail + $stderr.puts "Could not load actions for #{ind}: #{detail}" + end + end + + print str + end + exit(0) + end + + attr_accessor :verb, :name, :arguments + + def main + # Call the method associated with the provided action (e.g., 'find'). + send(verb, *arguments) + end + + def setup + Puppet::Util::Log.newdestination :console + + @verb, @arguments = command_line.args + @arguments ||= [] + + validate + end + + def validate + unless verb + raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" + end + + unless respond_to?(verb) + raise "Command '#{verb}' not found for 'data'" + end + end + + def indirections + Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort + end + + def terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + end + + def actions(indirection) + return [] unless app = Puppet::Application.find(indirection) + return app.actions.sort { |a,b| a.to_s <=> b.to_s } + end +end + diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb new file mode 100644 index 000000000..95142b8ba --- /dev/null +++ b/lib/puppet/application/data_baseclass.rb @@ -0,0 +1,80 @@ +require 'puppet/application' +require 'puppet/interface' + +class Puppet::Application::DataBaseclass < Puppet::Application + should_parse_config + run_mode :agent + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + option("--from TERMINUS", "-f") do |arg| + @from = arg + end + + option("--format FORMAT") do |arg| + @format = arg + end + + # XXX this doesn't work, I think + option("--list") do + indirections.each do |ind| + begin + classes = terminus_classes(ind.to_sym) + rescue => detail + $stderr.puts "Could not load terminuses for #{ind}: #{detail}" + next + end + puts "%-30s: #{classes.join(", ")}" % ind + end + exit(0) + end + + option("--mode RUNMODE", "-r") do |arg| + raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) + self.class.run_mode(arg.to_sym) + set_run_mode self.class.run_mode + end + + + attr_accessor :interface, :from, :type, :verb, :name, :arguments, :indirection, :format + + def main + # Call the method associated with the provided action (e.g., 'find'). + interface.send(verb, name, *arguments) + end + + def setup + @format ||= :yaml + + Puppet::Util::Log.newdestination :console + + @verb, @name, @arguments = command_line.args + @arguments ||= [] + + @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym + + @interface = Puppet::Interface.interface(@type).new + + validate + + raise "Could not find data type #{type} for application #{self.class.name}" unless @indirection = Puppet::Indirector::Indirection.instance(type) + + @interface.set_terminus(from) if from + end + + def validate + unless verb + raise "You must specify #{interface.actions.join(", ")} as a verb; 'save' probably does not work right now" + end + + unless interface.action?(verb) + raise "Command '#{verb}' not found for #{type}" + end + end +end diff --git a/lib/puppet/application/facts.rb b/lib/puppet/application/facts.rb new file mode 100644 index 000000000..dd79a00d9 --- /dev/null +++ b/lib/puppet/application/facts.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Facts < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/file_bucket_file.rb b/lib/puppet/application/file_bucket_file.rb new file mode 100644 index 000000000..f08a37f90 --- /dev/null +++ b/lib/puppet/application/file_bucket_file.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::File_bucket_file < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/inventory.rb b/lib/puppet/application/inventory.rb new file mode 100644 index 000000000..f54708f24 --- /dev/null +++ b/lib/puppet/application/inventory.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Inventory < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/key.rb b/lib/puppet/application/key.rb new file mode 100644 index 000000000..1197ae026 --- /dev/null +++ b/lib/puppet/application/key.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Key < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/node.rb b/lib/puppet/application/node.rb new file mode 100644 index 000000000..4d7de1ab2 --- /dev/null +++ b/lib/puppet/application/node.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Node < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/report.rb b/lib/puppet/application/report.rb new file mode 100644 index 000000000..e4b5cf440 --- /dev/null +++ b/lib/puppet/application/report.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Report < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/resource_type.rb b/lib/puppet/application/resource_type.rb new file mode 100644 index 000000000..5bd001e88 --- /dev/null +++ b/lib/puppet/application/resource_type.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Resource_type < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/status.rb b/lib/puppet/application/status.rb new file mode 100644 index 000000000..382532f7f --- /dev/null +++ b/lib/puppet/application/status.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::Status < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb new file mode 100644 index 000000000..2be3df5d6 --- /dev/null +++ b/lib/puppet/interface.rb @@ -0,0 +1,145 @@ +require 'puppet' + +class Puppet::Interface + # This is just so we can search for actions. We only use its + # list of directories to search. + def self.autoloader + require 'puppet/util/autoload' + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") + end + + # Declare that this app can take a specific action, and provide + # the code to do so. + def self.action(name, &block) + @actions ||= [] + name = name.to_s.downcase.to_sym + raise "Action #{name} already defined for #{name}" if actions.include?(name) + + @actions << name + + define_method(name, &block) + end + + def self.actions + @actions ||= [] + (if superclass.respond_to?(:actions) + @actions + superclass.actions + else + @actions + end).sort { |a,b| a.to_s <=> b.to_s } + end + + # Return an indirection associated with an interface, if one exists + # One usually does. + def self.indirection + unless @indirection + raise "Could not find data type '#{name}' for interface '#{name}'" unless @indirection = Puppet::Indirector::Indirection.instance(name.to_sym) + end + @indirection + end + + # Return an interface by name, loading from disk if necessary. + def self.interface(name) + require "puppet/interface/#{name.to_s.downcase}" + self.const_get(name.to_s.capitalize) + rescue Exception => detail + $stderr.puts "Unable to find interface '#{name.to_s}': #{detail}." + Kernel::exit(1) + end + + # Return the interface name. + def self.name + @name || self.to_s.sub(/.+::/, '').downcase + end + + attr_accessor :from, :type, :verb, :name, :arguments, :indirection, :format + + def action?(name) + self.class.actions.include?(name.to_sym) + end + + # Print the configuration for the current terminus class + action :showconfig do |*args| + if t = indirection.terminus_class + puts "Run mode #{Puppet.run_mode}: #{t}" + else + $stderr.puts "No default terminus class for run mode #{Puppet.run_mode}" + end + end + + action :destroy do |name, *args| + call_indirection_method(:destroy, name, *args) + end + + action :find do |name, *args| + call_indirection_method(:find, name, *args) + end + + action :save do |name, *args| + call_indirection_method(:save, name, *args) + end + + action :search do |name, *args| + call_indirection_method(:search, name, *args) + end + + def indirection + self.class.indirection + end + + def initialize(options = {}) + options.each { |opt, val| send(opt.to_s + "=", val) } + + @format ||= :yaml + + Puppet::Util::Log.newdestination :console + + load_actions + 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, name, *args) + begin + result = indirection.send(method, name, *args) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not call #{method} on #{type}: #{detail}" + end + + unless result + raise "Could not #{verb} #{type} for #{name}" + end + + puts result.render(format.to_sym) + end + + # Try to find actions defined in other files. + def load_actions + path = "puppet/interface/#{self.class.name}" + + self.class.autoloader.search_directories.each do |dir| + fdir = File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.glob("#{fdir}/*.rb").each do |file| + Puppet.info "Loading actions for '#{self.class.name}' from '#{file}'" + require file + end + end + end + + def indirections + Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort + end + + def terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + end +end diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb new file mode 100644 index 000000000..23e2b9cf5 --- /dev/null +++ b/lib/puppet/interface/catalog.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Catalog < Puppet::Interface +end diff --git a/lib/puppet/interface/catalog/select.rb b/lib/puppet/interface/catalog/select.rb new file mode 100644 index 000000000..6311a4a74 --- /dev/null +++ b/lib/puppet/interface/catalog/select.rb @@ -0,0 +1,4 @@ +# Select and show a list of resources of a given type. +Puppet::Interface::Catalog.action :select do |*args| + puts "Selecting #{args.inspect}" +end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb new file mode 100644 index 000000000..51e46c46b --- /dev/null +++ b/lib/puppet/interface/certificate.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Certificate < Puppet::Interface +end diff --git a/lib/puppet/interface/certificate_request.rb b/lib/puppet/interface/certificate_request.rb new file mode 100644 index 000000000..30ba5583a --- /dev/null +++ b/lib/puppet/interface/certificate_request.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Certificate_request < Puppet::Interface +end diff --git a/lib/puppet/interface/certificate_revocation_list.rb b/lib/puppet/interface/certificate_revocation_list.rb new file mode 100644 index 000000000..55a693918 --- /dev/null +++ b/lib/puppet/interface/certificate_revocation_list.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Certificate_revocation_list < Puppet::Interface +end diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb new file mode 100644 index 000000000..411416710 --- /dev/null +++ b/lib/puppet/interface/facts.rb @@ -0,0 +1,10 @@ +require 'puppet/interface' + +class Puppet::Interface::Facts < Puppet::Interface + # Upload our facts to the server + action(:upload) do |*args| + Puppet::Node::Facts.indirection.terminus_class = :facter + Puppet::Node::Facts.indirection.cache_class = :rest + Puppet::Node::Facts.indirection.find(Puppet[:certname]) + end +end diff --git a/lib/puppet/interface/file_bucket_file.rb b/lib/puppet/interface/file_bucket_file.rb new file mode 100644 index 000000000..f34ebc4c4 --- /dev/null +++ b/lib/puppet/interface/file_bucket_file.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::File_bucket_file < Puppet::Interface +end diff --git a/lib/puppet/interface/inventory.rb b/lib/puppet/interface/inventory.rb new file mode 100644 index 000000000..7521239d5 --- /dev/null +++ b/lib/puppet/interface/inventory.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Inventory < Puppet::Interface +end diff --git a/lib/puppet/interface/key.rb b/lib/puppet/interface/key.rb new file mode 100644 index 000000000..38f92c66b --- /dev/null +++ b/lib/puppet/interface/key.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Key < Puppet::Interface +end diff --git a/lib/puppet/interface/node.rb b/lib/puppet/interface/node.rb new file mode 100644 index 000000000..68e30698e --- /dev/null +++ b/lib/puppet/interface/node.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Node < Puppet::Interface +end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb new file mode 100644 index 000000000..72f1285ea --- /dev/null +++ b/lib/puppet/interface/report.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Report < Puppet::Interface +end diff --git a/lib/puppet/interface/resource_type.rb b/lib/puppet/interface/resource_type.rb new file mode 100644 index 000000000..619a4914b --- /dev/null +++ b/lib/puppet/interface/resource_type.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Resource_type < Puppet::Interface +end diff --git a/lib/puppet/interface/status.rb b/lib/puppet/interface/status.rb new file mode 100644 index 000000000..cdb1623ac --- /dev/null +++ b/lib/puppet/interface/status.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Status < Puppet::Interface +end -- cgit From efca35cbea836fac954fb655d76493f03b36e96f Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 8 Feb 2011 16:24:30 -0800 Subject: Finishing migration from puppet repo The whole system seems to work again, as long as you run it against 2.6.next. Signed-off-by: Luke Kanies --- lib/puppet/application/data.rb | 13 ++++++++++-- lib/puppet/application/data_baseclass.rb | 1 + lib/puppet/interface.rb | 34 ++++++++++++++++---------------- lib/puppet/interface/catalog/select.rb | 6 +++++- lib/puppet/interface/resource.rb | 4 ++++ 5 files changed, 38 insertions(+), 20 deletions(-) create mode 100644 lib/puppet/interface/resource.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/data.rb b/lib/puppet/application/data.rb index cfbf4305a..8d98d4416 100644 --- a/lib/puppet/application/data.rb +++ b/lib/puppet/application/data.rb @@ -52,6 +52,8 @@ class Puppet::Application::Data < Puppet::Application def setup Puppet::Util::Log.newdestination :console + load_applications # Call this to load all of the apps + @verb, @arguments = command_line.args @arguments ||= [] @@ -77,8 +79,15 @@ class Puppet::Application::Data < Puppet::Application end def actions(indirection) - return [] unless app = Puppet::Application.find(indirection) - return app.actions.sort { |a,b| a.to_s <=> b.to_s } + return [] unless interface = Puppet::Interface.interface(indirection) + interface.load_actions + return interface.actions.sort { |a,b| a.to_s <=> b.to_s } + end + + def load_applications + command_line.available_subcommands.each do |app| + command_line.require_application app + end end end diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb index 95142b8ba..3f498f56f 100644 --- a/lib/puppet/application/data_baseclass.rb +++ b/lib/puppet/application/data_baseclass.rb @@ -60,6 +60,7 @@ class Puppet::Application::DataBaseclass < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym @interface = Puppet::Interface.interface(@type).new + @interface.format = format if format validate diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 2be3df5d6..6e132f645 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -47,6 +47,21 @@ class Puppet::Interface Kernel::exit(1) end + # Try to find actions defined in other files. + def self.load_actions + path = "puppet/interface/#{name}" + + autoloader.search_directories.each do |dir| + fdir = File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.glob("#{fdir}/*.rb").each do |file| + Puppet.info "Loading actions for '#{name}' from '#{file}'" + require file + end + end + end + # Return the interface name. def self.name @name || self.to_s.sub(/.+::/, '').downcase @@ -94,7 +109,7 @@ class Puppet::Interface Puppet::Util::Log.newdestination :console - load_actions + self.class.load_actions end def set_terminus(from) @@ -114,27 +129,12 @@ class Puppet::Interface end unless result - raise "Could not #{verb} #{type} for #{name}" + raise "Could not #{method} #{indirection.name} for #{name}" end puts result.render(format.to_sym) end - # Try to find actions defined in other files. - def load_actions - path = "puppet/interface/#{self.class.name}" - - self.class.autoloader.search_directories.each do |dir| - fdir = File.join(dir, path) - next unless FileTest.directory?(fdir) - - Dir.glob("#{fdir}/*.rb").each do |file| - Puppet.info "Loading actions for '#{self.class.name}' from '#{file}'" - require file - end - end - end - def indirections Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort end diff --git a/lib/puppet/interface/catalog/select.rb b/lib/puppet/interface/catalog/select.rb index 6311a4a74..4bb49315c 100644 --- a/lib/puppet/interface/catalog/select.rb +++ b/lib/puppet/interface/catalog/select.rb @@ -1,4 +1,8 @@ # Select and show a list of resources of a given type. Puppet::Interface::Catalog.action :select do |*args| - puts "Selecting #{args.inspect}" + host = args.shift + type = args.shift + catalog = Puppet::Resource::Catalog.indirection.find(host) + + catalog.resources.reject { |res| res.type != type }.each { |res| puts res } end diff --git a/lib/puppet/interface/resource.rb b/lib/puppet/interface/resource.rb new file mode 100644 index 000000000..b9b007d00 --- /dev/null +++ b/lib/puppet/interface/resource.rb @@ -0,0 +1,4 @@ +require 'puppet/interface' + +class Puppet::Interface::Resource < Puppet::Interface +end -- cgit From 264a43c835a8131f3a2df5b5cf5c29c8bfcabb67 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 8 Feb 2011 16:26:10 -0800 Subject: Renaming "data" app to "interface" Signed-off-by: Luke Kanies --- lib/puppet/application/data.rb | 93 ------------------------------------- lib/puppet/application/interface.rb | 93 +++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 93 deletions(-) delete mode 100644 lib/puppet/application/data.rb create mode 100644 lib/puppet/application/interface.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/data.rb b/lib/puppet/application/data.rb deleted file mode 100644 index 8d98d4416..000000000 --- a/lib/puppet/application/data.rb +++ /dev/null @@ -1,93 +0,0 @@ -require 'puppet/application' - -class Puppet::Application::Data < Puppet::Application - - should_parse_config - run_mode :agent - - option("--debug", "-d") do |arg| - Puppet::Util::Log.level = :debug - end - - option("--verbose", "-v") do - Puppet::Util::Log.level = :info - end - - def list(*arguments) - if arguments.empty? - arguments = %w{terminuses actions} - end - indirections.each do |ind| - str = "#{ind}:\n" - if arguments.include?("terminuses") - begin - terms = terminus_classes(ind.to_sym) - str << "\tTerminuses: #{terms.join(", ")}\n" - rescue => detail - $stderr.puts "Could not load terminuses for #{ind}: #{detail}" - end - end - - if arguments.include?("actions") - begin - actions = actions(ind.to_sym) - str << "\tActions: #{actions.join(", ")}\n" - rescue => detail - $stderr.puts "Could not load actions for #{ind}: #{detail}" - end - end - - print str - end - exit(0) - end - - attr_accessor :verb, :name, :arguments - - def main - # Call the method associated with the provided action (e.g., 'find'). - send(verb, *arguments) - end - - def setup - Puppet::Util::Log.newdestination :console - - load_applications # Call this to load all of the apps - - @verb, @arguments = command_line.args - @arguments ||= [] - - validate - end - - def validate - unless verb - raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" - end - - unless respond_to?(verb) - raise "Command '#{verb}' not found for 'data'" - end - end - - def indirections - Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort - end - - def terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort - end - - def actions(indirection) - return [] unless interface = Puppet::Interface.interface(indirection) - interface.load_actions - return interface.actions.sort { |a,b| a.to_s <=> b.to_s } - end - - def load_applications - command_line.available_subcommands.each do |app| - command_line.require_application app - end - end -end - diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb new file mode 100644 index 000000000..8d98d4416 --- /dev/null +++ b/lib/puppet/application/interface.rb @@ -0,0 +1,93 @@ +require 'puppet/application' + +class Puppet::Application::Data < Puppet::Application + + should_parse_config + run_mode :agent + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + def list(*arguments) + if arguments.empty? + arguments = %w{terminuses actions} + end + indirections.each do |ind| + str = "#{ind}:\n" + if arguments.include?("terminuses") + begin + terms = terminus_classes(ind.to_sym) + str << "\tTerminuses: #{terms.join(", ")}\n" + rescue => detail + $stderr.puts "Could not load terminuses for #{ind}: #{detail}" + end + end + + if arguments.include?("actions") + begin + actions = actions(ind.to_sym) + str << "\tActions: #{actions.join(", ")}\n" + rescue => detail + $stderr.puts "Could not load actions for #{ind}: #{detail}" + end + end + + print str + end + exit(0) + end + + attr_accessor :verb, :name, :arguments + + def main + # Call the method associated with the provided action (e.g., 'find'). + send(verb, *arguments) + end + + def setup + Puppet::Util::Log.newdestination :console + + load_applications # Call this to load all of the apps + + @verb, @arguments = command_line.args + @arguments ||= [] + + validate + end + + def validate + unless verb + raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" + end + + unless respond_to?(verb) + raise "Command '#{verb}' not found for 'data'" + end + end + + def indirections + Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort + end + + def terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + end + + def actions(indirection) + return [] unless interface = Puppet::Interface.interface(indirection) + interface.load_actions + return interface.actions.sort { |a,b| a.to_s <=> b.to_s } + end + + def load_applications + command_line.available_subcommands.each do |app| + command_line.require_application app + end + end +end + -- cgit From 9cb594f898496e36c76f0717b73897f07e8aca5a Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 8 Feb 2011 16:46:47 -0800 Subject: Finishing the s/data/interface/ in the application Signed-off-by: Luke Kanies --- lib/puppet/application/interface.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb index 8d98d4416..db926df86 100644 --- a/lib/puppet/application/interface.rb +++ b/lib/puppet/application/interface.rb @@ -1,6 +1,6 @@ require 'puppet/application' -class Puppet::Application::Data < Puppet::Application +class Puppet::Application::Interface < Puppet::Application should_parse_config run_mode :agent @@ -66,7 +66,7 @@ class Puppet::Application::Data < Puppet::Application end unless respond_to?(verb) - raise "Command '#{verb}' not found for 'data'" + raise "Command '#{verb}' not found for 'interface'" end end -- cgit From 3ffb9abd3a500f1fb3246e04f737b79d232c082d Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 8 Feb 2011 21:27:24 -0800 Subject: Moving 'format' support to the application This allows easier use of the Interfaces in ruby. Signed-off-by: Luke Kanies --- lib/puppet/application/data_baseclass.rb | 8 ++++---- lib/puppet/interface.rb | 15 +++++++++++---- lib/puppet/interface/facts.rb | 2 ++ 3 files changed, 17 insertions(+), 8 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb index 3f498f56f..e67b1b368 100644 --- a/lib/puppet/application/data_baseclass.rb +++ b/lib/puppet/application/data_baseclass.rb @@ -18,7 +18,7 @@ class Puppet::Application::DataBaseclass < Puppet::Application end option("--format FORMAT") do |arg| - @format = arg + @format = arg.to_sym end # XXX this doesn't work, I think @@ -46,11 +46,11 @@ class Puppet::Application::DataBaseclass < Puppet::Application def main # Call the method associated with the provided action (e.g., 'find'). - interface.send(verb, name, *arguments) + result = interface.send(verb, name, *arguments) + puts result.render(format) end def setup - @format ||= :yaml Puppet::Util::Log.newdestination :console @@ -60,7 +60,7 @@ class Puppet::Application::DataBaseclass < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym @interface = Puppet::Interface.interface(@type).new - @interface.format = format if format + @format ||= @interface.class.default_format || :pson validate diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 6e132f645..f35a8bf44 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -1,6 +1,15 @@ require 'puppet' class Puppet::Interface + + class << self + attr_accessor :default_format + + def set_default_format(format) + self.default_format = format.to_sym + end + end + # This is just so we can search for actions. We only use its # list of directories to search. def self.autoloader @@ -67,7 +76,7 @@ class Puppet::Interface @name || self.to_s.sub(/.+::/, '').downcase end - attr_accessor :from, :type, :verb, :name, :arguments, :indirection, :format + attr_accessor :from, :type, :verb, :name, :arguments, :indirection def action?(name) self.class.actions.include?(name.to_sym) @@ -105,8 +114,6 @@ class Puppet::Interface def initialize(options = {}) options.each { |opt, val| send(opt.to_s + "=", val) } - @format ||= :yaml - Puppet::Util::Log.newdestination :console self.class.load_actions @@ -132,7 +139,7 @@ class Puppet::Interface raise "Could not #{method} #{indirection.name} for #{name}" end - puts result.render(format.to_sym) + result end def indirections diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb index 411416710..e40bb56d0 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/facts.rb @@ -1,6 +1,8 @@ require 'puppet/interface' class Puppet::Interface::Facts < Puppet::Interface + set_default_format :yaml + # Upload our facts to the server action(:upload) do |*args| Puppet::Node::Facts.indirection.terminus_class = :facter -- cgit From 9e124e1b3e3f3cd06db7ac58c3aefca3382cd870 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 10 Feb 2011 14:55:23 -0800 Subject: Fixing rendering to support arrays This isn't 100% - it will probably only work for Yaml and JSON - but it's a good start. Signed-off-by: Luke Kanies --- lib/puppet/application/data_baseclass.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb index e67b1b368..8da624c60 100644 --- a/lib/puppet/application/data_baseclass.rb +++ b/lib/puppet/application/data_baseclass.rb @@ -47,7 +47,8 @@ class Puppet::Application::DataBaseclass < Puppet::Application def main # Call the method associated with the provided action (e.g., 'find'). result = interface.send(verb, name, *arguments) - puts result.render(format) + render_method = Puppet::Network::FormatHandler.format(format).render_method + puts result.send(render_method) end def setup -- cgit From 782ca8df60c0adc6c264a196292032479d2c2f7c Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 16 Feb 2011 00:30:21 -0800 Subject: Fixing an error message Signed-off-by: Luke Kanies --- lib/puppet/interface.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index f35a8bf44..97e726a76 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -22,7 +22,7 @@ class Puppet::Interface def self.action(name, &block) @actions ||= [] name = name.to_s.downcase.to_sym - raise "Action #{name} already defined for #{name}" if actions.include?(name) + raise "Action #{name} already defined for #{self}" if actions.include?(name) @actions << name -- cgit From b3f903af34c0e27dccb1d043d84c35ea68f44830 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 16 Feb 2011 00:44:44 -0800 Subject: Enabling arbitrary interface names Previously the app, indirection, and interface names had to match exactly; now they can be arbitrary by just defining an overriding 'indirection_name' class method on the interface. I also renamed the file_bucket_file classes accordingly. Signed-off-by: Luke Kanies --- lib/puppet/application/data_baseclass.rb | 2 +- lib/puppet/application/file.rb | 4 ++++ lib/puppet/application/file_bucket_file.rb | 4 ---- lib/puppet/interface.rb | 11 +++++++++-- lib/puppet/interface/file.rb | 7 +++++++ lib/puppet/interface/file_bucket_file.rb | 4 ---- 6 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 lib/puppet/application/file.rb delete mode 100644 lib/puppet/application/file_bucket_file.rb create mode 100644 lib/puppet/interface/file.rb delete mode 100644 lib/puppet/interface/file_bucket_file.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb index 8da624c60..b7393f96c 100644 --- a/lib/puppet/application/data_baseclass.rb +++ b/lib/puppet/application/data_baseclass.rb @@ -65,7 +65,7 @@ class Puppet::Application::DataBaseclass < Puppet::Application validate - raise "Could not find data type #{type} for application #{self.class.name}" unless @indirection = Puppet::Indirector::Indirection.instance(type) + raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection @interface.set_terminus(from) if from end diff --git a/lib/puppet/application/file.rb b/lib/puppet/application/file.rb new file mode 100644 index 000000000..2acedda86 --- /dev/null +++ b/lib/puppet/application/file.rb @@ -0,0 +1,4 @@ +require 'puppet/application/data_baseclass' + +class Puppet::Application::File < Puppet::Application::DataBaseclass +end diff --git a/lib/puppet/application/file_bucket_file.rb b/lib/puppet/application/file_bucket_file.rb deleted file mode 100644 index f08a37f90..000000000 --- a/lib/puppet/application/file_bucket_file.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/application/data_baseclass' - -class Puppet::Application::File_bucket_file < Puppet::Application::DataBaseclass -end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 97e726a76..08a26db90 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -38,11 +38,17 @@ class Puppet::Interface end).sort { |a,b| a.to_s <=> b.to_s } end + # Here's your opportunity to override the indirection name. By default + # it will be the same name as the interface. + def self.indirection_name + name.to_sym + end + # Return an indirection associated with an interface, if one exists # One usually does. def self.indirection unless @indirection - raise "Could not find data type '#{name}' for interface '#{name}'" unless @indirection = Puppet::Indirector::Indirection.instance(name.to_sym) + raise "Could not find data type '#{indirection_name}' for interface '#{name}'" unless @indirection = Puppet::Indirector::Indirection.instance(indirection_name) end @indirection end @@ -52,6 +58,7 @@ class Puppet::Interface require "puppet/interface/#{name.to_s.downcase}" self.const_get(name.to_s.capitalize) rescue Exception => detail + puts detail.backtrace if Puppet[:trace] $stderr.puts "Unable to find interface '#{name.to_s}': #{detail}." Kernel::exit(1) end @@ -61,7 +68,7 @@ class Puppet::Interface path = "puppet/interface/#{name}" autoloader.search_directories.each do |dir| - fdir = File.join(dir, path) + fdir = ::File.join(dir, path) next unless FileTest.directory?(fdir) Dir.glob("#{fdir}/*.rb").each do |file| diff --git a/lib/puppet/interface/file.rb b/lib/puppet/interface/file.rb new file mode 100644 index 000000000..53c476d7c --- /dev/null +++ b/lib/puppet/interface/file.rb @@ -0,0 +1,7 @@ +require 'puppet/interface' + +class Puppet::Interface::File < Puppet::Interface + def self.indirection_name + :file_bucket_file + end +end diff --git a/lib/puppet/interface/file_bucket_file.rb b/lib/puppet/interface/file_bucket_file.rb deleted file mode 100644 index f34ebc4c4..000000000 --- a/lib/puppet/interface/file_bucket_file.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface' - -class Puppet::Interface::File_bucket_file < Puppet::Interface -end -- cgit From 7e3a02339a660a76019bf20243a7068325f1af68 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 16 Feb 2011 01:16:15 -0800 Subject: Only printing output if there is any Signed-off-by: Luke Kanies --- lib/puppet/application/data_baseclass.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb index b7393f96c..15ea961dc 100644 --- a/lib/puppet/application/data_baseclass.rb +++ b/lib/puppet/application/data_baseclass.rb @@ -48,7 +48,7 @@ class Puppet::Application::DataBaseclass < Puppet::Application # Call the method associated with the provided action (e.g., 'find'). result = interface.send(verb, name, *arguments) render_method = Puppet::Network::FormatHandler.format(format).render_method - puts result.send(render_method) + puts result.send(render_method) if result end def setup -- cgit From a54ee1e292238145bb0def2af6cf9ac22f2acd68 Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Sun, 13 Feb 2011 02:55:42 -0600 Subject: (#2) Should not assume interfaces have indirectors The initial work assumed that all interfaces were just skins on an indirected data type, but some interfaces will be more abstract than that. This commit removes that assumption by extracting all of the indirector work into a new Indirector subclass of Interface and then makes all of the new interfaces a subclass of that rather than of Interface itself. --- lib/puppet/interface.rb | 67 +----------------- lib/puppet/interface/catalog.rb | 4 +- lib/puppet/interface/certificate.rb | 4 +- lib/puppet/interface/certificate_request.rb | 4 +- .../interface/certificate_revocation_list.rb | 4 +- lib/puppet/interface/facts.rb | 4 +- lib/puppet/interface/file.rb | 4 +- lib/puppet/interface/indirector.rb | 82 ++++++++++++++++++++++ lib/puppet/interface/inventory.rb | 4 +- lib/puppet/interface/key.rb | 4 +- lib/puppet/interface/node.rb | 4 +- lib/puppet/interface/report.rb | 4 +- lib/puppet/interface/resource.rb | 4 +- lib/puppet/interface/resource_type.rb | 4 +- lib/puppet/interface/status.rb | 4 +- 15 files changed, 109 insertions(+), 92 deletions(-) create mode 100644 lib/puppet/interface/indirector.rb (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 08a26db90..999c38bad 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -38,21 +38,6 @@ class Puppet::Interface end).sort { |a,b| a.to_s <=> b.to_s } end - # Here's your opportunity to override the indirection name. By default - # it will be the same name as the interface. - def self.indirection_name - name.to_sym - end - - # Return an indirection associated with an interface, if one exists - # One usually does. - def self.indirection - unless @indirection - raise "Could not find data type '#{indirection_name}' for interface '#{name}'" unless @indirection = Puppet::Indirector::Indirection.instance(indirection_name) - end - @indirection - end - # Return an interface by name, loading from disk if necessary. def self.interface(name) require "puppet/interface/#{name.to_s.downcase}" @@ -83,7 +68,7 @@ class Puppet::Interface @name || self.to_s.sub(/.+::/, '').downcase end - attr_accessor :from, :type, :verb, :name, :arguments, :indirection + attr_accessor :type, :verb, :name, :arguments def action?(name) self.class.actions.include?(name.to_sym) @@ -98,26 +83,6 @@ class Puppet::Interface end end - action :destroy do |name, *args| - call_indirection_method(:destroy, name, *args) - end - - action :find do |name, *args| - call_indirection_method(:find, name, *args) - end - - action :save do |name, *args| - call_indirection_method(:save, name, *args) - end - - action :search do |name, *args| - call_indirection_method(:search, name, *args) - end - - def indirection - self.class.indirection - end - def initialize(options = {}) options.each { |opt, val| send(opt.to_s + "=", val) } @@ -126,34 +91,4 @@ class Puppet::Interface self.class.load_actions 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, name, *args) - begin - result = indirection.send(method, name, *args) - rescue => detail - puts detail.backtrace if Puppet[:trace] - raise "Could not call #{method} on #{type}: #{detail}" - end - - unless result - raise "Could not #{method} #{indirection.name} for #{name}" - end - - result - end - - def indirections - Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort - end - - def terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort - end end diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb index 23e2b9cf5..85aa2f37a 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/catalog.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Catalog < Puppet::Interface +class Puppet::Interface::Catalog < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 51e46c46b..48ca2c20f 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Certificate < Puppet::Interface +class Puppet::Interface::Certificate < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/certificate_request.rb b/lib/puppet/interface/certificate_request.rb index 30ba5583a..29dc73b9a 100644 --- a/lib/puppet/interface/certificate_request.rb +++ b/lib/puppet/interface/certificate_request.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Certificate_request < Puppet::Interface +class Puppet::Interface::Certificate_request < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/certificate_revocation_list.rb b/lib/puppet/interface/certificate_revocation_list.rb index 55a693918..144d5ef61 100644 --- a/lib/puppet/interface/certificate_revocation_list.rb +++ b/lib/puppet/interface/certificate_revocation_list.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Certificate_revocation_list < Puppet::Interface +class Puppet::Interface::Certificate_revocation_list < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb index e40bb56d0..42ba1fb81 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/facts.rb @@ -1,6 +1,6 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Facts < Puppet::Interface +class Puppet::Interface::Facts < Puppet::Interface::Indirector set_default_format :yaml # Upload our facts to the server diff --git a/lib/puppet/interface/file.rb b/lib/puppet/interface/file.rb index 53c476d7c..98a869153 100644 --- a/lib/puppet/interface/file.rb +++ b/lib/puppet/interface/file.rb @@ -1,6 +1,6 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::File < Puppet::Interface +class Puppet::Interface::File < Puppet::Interface::Indirector def self.indirection_name :file_bucket_file end diff --git a/lib/puppet/interface/indirector.rb b/lib/puppet/interface/indirector.rb new file mode 100644 index 000000000..f0beb8a9c --- /dev/null +++ b/lib/puppet/interface/indirector.rb @@ -0,0 +1,82 @@ +require 'puppet' +require 'puppet/interface' + +class Puppet::Interface::Indirector < Puppet::Interface + + + # Here's your opportunity to override the indirection name. By default + # it will be the same name as the interface. + def self.indirection_name + name.to_sym + end + + # Return an indirection associated with an interface, if one exists + # One usually does. + def self.indirection + unless @indirection + Puppet.info("Could not find terminus for #{indirection_name}") unless @indirection = Puppet::Indirector::Indirection.instance(indirection_name) + end + @indirection + end + + attr_accessor :from, :indirection + + action :destroy do |name, *args| + call_indirection_method(:destroy, name, *args) + end + + action :find do |name, *args| + call_indirection_method(:find, name, *args) + end + + action :save do |name, *args| + call_indirection_method(:save, name, *args) + end + + action :search do |name, *args| + call_indirection_method(:search, name, *args) + end + + def indirection + self.class.indirection + end + + def initialize(options = {}) + options.each { |opt, val| send(opt.to_s + "=", val) } + + Puppet::Util::Log.newdestination :console + + self.class.load_actions + 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, name, *args) + begin + result = indirection.send(method, name, *args) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not call #{method} on #{type}: #{detail}" + end + + unless result + raise "Could not #{method} #{indirection.name} for #{name}" + end + + result + end + + def indirections + Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort + end + + def terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + end +end diff --git a/lib/puppet/interface/inventory.rb b/lib/puppet/interface/inventory.rb index 7521239d5..16b216b8b 100644 --- a/lib/puppet/interface/inventory.rb +++ b/lib/puppet/interface/inventory.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Inventory < Puppet::Interface +class Puppet::Interface::Inventory < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/key.rb b/lib/puppet/interface/key.rb index 38f92c66b..17b661da1 100644 --- a/lib/puppet/interface/key.rb +++ b/lib/puppet/interface/key.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Key < Puppet::Interface +class Puppet::Interface::Key < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/node.rb b/lib/puppet/interface/node.rb index 68e30698e..5d9efa932 100644 --- a/lib/puppet/interface/node.rb +++ b/lib/puppet/interface/node.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Node < Puppet::Interface +class Puppet::Interface::Node < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb index 72f1285ea..fd6f45f16 100644 --- a/lib/puppet/interface/report.rb +++ b/lib/puppet/interface/report.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Report < Puppet::Interface +class Puppet::Interface::Report < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/resource.rb b/lib/puppet/interface/resource.rb index b9b007d00..deed0a533 100644 --- a/lib/puppet/interface/resource.rb +++ b/lib/puppet/interface/resource.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Resource < Puppet::Interface +class Puppet::Interface::Resource < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/resource_type.rb b/lib/puppet/interface/resource_type.rb index 619a4914b..6892926f0 100644 --- a/lib/puppet/interface/resource_type.rb +++ b/lib/puppet/interface/resource_type.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Resource_type < Puppet::Interface +class Puppet::Interface::Resource_type < Puppet::Interface::Indirector end diff --git a/lib/puppet/interface/status.rb b/lib/puppet/interface/status.rb index cdb1623ac..86ccab6e1 100644 --- a/lib/puppet/interface/status.rb +++ b/lib/puppet/interface/status.rb @@ -1,4 +1,4 @@ -require 'puppet/interface' +require 'puppet/interface/indirector' -class Puppet::Interface::Status < Puppet::Interface +class Puppet::Interface::Status < Puppet::Interface::Indirector end -- cgit From eff4eec9d53d4fb8270799458455fe4bdc47d1df Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Sun, 13 Feb 2011 02:53:23 -0600 Subject: (#3) Base application should catch SYSINT We should exit cleanly rather than throw traces. --- lib/puppet/application/data_baseclass.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb index 15ea961dc..599a217e9 100644 --- a/lib/puppet/application/data_baseclass.rb +++ b/lib/puppet/application/data_baseclass.rb @@ -5,6 +5,14 @@ class Puppet::Application::DataBaseclass < Puppet::Application should_parse_config run_mode :agent + def preinit + super + trap(:INT) do + $stderr.puts "Cancelling Interface" + exit(0) + end + end + option("--debug", "-d") do |arg| Puppet::Util::Log.level = :debug end -- cgit From cde1baa4a9a27ba95ad2a61bc8e46d43e708b081 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Sun, 20 Feb 2011 15:39:54 -0800 Subject: Fixing Interface listing It got broke when the Indirector base class was extracted. Signed-off-by: Luke Kanies --- lib/puppet/application/interface.rb | 42 +++++++++++++++++++++++++++++-------- lib/puppet/interface.rb | 7 ++++++- lib/puppet/interface/indirector.rb | 2 ++ 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb index db926df86..8f26658c9 100644 --- a/lib/puppet/application/interface.rb +++ b/lib/puppet/application/interface.rb @@ -17,23 +17,23 @@ class Puppet::Application::Interface < Puppet::Application if arguments.empty? arguments = %w{terminuses actions} end - indirections.each do |ind| - str = "#{ind}:\n" + interfaces.each do |name| + str = "#{name}:\n" if arguments.include?("terminuses") begin - terms = terminus_classes(ind.to_sym) + terms = terminus_classes(name.to_sym) str << "\tTerminuses: #{terms.join(", ")}\n" rescue => detail - $stderr.puts "Could not load terminuses for #{ind}: #{detail}" + $stderr.puts "Could not load terminuses for #{name}: #{detail}" end end if arguments.include?("actions") begin - actions = actions(ind.to_sym) + actions = actions(name.to_sym) str << "\tActions: #{actions.join(", ")}\n" rescue => detail - $stderr.puts "Could not load actions for #{ind}: #{detail}" + $stderr.puts "Could not load actions for #{name}: #{detail}" end end @@ -70,12 +70,36 @@ class Puppet::Application::Interface < Puppet::Application end end - def indirections - Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort + def interfaces + # Load all of the interfaces + unless @interfaces + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + Dir.chdir(dir) do + Dir.glob("puppet/interface/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| + begin + require file + rescue Error => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not load #{file}: #{detail}" + end + end + end + end + + @interfaces = [] + Puppet::Interface.constants.each do |name| + klass = Puppet::Interface.const_get(name) + next if klass.abstract? # skip base classes + + @interfaces << name.downcase + end + end + @interfaces end def terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort end def actions(indirection) diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 999c38bad..2e52de43d 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -3,7 +3,12 @@ require 'puppet' class Puppet::Interface class << self - attr_accessor :default_format + attr_accessor :default_format, :abstract + + # Is this an actual interface, or a base class for others? + def abstract? + abstract + end def set_default_format(format) self.default_format = format.to_sym diff --git a/lib/puppet/interface/indirector.rb b/lib/puppet/interface/indirector.rb index f0beb8a9c..507826b91 100644 --- a/lib/puppet/interface/indirector.rb +++ b/lib/puppet/interface/indirector.rb @@ -3,6 +3,8 @@ require 'puppet/interface' class Puppet::Interface::Indirector < Puppet::Interface + # This is just a base class. + @abstract = true # Here's your opportunity to override the indirection name. By default # it will be the same name as the interface. -- cgit From 0cbdbce0f518d43f0d0160a58dd5ec7253a5af87 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 09:25:21 -0800 Subject: Renaming 'data_baseclass' to 'interface_base' Signed-off-by: Luke Kanies --- lib/puppet/application/catalog.rb | 4 +- lib/puppet/application/certificate.rb | 4 +- lib/puppet/application/certificate_request.rb | 4 +- .../application/certificate_revocation_list.rb | 4 +- lib/puppet/application/data_baseclass.rb | 90 ---------------------- lib/puppet/application/facts.rb | 4 +- lib/puppet/application/file.rb | 4 +- lib/puppet/application/interface_base.rb | 90 ++++++++++++++++++++++ lib/puppet/application/inventory.rb | 4 +- lib/puppet/application/key.rb | 4 +- lib/puppet/application/node.rb | 4 +- lib/puppet/application/report.rb | 4 +- lib/puppet/application/resource_type.rb | 4 +- lib/puppet/application/status.rb | 4 +- 14 files changed, 114 insertions(+), 114 deletions(-) delete mode 100644 lib/puppet/application/data_baseclass.rb create mode 100644 lib/puppet/application/interface_base.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/catalog.rb b/lib/puppet/application/catalog.rb index 536d79c29..0151781a4 100644 --- a/lib/puppet/application/catalog.rb +++ b/lib/puppet/application/catalog.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Catalog < Puppet::Application::DataBaseclass +class Puppet::Application::Catalog < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb index 708de07bb..5033372eb 100644 --- a/lib/puppet/application/certificate.rb +++ b/lib/puppet/application/certificate.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Certificate < Puppet::Application::DataBaseclass +class Puppet::Application::Certificate < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/certificate_request.rb b/lib/puppet/application/certificate_request.rb index 4363fc1ae..f92876e95 100644 --- a/lib/puppet/application/certificate_request.rb +++ b/lib/puppet/application/certificate_request.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Certificate_request < Puppet::Application::DataBaseclass +class Puppet::Application::Certificate_request < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/certificate_revocation_list.rb b/lib/puppet/application/certificate_revocation_list.rb index 158ed7b20..9dd3bbba4 100644 --- a/lib/puppet/application/certificate_revocation_list.rb +++ b/lib/puppet/application/certificate_revocation_list.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Certificate_revocation_list < Puppet::Application::DataBaseclass +class Puppet::Application::Certificate_revocation_list < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/data_baseclass.rb b/lib/puppet/application/data_baseclass.rb deleted file mode 100644 index 599a217e9..000000000 --- a/lib/puppet/application/data_baseclass.rb +++ /dev/null @@ -1,90 +0,0 @@ -require 'puppet/application' -require 'puppet/interface' - -class Puppet::Application::DataBaseclass < Puppet::Application - should_parse_config - run_mode :agent - - def preinit - super - trap(:INT) do - $stderr.puts "Cancelling Interface" - exit(0) - end - end - - option("--debug", "-d") do |arg| - Puppet::Util::Log.level = :debug - end - - option("--verbose", "-v") do - Puppet::Util::Log.level = :info - end - - option("--from TERMINUS", "-f") do |arg| - @from = arg - end - - option("--format FORMAT") do |arg| - @format = arg.to_sym - end - - # XXX this doesn't work, I think - option("--list") do - indirections.each do |ind| - begin - classes = terminus_classes(ind.to_sym) - rescue => detail - $stderr.puts "Could not load terminuses for #{ind}: #{detail}" - next - end - puts "%-30s: #{classes.join(", ")}" % ind - end - exit(0) - end - - option("--mode RUNMODE", "-r") do |arg| - raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) - self.class.run_mode(arg.to_sym) - set_run_mode self.class.run_mode - end - - - attr_accessor :interface, :from, :type, :verb, :name, :arguments, :indirection, :format - - def main - # Call the method associated with the provided action (e.g., 'find'). - result = interface.send(verb, name, *arguments) - render_method = Puppet::Network::FormatHandler.format(format).render_method - puts result.send(render_method) if result - end - - def setup - - Puppet::Util::Log.newdestination :console - - @verb, @name, @arguments = command_line.args - @arguments ||= [] - - @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - - @interface = Puppet::Interface.interface(@type).new - @format ||= @interface.class.default_format || :pson - - validate - - raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection - - @interface.set_terminus(from) if from - end - - def validate - unless verb - raise "You must specify #{interface.actions.join(", ")} as a verb; 'save' probably does not work right now" - end - - unless interface.action?(verb) - raise "Command '#{verb}' not found for #{type}" - end - end -end diff --git a/lib/puppet/application/facts.rb b/lib/puppet/application/facts.rb index dd79a00d9..dfded58f7 100644 --- a/lib/puppet/application/facts.rb +++ b/lib/puppet/application/facts.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Facts < Puppet::Application::DataBaseclass +class Puppet::Application::Facts < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/file.rb b/lib/puppet/application/file.rb index 2acedda86..abf6230a3 100644 --- a/lib/puppet/application/file.rb +++ b/lib/puppet/application/file.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::File < Puppet::Application::DataBaseclass +class Puppet::Application::File < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb new file mode 100644 index 000000000..1dd1f76c2 --- /dev/null +++ b/lib/puppet/application/interface_base.rb @@ -0,0 +1,90 @@ +require 'puppet/application' +require 'puppet/interface' + +class Puppet::Application::InterfaceBase < Puppet::Application + should_parse_config + run_mode :agent + + def preinit + super + trap(:INT) do + $stderr.puts "Cancelling Interface" + exit(0) + end + end + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + option("--from TERMINUS", "-f") do |arg| + @from = arg + end + + option("--format FORMAT") do |arg| + @format = arg.to_sym + end + + # XXX this doesn't work, I think + option("--list") do + indirections.each do |ind| + begin + classes = terminus_classes(ind.to_sym) + rescue => detail + $stderr.puts "Could not load terminuses for #{ind}: #{detail}" + next + end + puts "%-30s: #{classes.join(", ")}" % ind + end + exit(0) + end + + option("--mode RUNMODE", "-r") do |arg| + raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) + self.class.run_mode(arg.to_sym) + set_run_mode self.class.run_mode + end + + + attr_accessor :interface, :from, :type, :verb, :name, :arguments, :indirection, :format + + def main + # Call the method associated with the provided action (e.g., 'find'). + result = interface.send(verb, name, *arguments) + render_method = Puppet::Network::FormatHandler.format(format).render_method + puts result.send(render_method) if result + end + + def setup + + Puppet::Util::Log.newdestination :console + + @verb, @name, @arguments = command_line.args + @arguments ||= [] + + @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym + + @interface = Puppet::Interface.interface(@type).new + @format ||= @interface.class.default_format || :pson + + validate + + raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection + + @interface.set_terminus(from) if from + end + + def validate + unless verb + raise "You must specify #{interface.actions.join(", ")} as a verb; 'save' probably does not work right now" + end + + unless interface.action?(verb) + raise "Command '#{verb}' not found for #{type}" + end + end +end diff --git a/lib/puppet/application/inventory.rb b/lib/puppet/application/inventory.rb index f54708f24..8a7e466df 100644 --- a/lib/puppet/application/inventory.rb +++ b/lib/puppet/application/inventory.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Inventory < Puppet::Application::DataBaseclass +class Puppet::Application::Inventory < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/key.rb b/lib/puppet/application/key.rb index 1197ae026..1458b9466 100644 --- a/lib/puppet/application/key.rb +++ b/lib/puppet/application/key.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Key < Puppet::Application::DataBaseclass +class Puppet::Application::Key < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/node.rb b/lib/puppet/application/node.rb index 4d7de1ab2..b5f566efc 100644 --- a/lib/puppet/application/node.rb +++ b/lib/puppet/application/node.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Node < Puppet::Application::DataBaseclass +class Puppet::Application::Node < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/report.rb b/lib/puppet/application/report.rb index e4b5cf440..994bc9ef1 100644 --- a/lib/puppet/application/report.rb +++ b/lib/puppet/application/report.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Report < Puppet::Application::DataBaseclass +class Puppet::Application::Report < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/resource_type.rb b/lib/puppet/application/resource_type.rb index 5bd001e88..ecc9f11f6 100644 --- a/lib/puppet/application/resource_type.rb +++ b/lib/puppet/application/resource_type.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Resource_type < Puppet::Application::DataBaseclass +class Puppet::Application::Resource_type < Puppet::Application::InterfaceBase end diff --git a/lib/puppet/application/status.rb b/lib/puppet/application/status.rb index 382532f7f..c34b89013 100644 --- a/lib/puppet/application/status.rb +++ b/lib/puppet/application/status.rb @@ -1,4 +1,4 @@ -require 'puppet/application/data_baseclass' +require 'puppet/application/interface_base' -class Puppet::Application::Status < Puppet::Application::DataBaseclass +class Puppet::Application::Status < Puppet::Application::InterfaceBase end -- cgit From 04fb6de5e2108799e47a081e5331d932fcf53109 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 11:59:19 -0800 Subject: Switching Interfaces to be instances They were previously classes, which made a lot of things stupider than they needed to be. This will likely involve some porting, but not much. Signed-off-by: Luke Kanies --- lib/puppet/application/interface_base.rb | 6 +- lib/puppet/interface.rb | 103 +++++++++++---------- lib/puppet/interface/action_manager.rb | 32 +++++++ lib/puppet/interface/catalog.rb | 2 +- lib/puppet/interface/certificate.rb | 2 +- lib/puppet/interface/certificate_request.rb | 2 +- .../interface/certificate_revocation_list.rb | 2 +- lib/puppet/interface/facts.rb | 3 +- lib/puppet/interface/file.rb | 6 +- lib/puppet/interface/indirector.rb | 58 +++++------- lib/puppet/interface/inventory.rb | 2 +- lib/puppet/interface/key.rb | 2 +- lib/puppet/interface/node.rb | 2 +- lib/puppet/interface/report.rb | 2 +- lib/puppet/interface/resource.rb | 2 +- lib/puppet/interface/resource_type.rb | 2 +- lib/puppet/interface/status.rb | 2 +- 17 files changed, 127 insertions(+), 103 deletions(-) create mode 100644 lib/puppet/interface/action_manager.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 1dd1f76c2..9a6c8d9ec 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -68,8 +68,10 @@ class Puppet::Application::InterfaceBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - @interface = Puppet::Interface.interface(@type).new - @format ||= @interface.class.default_format || :pson + unless @interface = Puppet::Interface.interface(@type) + raise "Could not find interface '#{@type}'" + end + @format ||= @interface.default_format || :pson validate diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 2e52de43d..901e83af6 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -1,60 +1,31 @@ require 'puppet' +require 'puppet/util/autoload' class Puppet::Interface + require 'puppet/interface/action_manager' - class << self - attr_accessor :default_format, :abstract - - # Is this an actual interface, or a base class for others? - def abstract? - abstract - end - - def set_default_format(format) - self.default_format = format.to_sym - end - end - + include Puppet::Interface::ActionManager + extend Puppet::Interface::ActionManager # This is just so we can search for actions. We only use its # list of directories to search. def self.autoloader - require 'puppet/util/autoload' @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") end - # Declare that this app can take a specific action, and provide - # the code to do so. - def self.action(name, &block) - @actions ||= [] - name = name.to_s.downcase.to_sym - raise "Action #{name} already defined for #{self}" if actions.include?(name) - - @actions << name - - define_method(name, &block) - end - - def self.actions - @actions ||= [] - (if superclass.respond_to?(:actions) - @actions + superclass.actions - else - @actions - end).sort { |a,b| a.to_s <=> b.to_s } - end - # Return an interface by name, loading from disk if necessary. def self.interface(name) - require "puppet/interface/#{name.to_s.downcase}" - self.const_get(name.to_s.capitalize) + @interfaces ||= {} + unless @interfaces[unify_name(name)] + require "puppet/interface/#{unify_name(name)}" + end + @interfaces[unify_name(name)] rescue Exception => detail puts detail.backtrace if Puppet[:trace] $stderr.puts "Unable to find interface '#{name.to_s}': #{detail}." - Kernel::exit(1) end # Try to find actions defined in other files. - def self.load_actions + def self.load_actions(name) path = "puppet/interface/#{name}" autoloader.search_directories.each do |dir| @@ -68,17 +39,43 @@ class Puppet::Interface end end + def self.register_interface(name, instance) + @interfaces ||= {} + @interfaces[unify_name(name)] = instance + const_set(name2const(name), instance) + end + + def self.unload_interface(name) + @interfaces ||= {} + @interfaces.delete(unify_name(name)) + const = name2const(name) + const_get(const) + remove_const(const) + rescue + # nothing - if the constant-getting fails, just return + end + + def self.unify_name(name) + name.to_s.downcase.to_sym + end + + def self.name2const(name) + name.to_s.capitalize + end + + attr_accessor :default_format + + def set_default_format(format) + self.default_format = format.to_sym + end + # Return the interface name. - def self.name + def name @name || self.to_s.sub(/.+::/, '').downcase end attr_accessor :type, :verb, :name, :arguments - def action?(name) - self.class.actions.include?(name.to_sym) - end - # Print the configuration for the current terminus class action :showconfig do |*args| if t = indirection.terminus_class @@ -88,12 +85,22 @@ class Puppet::Interface end end - def initialize(options = {}) + def initialize(name, options = {}, &block) + @name = name + + @default_format = :pson options.each { |opt, val| send(opt.to_s + "=", val) } - Puppet::Util::Log.newdestination :console + # We have to register before loading actions, + # since the actions require the registration + # Use the full class name, so this works with + # subclasses. + Puppet::Interface.register_interface(name, self) - self.class.load_actions - end + Puppet::Interface.load_actions(name) + if block_given? + instance_eval(&block) + end + end end diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb new file mode 100644 index 000000000..27a982929 --- /dev/null +++ b/lib/puppet/interface/action_manager.rb @@ -0,0 +1,32 @@ +module Puppet::Interface::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) + + @actions << name + if self.is_a?(Class) + define_method(name, &block) + else + meta_def(name, &block) + end + end + + def actions + @actions ||= [] + result = @actions.dup + + 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 { |a,b| a.to_s <=> b.to_s } + end + + def action?(name) + actions.include?(name.to_sym) + end +end diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb index 85aa2f37a..b2ed08f92 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/catalog.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Catalog < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:catalog) do end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 48ca2c20f..52ba4e3b8 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Certificate < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:certificate) do end diff --git a/lib/puppet/interface/certificate_request.rb b/lib/puppet/interface/certificate_request.rb index 29dc73b9a..77b485f8e 100644 --- a/lib/puppet/interface/certificate_request.rb +++ b/lib/puppet/interface/certificate_request.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Certificate_request < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:certificate_request) do end diff --git a/lib/puppet/interface/certificate_revocation_list.rb b/lib/puppet/interface/certificate_revocation_list.rb index 144d5ef61..ee1e6a8c4 100644 --- a/lib/puppet/interface/certificate_revocation_list.rb +++ b/lib/puppet/interface/certificate_revocation_list.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Certificate_revocation_list < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:certificate_revocation_list) do end diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb index 42ba1fb81..7b269e0d0 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/facts.rb @@ -1,6 +1,7 @@ require 'puppet/interface/indirector' +require 'puppet/node/facts' -class Puppet::Interface::Facts < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:facts) do set_default_format :yaml # Upload our facts to the server diff --git a/lib/puppet/interface/file.rb b/lib/puppet/interface/file.rb index 98a869153..9060c4042 100644 --- a/lib/puppet/interface/file.rb +++ b/lib/puppet/interface/file.rb @@ -1,7 +1,5 @@ require 'puppet/interface/indirector' -class Puppet::Interface::File < Puppet::Interface::Indirector - def self.indirection_name - :file_bucket_file - end +class Puppet::Interface::Indirector.new(:file) do + set_indirection_name :file_bucket_file end diff --git a/lib/puppet/interface/indirector.rb b/lib/puppet/interface/indirector.rb index 507826b91..feb356d85 100644 --- a/lib/puppet/interface/indirector.rb +++ b/lib/puppet/interface/indirector.rb @@ -2,27 +2,14 @@ require 'puppet' require 'puppet/interface' class Puppet::Interface::Indirector < Puppet::Interface - - # This is just a base class. - @abstract = true - - # Here's your opportunity to override the indirection name. By default - # it will be the same name as the interface. - def self.indirection_name - name.to_sym + def self.indirections + Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort end - # Return an indirection associated with an interface, if one exists - # One usually does. - def self.indirection - unless @indirection - Puppet.info("Could not find terminus for #{indirection_name}") unless @indirection = Puppet::Indirector::Indirection.instance(indirection_name) - end - @indirection + def self.terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort end - attr_accessor :from, :indirection - action :destroy do |name, *args| call_indirection_method(:destroy, name, *args) end @@ -39,16 +26,25 @@ class Puppet::Interface::Indirector < Puppet::Interface call_indirection_method(:search, name, *args) end - def indirection - self.class.indirection - end + attr_accessor :from - def initialize(options = {}) - options.each { |opt, val| send(opt.to_s + "=", val) } + def indirection_name + @indirection_name || name.to_sym + end - Puppet::Util::Log.newdestination :console + # Here's your opportunity to override the indirection name. By default + # it will be the same name as the interface. + def set_indirection_name(name) + @indirection_name = name + end - self.class.load_actions + # Return an indirection associated with an interface, 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) @@ -64,21 +60,9 @@ class Puppet::Interface::Indirector < Puppet::Interface result = indirection.send(method, name, *args) rescue => detail puts detail.backtrace if Puppet[:trace] - raise "Could not call #{method} on #{type}: #{detail}" - end - - unless result - raise "Could not #{method} #{indirection.name} for #{name}" + raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" end result end - - def indirections - Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort - end - - def terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort - end end diff --git a/lib/puppet/interface/inventory.rb b/lib/puppet/interface/inventory.rb index 16b216b8b..9b597c6ae 100644 --- a/lib/puppet/interface/inventory.rb +++ b/lib/puppet/interface/inventory.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Inventory < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:inventory) do end diff --git a/lib/puppet/interface/key.rb b/lib/puppet/interface/key.rb index 17b661da1..9343891d0 100644 --- a/lib/puppet/interface/key.rb +++ b/lib/puppet/interface/key.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Key < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:key) do end diff --git a/lib/puppet/interface/node.rb b/lib/puppet/interface/node.rb index 5d9efa932..7d7362d8b 100644 --- a/lib/puppet/interface/node.rb +++ b/lib/puppet/interface/node.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Node < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:node) do end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb index fd6f45f16..e7b916527 100644 --- a/lib/puppet/interface/report.rb +++ b/lib/puppet/interface/report.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Report < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:report) do end diff --git a/lib/puppet/interface/resource.rb b/lib/puppet/interface/resource.rb index deed0a533..65f2dec7a 100644 --- a/lib/puppet/interface/resource.rb +++ b/lib/puppet/interface/resource.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Resource < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:resource) do end diff --git a/lib/puppet/interface/resource_type.rb b/lib/puppet/interface/resource_type.rb index 6892926f0..bf16652a8 100644 --- a/lib/puppet/interface/resource_type.rb +++ b/lib/puppet/interface/resource_type.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Resource_type < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:resource_type) do end diff --git a/lib/puppet/interface/status.rb b/lib/puppet/interface/status.rb index 86ccab6e1..1a1d349d1 100644 --- a/lib/puppet/interface/status.rb +++ b/lib/puppet/interface/status.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Status < Puppet::Interface::Indirector +Puppet::Interface::Indirector.new(:status) do end -- cgit From 7da0a26f1bd44ecfffe9f622ec9d560870506207 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 13:36:18 -0800 Subject: Adding a string form to interfaces Signed-off-by: Luke Kanies --- lib/puppet/interface.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 901e83af6..70356debc 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -103,4 +103,8 @@ class Puppet::Interface instance_eval(&block) end end + + def to_s + name.to_s + end end -- cgit From c2715c0f20d916de0284e2d161eb5de32e508244 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 17:13:52 -0800 Subject: Splitting the Application base class We now have an indirection_base class along with interface_base. I've also added some basic tests for most of the interfaces. Signed-off-by: Luke Kanies --- lib/puppet/application/catalog.rb | 4 ++-- lib/puppet/application/certificate.rb | 4 ++-- lib/puppet/application/certificate_request.rb | 4 ++-- .../application/certificate_revocation_list.rb | 4 ++-- lib/puppet/application/facts.rb | 4 ++-- lib/puppet/application/file.rb | 4 ++-- lib/puppet/application/indirection_base.rb | 27 ++++++++++++++++++++++ lib/puppet/application/interface_base.rb | 27 ++-------------------- lib/puppet/application/inventory.rb | 4 ---- lib/puppet/application/key.rb | 4 ++-- lib/puppet/application/node.rb | 4 ++-- lib/puppet/application/report.rb | 4 ++-- lib/puppet/application/resource_type.rb | 4 ++-- lib/puppet/application/status.rb | 4 ++-- lib/puppet/interface/file.rb | 2 +- lib/puppet/interface/inventory.rb | 4 ---- 16 files changed, 52 insertions(+), 56 deletions(-) create mode 100644 lib/puppet/application/indirection_base.rb delete mode 100644 lib/puppet/application/inventory.rb delete mode 100644 lib/puppet/interface/inventory.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/catalog.rb b/lib/puppet/application/catalog.rb index 0151781a4..10ce05be7 100644 --- a/lib/puppet/application/catalog.rb +++ b/lib/puppet/application/catalog.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Catalog < Puppet::Application::InterfaceBase +class Puppet::Application::Catalog < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb index 5033372eb..4a2b3ef70 100644 --- a/lib/puppet/application/certificate.rb +++ b/lib/puppet/application/certificate.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Certificate < Puppet::Application::InterfaceBase +class Puppet::Application::Certificate < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/certificate_request.rb b/lib/puppet/application/certificate_request.rb index f92876e95..1b1b0830c 100644 --- a/lib/puppet/application/certificate_request.rb +++ b/lib/puppet/application/certificate_request.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Certificate_request < Puppet::Application::InterfaceBase +class Puppet::Application::Certificate_request < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/certificate_revocation_list.rb b/lib/puppet/application/certificate_revocation_list.rb index 9dd3bbba4..60b9d97d6 100644 --- a/lib/puppet/application/certificate_revocation_list.rb +++ b/lib/puppet/application/certificate_revocation_list.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Certificate_revocation_list < Puppet::Application::InterfaceBase +class Puppet::Application::Certificate_revocation_list < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/facts.rb b/lib/puppet/application/facts.rb index dfded58f7..d18b21ea7 100644 --- a/lib/puppet/application/facts.rb +++ b/lib/puppet/application/facts.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Facts < Puppet::Application::InterfaceBase +class Puppet::Application::Facts < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/file.rb b/lib/puppet/application/file.rb index abf6230a3..32a81c7c6 100644 --- a/lib/puppet/application/file.rb +++ b/lib/puppet/application/file.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::File < Puppet::Application::InterfaceBase +class Puppet::Application::File < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb new file mode 100644 index 000000000..3e907696e --- /dev/null +++ b/lib/puppet/application/indirection_base.rb @@ -0,0 +1,27 @@ +require 'puppet/application/interface_base' +require 'puppet/interface' + +class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase + option("--from TERMINUS", "-f") do |arg| + @from = arg + end + + attr_accessor :from, :indirection + + def main + # Call the method associated with the provided action (e.g., 'find'). + result = interface.send(verb, name, *arguments) + render_method = Puppet::Network::FormatHandler.format(format).render_method + puts result.send(render_method) if result + end + + def setup + super + + if interface.respond_to?(:indirection) + raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection + + interface.set_terminus(from) if from + end + end +end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 9a6c8d9ec..9e8ea9948 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -21,28 +21,10 @@ class Puppet::Application::InterfaceBase < Puppet::Application Puppet::Util::Log.level = :info end - option("--from TERMINUS", "-f") do |arg| - @from = arg - end - option("--format FORMAT") do |arg| @format = arg.to_sym end - # XXX this doesn't work, I think - option("--list") do - indirections.each do |ind| - begin - classes = terminus_classes(ind.to_sym) - rescue => detail - $stderr.puts "Could not load terminuses for #{ind}: #{detail}" - next - end - puts "%-30s: #{classes.join(", ")}" % ind - end - exit(0) - end - option("--mode RUNMODE", "-r") do |arg| raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) self.class.run_mode(arg.to_sym) @@ -50,7 +32,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application end - attr_accessor :interface, :from, :type, :verb, :name, :arguments, :indirection, :format + attr_accessor :interface, :type, :verb, :name, :arguments, :format def main # Call the method associated with the provided action (e.g., 'find'). @@ -60,7 +42,6 @@ class Puppet::Application::InterfaceBase < Puppet::Application end def setup - Puppet::Util::Log.newdestination :console @verb, @name, @arguments = command_line.args @@ -71,13 +52,9 @@ class Puppet::Application::InterfaceBase < Puppet::Application unless @interface = Puppet::Interface.interface(@type) raise "Could not find interface '#{@type}'" end - @format ||= @interface.default_format || :pson + @format ||= @interface.default_format validate - - raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection - - @interface.set_terminus(from) if from end def validate diff --git a/lib/puppet/application/inventory.rb b/lib/puppet/application/inventory.rb deleted file mode 100644 index 8a7e466df..000000000 --- a/lib/puppet/application/inventory.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/application/interface_base' - -class Puppet::Application::Inventory < Puppet::Application::InterfaceBase -end diff --git a/lib/puppet/application/key.rb b/lib/puppet/application/key.rb index 1458b9466..57835b627 100644 --- a/lib/puppet/application/key.rb +++ b/lib/puppet/application/key.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Key < Puppet::Application::InterfaceBase +class Puppet::Application::Key < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/node.rb b/lib/puppet/application/node.rb index b5f566efc..38c1f8610 100644 --- a/lib/puppet/application/node.rb +++ b/lib/puppet/application/node.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Node < Puppet::Application::InterfaceBase +class Puppet::Application::Node < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/report.rb b/lib/puppet/application/report.rb index 994bc9ef1..f7f961edd 100644 --- a/lib/puppet/application/report.rb +++ b/lib/puppet/application/report.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Report < Puppet::Application::InterfaceBase +class Puppet::Application::Report < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/resource_type.rb b/lib/puppet/application/resource_type.rb index ecc9f11f6..59594262c 100644 --- a/lib/puppet/application/resource_type.rb +++ b/lib/puppet/application/resource_type.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Resource_type < Puppet::Application::InterfaceBase +class Puppet::Application::Resource_type < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/application/status.rb b/lib/puppet/application/status.rb index c34b89013..1c3ca054e 100644 --- a/lib/puppet/application/status.rb +++ b/lib/puppet/application/status.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/indirection_base' -class Puppet::Application::Status < Puppet::Application::InterfaceBase +class Puppet::Application::Status < Puppet::Application::IndirectionBase end diff --git a/lib/puppet/interface/file.rb b/lib/puppet/interface/file.rb index 9060c4042..859f92ca4 100644 --- a/lib/puppet/interface/file.rb +++ b/lib/puppet/interface/file.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -class Puppet::Interface::Indirector.new(:file) do +Puppet::Interface::Indirector.new(:file) do set_indirection_name :file_bucket_file end diff --git a/lib/puppet/interface/inventory.rb b/lib/puppet/interface/inventory.rb deleted file mode 100644 index 9b597c6ae..000000000 --- a/lib/puppet/interface/inventory.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.new(:inventory) do -end -- cgit From 368210e8a8a35cf2cae509b1d357337f9958cdff Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 17:38:04 -0800 Subject: Adding a simple "config" app Signed-off-by: Luke Kanies --- lib/puppet/application/config.rb | 4 ++++ lib/puppet/interface/config.rb | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 lib/puppet/application/config.rb create mode 100644 lib/puppet/interface/config.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/config.rb b/lib/puppet/application/config.rb new file mode 100644 index 000000000..90c5f53c4 --- /dev/null +++ b/lib/puppet/application/config.rb @@ -0,0 +1,4 @@ +require 'puppet/application/interface_base' + +class Puppet::Application::Config < Puppet::Application::InterfaceBase +end diff --git a/lib/puppet/interface/config.rb b/lib/puppet/interface/config.rb new file mode 100644 index 000000000..501099a64 --- /dev/null +++ b/lib/puppet/interface/config.rb @@ -0,0 +1,10 @@ +require 'puppet/interface' + +Puppet::Interface.new(:config) do + action(:print) do |*args| + if name + Puppet.settings[:configprint] = args.join(",") + end + Puppet.settings.print_config_options + end +end -- cgit From bec807e5a12e24c11aedb40a997b154f1bed62c0 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 23:04:45 -0800 Subject: Fixing 'puppet interface list' Also added a test to hopefully confirm it won't break again. Signed-off-by: Luke Kanies --- lib/puppet/application/interface.rb | 30 +++----------------- lib/puppet/interface.rb | 56 ++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 42 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb index 8f26658c9..10823e920 100644 --- a/lib/puppet/application/interface.rb +++ b/lib/puppet/application/interface.rb @@ -1,4 +1,5 @@ require 'puppet/application' +require 'puppet/interface' class Puppet::Application::Interface < Puppet::Application @@ -24,6 +25,7 @@ class Puppet::Application::Interface < Puppet::Application terms = terminus_classes(name.to_sym) str << "\tTerminuses: #{terms.join(", ")}\n" rescue => detail + puts detail.backtrace if Puppet[:trace] $stderr.puts "Could not load terminuses for #{name}: #{detail}" end end @@ -33,13 +35,13 @@ class Puppet::Application::Interface < Puppet::Application actions = actions(name.to_sym) str << "\tActions: #{actions.join(", ")}\n" rescue => detail + puts detail.backtrace if Puppet[:trace] $stderr.puts "Could not load actions for #{name}: #{detail}" end end print str end - exit(0) end attr_accessor :verb, :name, :arguments @@ -71,31 +73,7 @@ class Puppet::Application::Interface < Puppet::Application end def interfaces - # Load all of the interfaces - unless @interfaces - $LOAD_PATH.each do |dir| - next unless FileTest.directory?(dir) - Dir.chdir(dir) do - Dir.glob("puppet/interface/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| - begin - require file - rescue Error => detail - puts detail.backtrace if Puppet[:trace] - raise "Could not load #{file}: #{detail}" - end - end - end - end - - @interfaces = [] - Puppet::Interface.constants.each do |name| - klass = Puppet::Interface.const_get(name) - next if klass.abstract? # skip base classes - - @interfaces << name.downcase - end - end - @interfaces + Puppet::Interface.interfaces end def terminus_classes(indirection) diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 70356debc..f8791e51f 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -12,6 +12,27 @@ class Puppet::Interface @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") end + def self.interfaces + unless @loaded + @loaded = true + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + Dir.chdir(dir) do + Dir.glob("puppet/interface/*.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 + @interfaces.keys + end + # Return an interface by name, loading from disk if necessary. def self.interface(name) @interfaces ||= {} @@ -24,21 +45,6 @@ class Puppet::Interface $stderr.puts "Unable to find interface '#{name.to_s}': #{detail}." end - # Try to find actions defined in other files. - def self.load_actions(name) - path = "puppet/interface/#{name}" - - autoloader.search_directories.each do |dir| - fdir = ::File.join(dir, path) - next unless FileTest.directory?(fdir) - - Dir.glob("#{fdir}/*.rb").each do |file| - Puppet.info "Loading actions for '#{name}' from '#{file}'" - require file - end - end - end - def self.register_interface(name, instance) @interfaces ||= {} @interfaces[unify_name(name)] = instance @@ -97,13 +103,31 @@ class Puppet::Interface # subclasses. Puppet::Interface.register_interface(name, self) - Puppet::Interface.load_actions(name) + load_actions if block_given? instance_eval(&block) end end + # Try to find actions defined in other files. + def load_actions + path = "puppet/interface/#{name}" + + self.class.autoloader.search_directories.each do |dir| + fdir = ::File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.chdir(fdir) do + Dir.glob("*.rb").each do |file| + aname = file.sub(/\.rb/, '') + Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + require "#{path}/#{aname}" + end + end + end + end + def to_s name.to_s end -- cgit From 4fa54d02a2806e8fde54da9bb7e4d6735b3cffe4 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Feb 2011 23:49:01 -0800 Subject: Adding render and exit_code override support This is mostly in response to feature requests from Dan. Signed-off-by: Luke Kanies --- lib/puppet/application/interface_base.rb | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 9e8ea9948..49c2e9622 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -33,12 +33,26 @@ class Puppet::Application::InterfaceBase < Puppet::Application attr_accessor :interface, :type, :verb, :name, :arguments, :format + attr_writer :exit_code + + # This allows you to set the exit code if you don't want to just exit + # immediately but you need to indicate a failure. + def exit_code + @exit_code || 0 + end def main # Call the method associated with the provided action (e.g., 'find'). - result = interface.send(verb, name, *arguments) + if result = interface.send(verb, name, *arguments) + puts render(result) + end + exit(exit_code) + end + + # Override this if you need custom rendering. + def render(result) render_method = Puppet::Network::FormatHandler.format(format).render_method - puts result.send(render_method) if result + result.send(render_method) end def setup -- cgit From 59a648502a8f09948bd2d25a72a9099f7740e108 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 23 Feb 2011 00:20:15 -0800 Subject: Adding Application options to Interfaces This allows all of the actions to react to the CLI options. I've also removed the unnecessary 'name' variables I was using in various places - they were just the first of the arguments, and they weren't actually always names. Signed-off-by: Luke Kanies --- lib/puppet/application/interface_base.rb | 10 +++++++--- lib/puppet/interface.rb | 2 +- lib/puppet/interface/indirector.rb | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 14 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 49c2e9622..044249d39 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -32,7 +32,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application end - attr_accessor :interface, :type, :verb, :name, :arguments, :format + attr_accessor :interface, :type, :verb, :arguments, :format attr_writer :exit_code # This allows you to set the exit code if you don't want to just exit @@ -43,7 +43,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application def main # Call the method associated with the provided action (e.g., 'find'). - if result = interface.send(verb, name, *arguments) + if result = interface.send(verb, *arguments) puts render(result) end exit(exit_code) @@ -58,7 +58,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application def setup Puppet::Util::Log.newdestination :console - @verb, @name, @arguments = command_line.args + @verb, @arguments = command_line.args @arguments ||= [] @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym @@ -68,6 +68,10 @@ class Puppet::Application::InterfaceBase < Puppet::Application end @format ||= @interface.default_format + # We copy all of the app options to the interface. + # This allows each action to read in the options. + @interface.options = options + validate end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index f8791e51f..3fb61c8a8 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -80,7 +80,7 @@ class Puppet::Interface @name || self.to_s.sub(/.+::/, '').downcase end - attr_accessor :type, :verb, :name, :arguments + attr_accessor :type, :verb, :name, :arguments, :options # Print the configuration for the current terminus class action :showconfig do |*args| diff --git a/lib/puppet/interface/indirector.rb b/lib/puppet/interface/indirector.rb index feb356d85..f106db4b8 100644 --- a/lib/puppet/interface/indirector.rb +++ b/lib/puppet/interface/indirector.rb @@ -10,20 +10,20 @@ class Puppet::Interface::Indirector < Puppet::Interface Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort end - action :destroy do |name, *args| - call_indirection_method(:destroy, name, *args) + action :destroy do |*args| + call_indirection_method(:destroy, *args) end - action :find do |name, *args| - call_indirection_method(:find, name, *args) + action :find do |*args| + call_indirection_method(:find, *args) end - action :save do |name, *args| - call_indirection_method(:save, name, *args) + action :save do |*args| + call_indirection_method(:save, *args) end - action :search do |name, *args| - call_indirection_method(:search, name, *args) + action :search do |*args| + call_indirection_method(:search, *args) end attr_accessor :from @@ -55,9 +55,9 @@ class Puppet::Interface::Indirector < Puppet::Interface end end - def call_indirection_method(method, name, *args) + def call_indirection_method(method, *args) begin - result = indirection.send(method, name, *args) + result = indirection.send(method, *args) rescue => detail puts detail.backtrace if Puppet[:trace] raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" -- cgit From 21b541d6ca4b1b76a4e0cd525fa66192c0857a5e Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 24 Feb 2011 08:34:24 -0800 Subject: Fixing plugin usage I had broken some usages of plugins by incorrectly selecting command-line arguments. The fix was to remove the #main method contained in the IndirectionBase subclass. Signed-off-by: Luke Kanies --- lib/puppet/application/indirection_base.rb | 7 ------- lib/puppet/application/interface_base.rb | 2 ++ 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index 3e907696e..e6d172ced 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -8,13 +8,6 @@ class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase attr_accessor :from, :indirection - def main - # Call the method associated with the provided action (e.g., 'find'). - result = interface.send(verb, name, *arguments) - render_method = Puppet::Network::FormatHandler.format(format).render_method - puts result.send(render_method) if result - end - def setup super diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 044249d39..70022f17d 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -61,6 +61,8 @@ class Puppet::Application::InterfaceBase < Puppet::Application @verb, @arguments = command_line.args @arguments ||= [] + @arguments = Array(@arguments) + @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym unless @interface = Puppet::Interface.interface(@type) -- cgit From 66c994ac43347c735f0ea4158b38557d32ec5747 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 24 Feb 2011 10:24:08 -0800 Subject: Attempting to skip loading of duplicate actions Signed-off-by: Luke Kanies --- lib/puppet/interface.rb | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 3fb61c8a8..1dfb34cf3 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -114,6 +114,7 @@ class Puppet::Interface def load_actions path = "puppet/interface/#{name}" + loaded = [] self.class.autoloader.search_directories.each do |dir| fdir = ::File.join(dir, path) next unless FileTest.directory?(fdir) @@ -121,6 +122,11 @@ class Puppet::Interface Dir.chdir(fdir) do Dir.glob("*.rb").each do |file| aname = file.sub(/\.rb/, '') + if loaded.include?(aname) + Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + next + end + loaded << aname Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" require "#{path}/#{aname}" end -- cgit From 905ff3aee31775e3fff3ebf8a2eaa6bb2cf0f431 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Sun, 27 Feb 2011 16:34:10 -0800 Subject: Pretty-printing json using "jj" Signed-off-by: Luke Kanies --- lib/puppet/application/interface_base.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 70022f17d..d54ac7922 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -52,7 +52,12 @@ class Puppet::Application::InterfaceBase < Puppet::Application # Override this if you need custom rendering. def render(result) render_method = Puppet::Network::FormatHandler.format(format).render_method - result.send(render_method) + if render_method == "to_pson" + jj result + exit(0) + else + result.send(render_method) + end end def setup -- cgit From 353b9145e465a002f1b66f2a616cce3a8647d370 Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Tue, 1 Mar 2011 19:09:20 -0600 Subject: (14) updated interface_base to support multiple command line arguments --- lib/puppet/application/interface_base.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index d54ac7922..58fc3b80b 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -63,7 +63,8 @@ class Puppet::Application::InterfaceBase < Puppet::Application def setup Puppet::Util::Log.newdestination :console - @verb, @arguments = command_line.args + @verb = command_line.args.shift + @arguments = command_line.args @arguments ||= [] @arguments = Array(@arguments) -- cgit From 23064bb601622f8a0efaf47c66a9fefec6e62f95 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 2 Mar 2011 17:13:44 -0800 Subject: Adding a test for fix to #14 Signed-off-by: Luke Kanies --- lib/puppet/application/interface_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 58fc3b80b..88f97b69b 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -63,7 +63,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application def setup Puppet::Util::Log.newdestination :console - @verb = command_line.args.shift + @verb = command_line.args.shift @arguments = command_line.args @arguments ||= [] -- cgit From 63263a41ab361985845ef514a3d1247a41f46475 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 2 Mar 2011 17:19:36 -0800 Subject: Fixing #13 - showconfig moved to indirector I renamed it to 'info', too. It only showed indirector-related info, so this makes sense. Signed-off-by: Luke Kanies --- lib/puppet/interface.rb | 9 --------- lib/puppet/interface/indirector.rb | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 1dfb34cf3..476de8bbf 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -82,15 +82,6 @@ class Puppet::Interface attr_accessor :type, :verb, :name, :arguments, :options - # Print the configuration for the current terminus class - action :showconfig do |*args| - if t = indirection.terminus_class - puts "Run mode #{Puppet.run_mode}: #{t}" - else - $stderr.puts "No default terminus class for run mode #{Puppet.run_mode}" - end - end - def initialize(name, options = {}, &block) @name = name diff --git a/lib/puppet/interface/indirector.rb b/lib/puppet/interface/indirector.rb index f106db4b8..9c26cc37a 100644 --- a/lib/puppet/interface/indirector.rb +++ b/lib/puppet/interface/indirector.rb @@ -26,6 +26,15 @@ class Puppet::Interface::Indirector < Puppet::Interface call_indirection_method(:search, *args) end + # Print the configuration for the current terminus class + action :info 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 + attr_accessor :from def indirection_name -- cgit From ece0c8e8defeec7af5aa28bb583bbb69aaba79a9 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 2 Mar 2011 17:32:07 -0800 Subject: Fixing #16 - nodes default to yaml We don't have json support for node output yet. Signed-off-by: Luke Kanies --- lib/puppet/interface/node.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/node.rb b/lib/puppet/interface/node.rb index 7d7362d8b..0a0f57a1e 100644 --- a/lib/puppet/interface/node.rb +++ b/lib/puppet/interface/node.rb @@ -1,4 +1,5 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.new(:node) do + set_default_format :yaml end -- cgit From f67e7fa39479751a7c5268bd32e503e35602ce4f Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 2 Mar 2011 18:16:41 -0800 Subject: Modifying Facts.upload a bit The functionality is basically the same, but we're no longer using caching, and we log that it happened. Signed-off-by: Luke Kanies --- lib/puppet/interface/facts.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb index 7b269e0d0..326274545 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/facts.rb @@ -7,7 +7,10 @@ Puppet::Interface::Indirector.new(:facts) do # Upload our facts to the server action(:upload) do |*args| Puppet::Node::Facts.indirection.terminus_class = :facter - Puppet::Node::Facts.indirection.cache_class = :rest - Puppet::Node::Facts.indirection.find(Puppet[:certname]) + 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 -- cgit From b187e071ac1b334878498d52ee6c18f8c0e6a5d9 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Fri, 18 Mar 2011 20:53:00 -0700 Subject: (#6786) Removing the #interface method. Since constants are already being defined for each interface, the #interface method does little but provide another way to access the same data. Reviewed-By: Nick Lewis --- lib/puppet/interface.rb | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 476de8bbf..f9b26950a 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -6,8 +6,10 @@ class Puppet::Interface include Puppet::Interface::ActionManager extend Puppet::Interface::ActionManager + # This is just so we can search for actions. We only use its # list of directories to search. + # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb def self.autoloader @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") end @@ -30,35 +32,22 @@ class Puppet::Interface end end end - @interfaces.keys + Puppet::Interface.constants.map { |c| c.to_s.downcase } end - # Return an interface by name, loading from disk if necessary. - def self.interface(name) - @interfaces ||= {} - unless @interfaces[unify_name(name)] - require "puppet/interface/#{unify_name(name)}" - end - @interfaces[unify_name(name)] - rescue Exception => detail - puts detail.backtrace if Puppet[:trace] - $stderr.puts "Unable to find interface '#{name.to_s}': #{detail}." + def self.const_missing(name) + require "puppet/interface/#{name.to_s.downcase}" + const_get(name) if const_defined?(name) + rescue LoadError + nil end def self.register_interface(name, instance) - @interfaces ||= {} - @interfaces[unify_name(name)] = instance const_set(name2const(name), instance) end def self.unload_interface(name) - @interfaces ||= {} - @interfaces.delete(unify_name(name)) - const = name2const(name) - const_get(const) - remove_const(const) - rescue - # nothing - if the constant-getting fails, just return + remove_const(name2const(name)) rescue nil end def self.unify_name(name) -- cgit From a7173dc2054c4167c71a23fb70e3ca54d07c7447 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Mon, 21 Mar 2011 15:00:17 -0700 Subject: (#6786) Fixing a number of failing tests. The initial merge of this branch hadn't actually been run against the full suite of specs; a number of specs began failing shortly afterward. Reviewed-By: Daniel Pittman --- lib/puppet/application/indirection_base.rb | 2 +- lib/puppet/application/interface_base.rb | 2 +- lib/puppet/interface.rb | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index e6d172ced..764098925 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -2,7 +2,7 @@ require 'puppet/application/interface_base' require 'puppet/interface' class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase - option("--from TERMINUS", "-f") do |arg| + option("--terminus TERMINUS") do |arg| @from = arg end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 88f97b69b..1f18b086c 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -71,7 +71,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - unless @interface = Puppet::Interface.interface(@type) + unless @interface = Puppet::Interface.const_get(@type) raise "Could not find interface '#{@type}'" end @format ||= @interface.default_format diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index f9b26950a..dfd75ef58 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -42,20 +42,25 @@ class Puppet::Interface nil end + def self.const_get(name) + name = constantize(name) + super(name) + end + def self.register_interface(name, instance) - const_set(name2const(name), instance) + const_set(constantize(name), instance) end def self.unload_interface(name) - remove_const(name2const(name)) rescue nil + remove_const(constantize(name)) rescue nil end def self.unify_name(name) name.to_s.downcase.to_sym end - def self.name2const(name) - name.to_s.capitalize + def self.constantize(name) + name.to_s.split(/\W|_/).map { |x| x.capitalize }.join end attr_accessor :default_format -- cgit From ba67cc8a39012a9c28a509d797f46decfdeb32d5 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Mon, 21 Mar 2011 15:04:42 -0700 Subject: (#6785) Internal consistency for `--terminus`. Paired-With: Richard Crowley --- lib/puppet/application/indirection_base.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index 764098925..2d30aa707 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -3,10 +3,10 @@ require 'puppet/interface' class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase option("--terminus TERMINUS") do |arg| - @from = arg + @terminus = arg end - attr_accessor :from, :indirection + attr_accessor :terminus, :indirection def setup super @@ -14,7 +14,7 @@ class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase if interface.respond_to?(:indirection) raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection - interface.set_terminus(from) if from + interface.set_terminus(terminus) if terminus end end end -- cgit From 072becf6b51cb359d18b30d7eb01391f641dd840 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 21 Mar 2011 14:31:18 -0700 Subject: (#6806) Improve error checking and reporting for interface naming. We didn't do enough input checking and sanitization, and missed some edge-cases for naming interfaces. This adds testing, and cleans up some edge cases to handle things better. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index dfd75ef58..d169067ea 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -55,12 +55,12 @@ class Puppet::Interface remove_const(constantize(name)) rescue nil end - def self.unify_name(name) - name.to_s.downcase.to_sym - end - def self.constantize(name) - name.to_s.split(/\W|_/).map { |x| x.capitalize }.join + unless name.to_s =~ /^[-_a-z]+$/i then + raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid interface name" + end + + name.to_s.split(/[-_]/).map { |x| x.capitalize }.join end attr_accessor :default_format -- cgit From 84ba21e66660a67e20c1194780138317e6a39d49 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 21 Mar 2011 15:51:21 -0700 Subject: Fixing a load-order issue in Puppet::Interface The application classes were having issues loading the Interface class in certain circumstances because of load order. This just pushes the loading as late as possible. Signed-off-by: Luke Kanies --- lib/puppet/application/indirection_base.rb | 1 - lib/puppet/application/interface_base.rb | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index 2d30aa707..7d1c851cf 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -1,5 +1,4 @@ require 'puppet/application/interface_base' -require 'puppet/interface' class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase option("--terminus TERMINUS") do |arg| diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 1f18b086c..f2c147f1f 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -1,5 +1,4 @@ require 'puppet/application' -require 'puppet/interface' class Puppet::Application::InterfaceBase < Puppet::Application should_parse_config @@ -41,6 +40,11 @@ class Puppet::Application::InterfaceBase < Puppet::Application @exit_code || 0 end + def initialize(*args) + require 'puppet/interface' + super + end + def main # Call the method associated with the provided action (e.g., 'find'). if result = interface.send(verb, *arguments) -- cgit From 63f33d078429a9f589474f9c0778b21d82f38682 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Mon, 21 Mar 2011 14:21:53 -0700 Subject: (#6805) Add a "configurer" application This application is similar in basic functionality to the "agent" application, but implemented in terms of interfaces. It currently will retrieve facts, retrieve a catalog, apply the catalog, and submit a report. Options such as noop and daemonize are still to come. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/configurer.rb | 23 +++++++++++++++++++++++ lib/puppet/interface.rb | 2 ++ lib/puppet/interface/catalog.rb | 32 ++++++++++++++++++++++++++++++++ lib/puppet/interface/configurer.rb | 13 +++++++++++++ lib/puppet/interface/report.rb | 9 +++++++++ 5 files changed, 79 insertions(+) create mode 100644 lib/puppet/application/configurer.rb create mode 100644 lib/puppet/interface/configurer.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb new file mode 100644 index 000000000..70d24814e --- /dev/null +++ b/lib/puppet/application/configurer.rb @@ -0,0 +1,23 @@ +require 'puppet/application' +require 'puppet/interface' + +class Puppet::Application::Configurer < Puppet::Application + should_parse_config + run_mode :agent + + option("--debug","-d") + option("--verbose","-v") + + def setup + if options[:debug] or options[:verbose] + Puppet::Util::Log.level = options[:debug] ? :debug : :info + end + + Puppet::Util::Log.newdestination(:console) + end + + def run_command + report = Puppet::Interface::Configurer.synchronize(Puppet[:certname]) + Puppet::Interface::Report.submit(report) + end +end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index d169067ea..13b1a811b 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -7,6 +7,8 @@ class Puppet::Interface include Puppet::Interface::ActionManager extend Puppet::Interface::ActionManager + include Puppet::Util + # This is just so we can search for actions. We only use its # list of directories to search. # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb index b2ed08f92..f99d0881a 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/catalog.rb @@ -1,4 +1,36 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.new(:catalog) do + action(:apply) 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 + + action(:download) 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::Interface::Catalog.find(certname, facts_to_upload) + end + catalog = catalog.to_ral + catalog.finalize + catalog.retrieval_duration = retrieval_duration + catalog.write_class_file + catalog + end end diff --git a/lib/puppet/interface/configurer.rb b/lib/puppet/interface/configurer.rb new file mode 100644 index 000000000..42e950fa3 --- /dev/null +++ b/lib/puppet/interface/configurer.rb @@ -0,0 +1,13 @@ +require 'puppet/interface' + +Puppet::Interface.new(:configurer) do + action(:synchronize) do |certname| + facts = Puppet::Interface::Facts.find(certname) + + catalog = Puppet::Interface::Catalog.download(certname, facts) + + report = Puppet::Interface::Catalog.apply(catalog) + + report + end +end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb index e7b916527..4923a4b67 100644 --- a/lib/puppet/interface/report.rb +++ b/lib/puppet/interface/report.rb @@ -1,4 +1,13 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.new(:report) do + action(:submit) 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 -- cgit From c2627a3229577685a5baef1796f7f5b525fed667 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Mon, 21 Mar 2011 16:53:49 -0700 Subject: (Maint.) Remove Puppet::Interface#unload_interface Reviewed-By: Nick Lewis --- lib/puppet/interface.rb | 4 ---- 1 file changed, 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 13b1a811b..38841d948 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -53,10 +53,6 @@ class Puppet::Interface const_set(constantize(name), instance) end - def self.unload_interface(name) - remove_const(constantize(name)) rescue nil - end - def self.constantize(name) unless name.to_s =~ /^[-_a-z]+$/i then raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid interface name" -- cgit From a58bf959ec49c033e0498916a09e77e303c5792e Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Tue, 22 Mar 2011 13:19:25 -0700 Subject: (#6786) Change interface storage and access. Ruby's namespace mechanism introduced a number of problems, including incorrect name resolution for common and simple cases. Given that, we've refactored back to class-level data structures with accessor methods available. The current method names are unlikely to be the final UI. Reviewed-By: Daniel Pittman --- lib/puppet/application/configurer.rb | 4 ++-- lib/puppet/application/interface_base.rb | 3 ++- lib/puppet/interface.rb | 30 +++++++++++++++++------------- lib/puppet/interface/catalog.rb | 2 +- lib/puppet/interface/catalog/select.rb | 12 +++++++----- lib/puppet/interface/configurer.rb | 9 +++------ 6 files changed, 32 insertions(+), 28 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index 70d24814e..378364430 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -17,7 +17,7 @@ class Puppet::Application::Configurer < Puppet::Application end def run_command - report = Puppet::Interface::Configurer.synchronize(Puppet[:certname]) - Puppet::Interface::Report.submit(report) + report = Puppet::Interface.interface(:configurer).synchronize(Puppet[:certname]) + Puppet::Interface.interface(:report).submit(report) end end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index f2c147f1f..654674df5 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -75,9 +75,10 @@ class Puppet::Application::InterfaceBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - unless @interface = Puppet::Interface.const_get(@type) + unless Puppet::Interface.interface?(@type) raise "Could not find interface '#{@type}'" end + @interface = Puppet::Interface.interface(@type) @format ||= @interface.default_format # We copy all of the app options to the interface. diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 38841d948..0ec0f803f 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -9,6 +9,8 @@ class Puppet::Interface include Puppet::Util + @interfaces = {} + # This is just so we can search for actions. We only use its # list of directories to search. # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb @@ -34,31 +36,33 @@ class Puppet::Interface end end end - Puppet::Interface.constants.map { |c| c.to_s.downcase } + return @interfaces.keys end - def self.const_missing(name) - require "puppet/interface/#{name.to_s.downcase}" - const_get(name) if const_defined?(name) + def self.interface?(name) + name = underscorize(name) + require "puppet/interface/#{name}" unless @interfaces.has_key? name + return @interfaces.has_key? name rescue LoadError - nil + return false end - def self.const_get(name) - name = constantize(name) - super(name) + def self.interface(name, &blk) + interface = interface?(name) ? @interfaces[underscorize(name)] : new(name) + interface.instance_eval(&blk) if block_given? + return interface end def self.register_interface(name, instance) - const_set(constantize(name), instance) + @interfaces[underscorize(name)] = instance end - def self.constantize(name) + def self.underscorize(name) unless name.to_s =~ /^[-_a-z]+$/i then raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid interface name" end - name.to_s.split(/[-_]/).map { |x| x.capitalize }.join + name.to_s.downcase.split(/[-_]/).join('_').to_sym end attr_accessor :default_format @@ -75,7 +79,7 @@ class Puppet::Interface attr_accessor :type, :verb, :name, :arguments, :options def initialize(name, options = {}, &block) - @name = name + @name = self.class.underscorize(name) @default_format = :pson options.each { |opt, val| send(opt.to_s + "=", val) } @@ -118,6 +122,6 @@ class Puppet::Interface end def to_s - name.to_s + "Puppet::Interface(#{name})" end end diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb index f99d0881a..34a1d8119 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/catalog.rb @@ -25,7 +25,7 @@ Puppet::Interface::Indirector.new(:catalog) do facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} catalog = nil retrieval_duration = thinmark do - catalog = Puppet::Interface::Catalog.find(certname, facts_to_upload) + catalog = Puppet::Interface.interface(:catalog).find(certname, facts_to_upload) end catalog = catalog.to_ral catalog.finalize diff --git a/lib/puppet/interface/catalog/select.rb b/lib/puppet/interface/catalog/select.rb index 4bb49315c..082d93c34 100644 --- a/lib/puppet/interface/catalog/select.rb +++ b/lib/puppet/interface/catalog/select.rb @@ -1,8 +1,10 @@ # Select and show a list of resources of a given type. -Puppet::Interface::Catalog.action :select do |*args| - host = args.shift - type = args.shift - catalog = Puppet::Resource::Catalog.indirection.find(host) +Puppet::Interface.interface(:catalog) do + action :select do |*args| + host = args.shift + type = args.shift + catalog = Puppet::Resource::Catalog.indirection.find(host) - catalog.resources.reject { |res| res.type != type }.each { |res| puts res } + catalog.resources.reject { |res| res.type != type }.each { |res| puts res } + end end diff --git a/lib/puppet/interface/configurer.rb b/lib/puppet/interface/configurer.rb index 42e950fa3..c1a28b2e7 100644 --- a/lib/puppet/interface/configurer.rb +++ b/lib/puppet/interface/configurer.rb @@ -2,12 +2,9 @@ require 'puppet/interface' Puppet::Interface.new(:configurer) do action(:synchronize) do |certname| - facts = Puppet::Interface::Facts.find(certname) - - catalog = Puppet::Interface::Catalog.download(certname, facts) - - report = Puppet::Interface::Catalog.apply(catalog) - + facts = Puppet::Interface.interface(:facts).find(certname) + catalog = Puppet::Interface.interface(:catalog).download(certname, facts) + report = Puppet::Interface.interface(:catalog).apply(catalog) report end end -- cgit From e3d24865c89bccd0221f3d6d475d350f577ed3fb Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Tue, 22 Mar 2011 12:54:52 -0700 Subject: (#6814) Create a dedicated Action class This class will represents an action, and allows us to store metadata for an action, and programmatically introspect and invoke them. A helper class ActionBuilder represents the DSL for defining an action. Also defined an "invoke" DSL method to handle the functionality of defining the method for an action. Reviewed-By: Daniel Pittman --- lib/puppet/interface/action.rb | 16 +++++++++++ lib/puppet/interface/action_builder.rb | 29 +++++++++++++++++++ lib/puppet/interface/action_manager.rb | 26 ++++++++++------- lib/puppet/interface/catalog.rb | 52 ++++++++++++++++++---------------- lib/puppet/interface/catalog/select.rb | 12 ++++---- lib/puppet/interface/config.rb | 6 ++-- lib/puppet/interface/configurer.rb | 12 ++++---- lib/puppet/interface/facts.rb | 16 ++++++----- lib/puppet/interface/indirector.rb | 28 +++++++++--------- lib/puppet/interface/report.rb | 16 ++++++----- 10 files changed, 138 insertions(+), 75 deletions(-) create mode 100644 lib/puppet/interface/action.rb create mode 100644 lib/puppet/interface/action_builder.rb (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb new file mode 100644 index 000000000..e4c2a4666 --- /dev/null +++ b/lib/puppet/interface/action.rb @@ -0,0 +1,16 @@ +require 'puppet/interface' + +class Puppet::Interface::Action + attr_reader :name + + def initialize(interface, name) + name = name.to_s + raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/ + @interface = interface + @name = name + end + + def invoke(*args, &block) + @interface.method(name).call(*args,&block) + end +end diff --git a/lib/puppet/interface/action_builder.rb b/lib/puppet/interface/action_builder.rb new file mode 100644 index 000000000..777fcaf85 --- /dev/null +++ b/lib/puppet/interface/action_builder.rb @@ -0,0 +1,29 @@ +require 'puppet/interface' + +class Puppet::Interface::ActionBuilder + attr_reader :action + + def self.build(interface, name, &block) + name = name.to_s + raise "Action '#{name}' must specify a block" unless block + builder = new(interface, name, &block) + builder.action + end + + def initialize(interface, name, &block) + @interface = interface + @action = Puppet::Interface::Action.new(interface, name) + instance_eval(&block) + end + + # Ideally the method we're defining here would be added to the action, and a + # method on the interface would defer to it + def invoke(&block) + raise "Invoke called on an ActionBuilder with no corresponding Action" unless @action + if @interface.is_a?(Class) + @interface.define_method(@action.name, &block) + else + @interface.meta_def(@action.name, &block) + end + end +end diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb index 27a982929..8629b4cbe 100644 --- a/lib/puppet/interface/action_manager.rb +++ b/lib/puppet/interface/action_manager.rb @@ -1,32 +1,36 @@ +require 'puppet/interface/action_builder' + module Puppet::Interface::ActionManager # Declare that this app can take a specific action, and provide # the code to do so. def action(name, &block) - @actions ||= [] + @actions ||= {} name = name.to_s.downcase.to_sym + raise "Action #{name} already defined for #{self}" if action?(name) - @actions << name - if self.is_a?(Class) - define_method(name, &block) - else - meta_def(name, &block) - end + action = Puppet::Interface::ActionBuilder.build(self, name, &block) + + @actions[name] = action end def actions - @actions ||= [] - result = @actions.dup + @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 { |a,b| a.to_s <=> b.to_s } + result.sort + end + + def get_action(name) + @actions[name].dup end def action?(name) - actions.include?(name.to_sym) + actions.include?(name) end end diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb index f99d0881a..6c235e2d2 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/catalog.rb @@ -1,36 +1,40 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.new(:catalog) do - action(:apply) do |catalog| - report = Puppet::Transaction::Report.new("apply") - report.configuration_version = catalog.version + action(:apply) do + invoke do |catalog| + report = Puppet::Transaction::Report.new("apply") + report.configuration_version = catalog.version - Puppet::Util::Log.newdestination(report) + Puppet::Util::Log.newdestination(report) - begin - benchmark(:notice, "Finished catalog run") do - catalog.apply(:report => 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 - rescue => detail - puts detail.backtrace if Puppet[:trace] - Puppet.err "Failed to apply catalog: #{detail}" - end - report.finalize_report - report + report.finalize_report + report + end end - action(:download) 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::Interface::Catalog.find(certname, facts_to_upload) + 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::Interface::Catalog.find(certname, facts_to_upload) + end + catalog = catalog.to_ral + catalog.finalize + catalog.retrieval_duration = retrieval_duration + catalog.write_class_file + catalog end - catalog = catalog.to_ral - catalog.finalize - catalog.retrieval_duration = retrieval_duration - catalog.write_class_file - catalog end end diff --git a/lib/puppet/interface/catalog/select.rb b/lib/puppet/interface/catalog/select.rb index 4bb49315c..349d9c5e0 100644 --- a/lib/puppet/interface/catalog/select.rb +++ b/lib/puppet/interface/catalog/select.rb @@ -1,8 +1,10 @@ # Select and show a list of resources of a given type. -Puppet::Interface::Catalog.action :select do |*args| - host = args.shift - type = args.shift - catalog = Puppet::Resource::Catalog.indirection.find(host) +Puppet::Interface::Catalog.action :select do + invoke do |*args| + host = args.shift + type = args.shift + catalog = Puppet::Resource::Catalog.indirection.find(host) - catalog.resources.reject { |res| res.type != type }.each { |res| puts res } + catalog.resources.reject { |res| res.type != type }.each { |res| puts res } + end end diff --git a/lib/puppet/interface/config.rb b/lib/puppet/interface/config.rb index 501099a64..0aecc263f 100644 --- a/lib/puppet/interface/config.rb +++ b/lib/puppet/interface/config.rb @@ -1,10 +1,10 @@ require 'puppet/interface' Puppet::Interface.new(:config) do - action(:print) do |*args| - if name + action(:print) do + invoke do |*args| Puppet.settings[:configprint] = args.join(",") + Puppet.settings.print_config_options end - Puppet.settings.print_config_options end end diff --git a/lib/puppet/interface/configurer.rb b/lib/puppet/interface/configurer.rb index 42e950fa3..36953baac 100644 --- a/lib/puppet/interface/configurer.rb +++ b/lib/puppet/interface/configurer.rb @@ -1,13 +1,15 @@ require 'puppet/interface' Puppet::Interface.new(:configurer) do - action(:synchronize) do |certname| - facts = Puppet::Interface::Facts.find(certname) + action(:synchronize) do + invoke do |certname| + facts = Puppet::Interface::Facts.find(certname) - catalog = Puppet::Interface::Catalog.download(certname, facts) + catalog = Puppet::Interface::Catalog.download(certname, facts) - report = Puppet::Interface::Catalog.apply(catalog) + report = Puppet::Interface::Catalog.apply(catalog) - report + report + end end end diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb index 326274545..8843d297d 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/facts.rb @@ -5,12 +5,14 @@ Puppet::Interface::Indirector.new(:facts) do set_default_format :yaml # Upload our facts to the server - action(:upload) 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 + 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/interface/indirector.rb b/lib/puppet/interface/indirector.rb index 9c26cc37a..485af4779 100644 --- a/lib/puppet/interface/indirector.rb +++ b/lib/puppet/interface/indirector.rb @@ -10,28 +10,30 @@ class Puppet::Interface::Indirector < Puppet::Interface Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort end - action :destroy do |*args| - call_indirection_method(:destroy, *args) + action :destroy do + invoke { |*args| call_indirection_method(:destroy, *args) } end - action :find do |*args| - call_indirection_method(:find, *args) + action :find do + invoke { |*args| call_indirection_method(:find, *args) } end - action :save do |*args| - call_indirection_method(:save, *args) + action :save do + invoke { |*args| call_indirection_method(:save, *args) } end - action :search do |*args| - call_indirection_method(:search, *args) + action :search do + invoke { |*args| call_indirection_method(:search, *args) } end # Print the configuration for the current terminus class - action :info 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}'" + 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 diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb index 4923a4b67..e785ae22d 100644 --- a/lib/puppet/interface/report.rb +++ b/lib/puppet/interface/report.rb @@ -1,13 +1,15 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.new(:report) do - action(:submit) 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}" + 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 -- cgit From 50ba62d68ef3a6a81e00581dd7d74f6387bd73fc Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Tue, 22 Mar 2011 14:29:52 -0700 Subject: maint: Make args to Catalog.select explicit No other args are used, so passing *args and shifting is unnecessary. --- lib/puppet/interface/catalog/select.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/catalog/select.rb b/lib/puppet/interface/catalog/select.rb index 3f724d360..32d9b7c45 100644 --- a/lib/puppet/interface/catalog/select.rb +++ b/lib/puppet/interface/catalog/select.rb @@ -1,9 +1,7 @@ # Select and show a list of resources of a given type. Puppet::Interface.interface(:catalog) do action :select do - invoke do |*args| - host = args.shift - type = args.shift + invoke do |host,type| catalog = Puppet::Resource::Catalog.indirection.find(host) catalog.resources.reject { |res| res.type != type }.each { |res| puts res } -- cgit From ee66f36aa3c730819bd81d8352914628a811e516 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Tue, 22 Mar 2011 14:33:59 -0700 Subject: (#6814) Add missing require for specs --- lib/puppet/interface/action_builder.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action_builder.rb b/lib/puppet/interface/action_builder.rb index 777fcaf85..e76fb1c6e 100644 --- a/lib/puppet/interface/action_builder.rb +++ b/lib/puppet/interface/action_builder.rb @@ -1,4 +1,5 @@ require 'puppet/interface' +require 'puppet/interface/action' class Puppet::Interface::ActionBuilder attr_reader :action -- cgit From 847ac203f9c0b5fce299e87a63b0de5d3ef416f6 Mon Sep 17 00:00:00 2001 From: Nick Lewis Date: Tue, 22 Mar 2011 16:44:01 -0700 Subject: maint: Implement an InterfaceCollection class to manage interfaces Having an instance variable on class Interface is insufficient for Interface::Indirector. This also changes the semantics of "Interface.interface" to handle registration and loading actions, and for "Interface.new" to only instantiate an Interface. Thus, consumers of the API should typically use "Interface.interface", unless they have reasons to not want an interface automatically registered. Paired-With: Pieter van de Bruggen --- lib/puppet/application/interface_base.rb | 6 +- lib/puppet/interface.rb | 74 ++++++---------------- lib/puppet/interface/catalog.rb | 2 +- lib/puppet/interface/certificate.rb | 2 +- lib/puppet/interface/certificate_request.rb | 2 +- .../interface/certificate_revocation_list.rb | 2 +- lib/puppet/interface/config.rb | 2 +- lib/puppet/interface/configurer.rb | 2 +- lib/puppet/interface/facts.rb | 2 +- lib/puppet/interface/file.rb | 2 +- lib/puppet/interface/interface_collection.rb | 50 +++++++++++++++ lib/puppet/interface/key.rb | 2 +- lib/puppet/interface/node.rb | 2 +- lib/puppet/interface/report.rb | 2 +- lib/puppet/interface/resource.rb | 2 +- lib/puppet/interface/resource_type.rb | 2 +- lib/puppet/interface/status.rb | 2 +- 17 files changed, 84 insertions(+), 74 deletions(-) create mode 100644 lib/puppet/interface/interface_collection.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 654674df5..7a31ce323 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -1,4 +1,5 @@ require 'puppet/application' +require 'puppet/interface' class Puppet::Application::InterfaceBase < Puppet::Application should_parse_config @@ -40,11 +41,6 @@ class Puppet::Application::InterfaceBase < Puppet::Application @exit_code || 0 end - def initialize(*args) - require 'puppet/interface' - super - end - def main # Call the method associated with the provided action (e.g., 'find'). if result = interface.send(verb, *arguments) diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 0ec0f803f..f82d6235c 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -3,6 +3,7 @@ require 'puppet/util/autoload' class Puppet::Interface require 'puppet/interface/action_manager' + require 'puppet/interface/interface_collection' include Puppet::Interface::ActionManager extend Puppet::Interface::ActionManager @@ -19,50 +20,27 @@ class Puppet::Interface end def self.interfaces - unless @loaded - @loaded = true - $LOAD_PATH.each do |dir| - next unless FileTest.directory?(dir) - Dir.chdir(dir) do - Dir.glob("puppet/interface/*.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 @interfaces.keys + Puppet::Interface::InterfaceCollection.interfaces end def self.interface?(name) - name = underscorize(name) - require "puppet/interface/#{name}" unless @interfaces.has_key? name - return @interfaces.has_key? name - rescue LoadError - return false - end - - def self.interface(name, &blk) - interface = interface?(name) ? @interfaces[underscorize(name)] : new(name) - interface.instance_eval(&blk) if block_given? - return interface + Puppet::Interface::InterfaceCollection.interface?(name) end - def self.register_interface(name, instance) - @interfaces[underscorize(name)] = instance + def self.register(instance) + Puppet::Interface::InterfaceCollection.register(instance) end - def self.underscorize(name) - unless name.to_s =~ /^[-_a-z]+$/i then - raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid interface name" + def self.interface(name, &blk) + if interface?(name) + interface = Puppet::Interface::InterfaceCollection[name] + interface.instance_eval(&blk) if blk + else + interface = new(name, &blk) + Puppet::Interface::InterfaceCollection.register(interface) + interface.load_actions end - - name.to_s.downcase.split(/[-_]/).join('_').to_sym + return interface end attr_accessor :default_format @@ -71,30 +49,16 @@ class Puppet::Interface self.default_format = format.to_sym end - # Return the interface name. - def name - @name || self.to_s.sub(/.+::/, '').downcase - end - - attr_accessor :type, :verb, :name, :arguments, :options + attr_accessor :type, :verb, :arguments, :options + attr_reader :name def initialize(name, options = {}, &block) - @name = self.class.underscorize(name) + @name = Puppet::Interface::InterfaceCollection.underscorize(name) @default_format = :pson options.each { |opt, val| send(opt.to_s + "=", val) } - # We have to register before loading actions, - # since the actions require the registration - # Use the full class name, so this works with - # subclasses. - Puppet::Interface.register_interface(name, self) - - load_actions - - if block_given? - instance_eval(&block) - end + instance_eval(&block) if block end # Try to find actions defined in other files. @@ -102,7 +66,7 @@ class Puppet::Interface path = "puppet/interface/#{name}" loaded = [] - self.class.autoloader.search_directories.each do |dir| + Puppet::Interface.autoloader.search_directories.each do |dir| fdir = ::File.join(dir, path) next unless FileTest.directory?(fdir) diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb index c0af53bac..defe32127 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/catalog.rb @@ -1,6 +1,6 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:catalog) do +Puppet::Interface::Indirector.interface(:catalog) do action(:apply) do invoke do |catalog| report = Puppet::Transaction::Report.new("apply") diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 52ba4e3b8..09da0a6c3 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:certificate) do +Puppet::Interface::Indirector.interface(:certificate) do end diff --git a/lib/puppet/interface/certificate_request.rb b/lib/puppet/interface/certificate_request.rb index 77b485f8e..b85c15fef 100644 --- a/lib/puppet/interface/certificate_request.rb +++ b/lib/puppet/interface/certificate_request.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:certificate_request) do +Puppet::Interface::Indirector.interface(:certificate_request) do end diff --git a/lib/puppet/interface/certificate_revocation_list.rb b/lib/puppet/interface/certificate_revocation_list.rb index ee1e6a8c4..956fb6494 100644 --- a/lib/puppet/interface/certificate_revocation_list.rb +++ b/lib/puppet/interface/certificate_revocation_list.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:certificate_revocation_list) do +Puppet::Interface::Indirector.interface(:certificate_revocation_list) do end diff --git a/lib/puppet/interface/config.rb b/lib/puppet/interface/config.rb index 0aecc263f..79d2ee7c1 100644 --- a/lib/puppet/interface/config.rb +++ b/lib/puppet/interface/config.rb @@ -1,6 +1,6 @@ require 'puppet/interface' -Puppet::Interface.new(:config) do +Puppet::Interface.interface(:config) do action(:print) do invoke do |*args| Puppet.settings[:configprint] = args.join(",") diff --git a/lib/puppet/interface/configurer.rb b/lib/puppet/interface/configurer.rb index 2fbde27f1..0d21c4d72 100644 --- a/lib/puppet/interface/configurer.rb +++ b/lib/puppet/interface/configurer.rb @@ -1,6 +1,6 @@ require 'puppet/interface' -Puppet::Interface.new(:configurer) do +Puppet::Interface.interface(:configurer) do action(:synchronize) do invoke do |certname| facts = Puppet::Interface.interface(:facts).find(certname) diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb index 8843d297d..97e22714b 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/facts.rb @@ -1,7 +1,7 @@ require 'puppet/interface/indirector' require 'puppet/node/facts' -Puppet::Interface::Indirector.new(:facts) do +Puppet::Interface::Indirector.interface(:facts) do set_default_format :yaml # Upload our facts to the server diff --git a/lib/puppet/interface/file.rb b/lib/puppet/interface/file.rb index 859f92ca4..f38af2b92 100644 --- a/lib/puppet/interface/file.rb +++ b/lib/puppet/interface/file.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:file) do +Puppet::Interface::Indirector.interface(:file) do set_indirection_name :file_bucket_file end diff --git a/lib/puppet/interface/interface_collection.rb b/lib/puppet/interface/interface_collection.rb new file mode 100644 index 000000000..47ed702aa --- /dev/null +++ b/lib/puppet/interface/interface_collection.rb @@ -0,0 +1,50 @@ +require 'puppet/interface' + +module Puppet::Interface::InterfaceCollection + @interfaces = {} + + def self.interfaces + unless @loaded + @loaded = true + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + Dir.chdir(dir) do + Dir.glob("puppet/interface/*.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 @interfaces.keys + end + + def self.[](name) + @interfaces[underscorize(name)] if interface?(name) + end + + def self.interface?(name) + name = underscorize(name) + require "puppet/interface/#{name}" unless @interfaces.has_key? name + return @interfaces.has_key? name + rescue LoadError + return false + end + + def self.register(interface) + @interfaces[underscorize(interface.name)] = interface + end + + def self.underscorize(name) + unless name.to_s =~ /^[-_a-z]+$/i then + raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid interface name" + end + + name.to_s.downcase.split(/[-_]/).join('_').to_sym + end +end diff --git a/lib/puppet/interface/key.rb b/lib/puppet/interface/key.rb index 9343891d0..57519883d 100644 --- a/lib/puppet/interface/key.rb +++ b/lib/puppet/interface/key.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:key) do +Puppet::Interface::Indirector.interface(:key) do end diff --git a/lib/puppet/interface/node.rb b/lib/puppet/interface/node.rb index 0a0f57a1e..8940fd7dd 100644 --- a/lib/puppet/interface/node.rb +++ b/lib/puppet/interface/node.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:node) do +Puppet::Interface::Indirector.interface(:node) do set_default_format :yaml end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb index e785ae22d..56a58f6aa 100644 --- a/lib/puppet/interface/report.rb +++ b/lib/puppet/interface/report.rb @@ -1,6 +1,6 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:report) do +Puppet::Interface::Indirector.interface(:report) do action(:submit) do invoke do |report| begin diff --git a/lib/puppet/interface/resource.rb b/lib/puppet/interface/resource.rb index 65f2dec7a..130f40fce 100644 --- a/lib/puppet/interface/resource.rb +++ b/lib/puppet/interface/resource.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:resource) do +Puppet::Interface::Indirector.interface(:resource) do end diff --git a/lib/puppet/interface/resource_type.rb b/lib/puppet/interface/resource_type.rb index bf16652a8..70bf3b95a 100644 --- a/lib/puppet/interface/resource_type.rb +++ b/lib/puppet/interface/resource_type.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:resource_type) do +Puppet::Interface::Indirector.interface(:resource_type) do end diff --git a/lib/puppet/interface/status.rb b/lib/puppet/interface/status.rb index 1a1d349d1..432d1ce54 100644 --- a/lib/puppet/interface/status.rb +++ b/lib/puppet/interface/status.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.new(:status) do +Puppet::Interface::Indirector.interface(:status) do end -- cgit From 5d7715b0c56c6f06d916126e8470d7edb66d7687 Mon Sep 17 00:00:00 2001 From: Richard Crowley Date: Tue, 22 Mar 2011 23:46:21 +0000 Subject: Factoring cert status app back into certificate. --- lib/puppet/application/certificate.rb | 13 +++++++++++++ lib/puppet/interface/certificate.rb | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb index 4a2b3ef70..edb4eefd3 100644 --- a/lib/puppet/application/certificate.rb +++ b/lib/puppet/application/certificate.rb @@ -1,4 +1,17 @@ require 'puppet/application/indirection_base' class Puppet::Application::Certificate < Puppet::Application::IndirectionBase + + # Luke used to call this --ca but that's taken by the global boolean --ca. + # Since these options map CA terminology to indirector terminology, it's + # now called --ca-location. + option "--ca-location CA_LOCATION" do |arg| + handle_terminus({ + :local => :file, + :remote => :rest, + :only => :file, + :none => nil, + }[arg.to_sym]) + end + end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 09da0a6c3..c2101d926 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,4 +1,21 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.interface(:certificate) do + + action :sign do |name| + unless indirection.terminus + raise ArgumentError, "You must have a CA specified; use --ca-location to specify the location (remote, local, only)" + end + + location = Puppet::SSL::Host.ca_location + if location == :local && !Puppet::SSL::CertificateAuthority.ca? + Puppet::Application[:certificate].class.run_mode("master") + set_run_mode Puppet::Application[:certificate].class.run_mode + end + + Puppet::SSL::CertificateStatus.indirection.save( + Puppet::SSL::CertificateStatus.new(name)) + + end + end -- cgit From 562bd0f10be966bef725896af9ec3cdc30771ac6 Mon Sep 17 00:00:00 2001 From: Richard Crowley Date: Wed, 23 Mar 2011 00:14:59 +0000 Subject: Use the new name for the terminus. --- lib/puppet/application/certificate.rb | 7 +------ lib/puppet/interface/certificate.rb | 3 +-- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb index edb4eefd3..48736fc84 100644 --- a/lib/puppet/application/certificate.rb +++ b/lib/puppet/application/certificate.rb @@ -6,12 +6,7 @@ class Puppet::Application::Certificate < Puppet::Application::IndirectionBase # Since these options map CA terminology to indirector terminology, it's # now called --ca-location. option "--ca-location CA_LOCATION" do |arg| - handle_terminus({ - :local => :file, - :remote => :rest, - :only => :file, - :none => nil, - }[arg.to_sym]) + Puppet::SSL::Host.ca_location = arg.to_sym end end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index c2101d926..32415ea9d 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -13,8 +13,7 @@ Puppet::Interface::Indirector.interface(:certificate) do set_run_mode Puppet::Application[:certificate].class.run_mode end - Puppet::SSL::CertificateStatus.indirection.save( - Puppet::SSL::CertificateStatus.new(name)) + Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) end -- cgit From 562ae5fb9d78b1a6d46e79bb41d8498f29246f41 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Mar 2011 19:10:35 -0700 Subject: WIP - all tests fail Signed-off-by: Luke Kanies --- lib/puppet/interface/action_manager.rb | 2 +- lib/puppet/interface/certificate.rb | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb index 8629b4cbe..0db82d612 100644 --- a/lib/puppet/interface/action_manager.rb +++ b/lib/puppet/interface/action_manager.rb @@ -31,6 +31,6 @@ module Puppet::Interface::ActionManager end def action?(name) - actions.include?(name) + actions.include?(name.to_sym) end end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 32415ea9d..9b9496977 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,20 +1,20 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.interface(:certificate) do - action :sign do |name| - unless indirection.terminus - raise ArgumentError, "You must have a CA specified; use --ca-location to specify the location (remote, local, only)" - end + invoke do |name| + unless Puppet::SSL::Host.ca_location + raise ArgumentError, "You must have a CA location specified; use --ca-location to specify the location (remote, local, only)" + end - location = Puppet::SSL::Host.ca_location - if location == :local && !Puppet::SSL::CertificateAuthority.ca? - Puppet::Application[:certificate].class.run_mode("master") - set_run_mode Puppet::Application[:certificate].class.run_mode - end + location = Puppet::SSL::Host.ca_location + if location == :local && !Puppet::SSL::CertificateAuthority.ca? + Puppet::Application[:certificate].class.run_mode("master") + set_run_mode Puppet::Application[:certificate].class.run_mode + end - Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) + Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) + end end - end -- cgit From a1ce253d5896c6923165b5c00edef87003b16d7b Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 22 Mar 2011 19:17:57 -0700 Subject: Adding Certficate#generate Signed-off-by: Luke Kanies --- lib/puppet/interface/certificate.rb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 9b9496977..6ba043e8c 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,6 +1,15 @@ require 'puppet/interface/indirector' Puppet::Interface::Indirector.interface(:certificate) do + action :generate do + invoke do |name| + require 'puppet/ssl/host' + + host = Puppet::SSL::Host.new(name) + host.generate + end + end + action :sign do |name| invoke do |name| unless Puppet::SSL::Host.ca_location @@ -9,8 +18,9 @@ Puppet::Interface::Indirector.interface(:certificate) do location = Puppet::SSL::Host.ca_location if location == :local && !Puppet::SSL::CertificateAuthority.ca? - Puppet::Application[:certificate].class.run_mode("master") - set_run_mode Puppet::Application[:certificate].class.run_mode + app = Puppet::Application[:certificate] + app.class.run_mode("master") + app.set_run_mode Puppet::Application[:certificate].class.run_mode end Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) -- cgit From a7a9e125018c7a3fd0f0afc543f7aeaea1c19525 Mon Sep 17 00:00:00 2001 From: Richard Crowley Date: Wed, 23 Mar 2011 17:44:58 +0000 Subject: Alter generate action to work on CSRs only. --- lib/puppet/interface/certificate.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 6ba043e8c..4088a4557 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -1,12 +1,13 @@ require 'puppet/interface/indirector' +require 'puppet/ssl/host' Puppet::Interface::Indirector.interface(:certificate) do + action :generate do invoke do |name| - require 'puppet/ssl/host' - host = Puppet::SSL::Host.new(name) - host.generate + host.generate_certificate_request + host.certificate_request.class.indirection.save(host.certificate_request) end end -- cgit From 961c7163f336c0dd96f7f72122af9155e1a2260a Mon Sep 17 00:00:00 2001 From: Richard Crowley Date: Wed, 23 Mar 2011 17:45:46 +0000 Subject: Added list action. The common tasks of checking the --ca-location argument and becoming a CA process if necessary (that is, acting like a master) have been abstracted into the Application where they belong. --- lib/puppet/application/certificate.rb | 15 +++++++++++++++ lib/puppet/interface/certificate.rb | 22 ++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb index 48736fc84..f4b13ffe0 100644 --- a/lib/puppet/application/certificate.rb +++ b/lib/puppet/application/certificate.rb @@ -9,4 +9,19 @@ class Puppet::Application::Certificate < Puppet::Application::IndirectionBase Puppet::SSL::Host.ca_location = arg.to_sym end + def setup + + unless Puppet::SSL::Host.ca_location + raise ArgumentError, "You must have a CA location specified; use --ca-location to specify the location (remote, local, only)" + end + + location = Puppet::SSL::Host.ca_location + if location == :local && !Puppet::SSL::CertificateAuthority.ca? + self.class.run_mode("master") + self.set_run_mode self.class.run_mode + end + + super + end + end diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 4088a4557..5c06cdc29 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -11,21 +11,19 @@ Puppet::Interface::Indirector.interface(:certificate) do end end - action :sign do |name| - invoke do |name| - unless Puppet::SSL::Host.ca_location - raise ArgumentError, "You must have a CA location specified; use --ca-location to specify the location (remote, local, only)" - end - - location = Puppet::SSL::Host.ca_location - if location == :local && !Puppet::SSL::CertificateAuthority.ca? - app = Puppet::Application[:certificate] - app.class.run_mode("master") - app.set_run_mode Puppet::Application[:certificate].class.run_mode + action :list do + invoke do + Puppet::SSL::Host.indirection.search("*").each do |host| + puts host.inspect end + nil + end + end + action :sign do |name| + invoke do |name| Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) - end end + end -- cgit From 1187a0eb2550f04d9b6c3dcfdcacdfbb32de0e56 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Wed, 23 Mar 2011 13:59:44 -0700 Subject: (#6770) Add basic versioning for interfaces. Reviewed-By: Nick Lewis --- lib/puppet/application/configurer.rb | 4 +-- lib/puppet/application/interface.rb | 2 +- lib/puppet/application/interface_base.rb | 7 ++-- lib/puppet/interface.rb | 22 ++++++------ lib/puppet/interface/catalog.rb | 40 ---------------------- lib/puppet/interface/catalog/select.rb | 10 ------ lib/puppet/interface/certificate.rb | 4 --- lib/puppet/interface/certificate_request.rb | 4 --- .../interface/certificate_revocation_list.rb | 4 --- lib/puppet/interface/config.rb | 10 ------ lib/puppet/interface/configurer.rb | 12 ------- lib/puppet/interface/facts.rb | 18 ---------- lib/puppet/interface/file.rb | 5 --- lib/puppet/interface/interface_collection.rb | 16 +++++---- lib/puppet/interface/key.rb | 4 --- lib/puppet/interface/node.rb | 5 --- lib/puppet/interface/report.rb | 15 -------- lib/puppet/interface/resource.rb | 4 --- lib/puppet/interface/resource_type.rb | 4 --- lib/puppet/interface/status.rb | 4 --- lib/puppet/interface/v1/catalog.rb | 40 ++++++++++++++++++++++ lib/puppet/interface/v1/catalog/select.rb | 10 ++++++ lib/puppet/interface/v1/certificate.rb | 4 +++ lib/puppet/interface/v1/certificate_request.rb | 4 +++ .../interface/v1/certificate_revocation_list.rb | 4 +++ lib/puppet/interface/v1/config.rb | 10 ++++++ lib/puppet/interface/v1/configurer.rb | 12 +++++++ lib/puppet/interface/v1/facts.rb | 18 ++++++++++ lib/puppet/interface/v1/file.rb | 5 +++ lib/puppet/interface/v1/key.rb | 4 +++ lib/puppet/interface/v1/node.rb | 5 +++ lib/puppet/interface/v1/report.rb | 15 ++++++++ lib/puppet/interface/v1/resource.rb | 4 +++ lib/puppet/interface/v1/resource_type.rb | 4 +++ lib/puppet/interface/v1/status.rb | 4 +++ 35 files changed, 171 insertions(+), 166 deletions(-) delete mode 100644 lib/puppet/interface/catalog.rb delete mode 100644 lib/puppet/interface/catalog/select.rb delete mode 100644 lib/puppet/interface/certificate.rb delete mode 100644 lib/puppet/interface/certificate_request.rb delete mode 100644 lib/puppet/interface/certificate_revocation_list.rb delete mode 100644 lib/puppet/interface/config.rb delete mode 100644 lib/puppet/interface/configurer.rb delete mode 100644 lib/puppet/interface/facts.rb delete mode 100644 lib/puppet/interface/file.rb delete mode 100644 lib/puppet/interface/key.rb delete mode 100644 lib/puppet/interface/node.rb delete mode 100644 lib/puppet/interface/report.rb delete mode 100644 lib/puppet/interface/resource.rb delete mode 100644 lib/puppet/interface/resource_type.rb delete mode 100644 lib/puppet/interface/status.rb create mode 100644 lib/puppet/interface/v1/catalog.rb create mode 100644 lib/puppet/interface/v1/catalog/select.rb create mode 100644 lib/puppet/interface/v1/certificate.rb create mode 100644 lib/puppet/interface/v1/certificate_request.rb create mode 100644 lib/puppet/interface/v1/certificate_revocation_list.rb create mode 100644 lib/puppet/interface/v1/config.rb create mode 100644 lib/puppet/interface/v1/configurer.rb create mode 100644 lib/puppet/interface/v1/facts.rb create mode 100644 lib/puppet/interface/v1/file.rb create mode 100644 lib/puppet/interface/v1/key.rb create mode 100644 lib/puppet/interface/v1/node.rb create mode 100644 lib/puppet/interface/v1/report.rb create mode 100644 lib/puppet/interface/v1/resource.rb create mode 100644 lib/puppet/interface/v1/resource_type.rb create mode 100644 lib/puppet/interface/v1/status.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index 378364430..a76aaaf01 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -17,7 +17,7 @@ class Puppet::Application::Configurer < Puppet::Application end def run_command - report = Puppet::Interface.interface(:configurer).synchronize(Puppet[:certname]) - Puppet::Interface.interface(:report).submit(report) + report = Puppet::Interface.interface(:configurer, 1).synchronize(Puppet[:certname]) + Puppet::Interface.interface(:report, 1).submit(report) end end diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb index 10823e920..99c10dc16 100644 --- a/lib/puppet/application/interface.rb +++ b/lib/puppet/application/interface.rb @@ -81,7 +81,7 @@ class Puppet::Application::Interface < Puppet::Application end def actions(indirection) - return [] unless interface = Puppet::Interface.interface(indirection) + return [] unless interface = Puppet::Interface.interface(indirection, 1) interface.load_actions return interface.actions.sort { |a,b| a.to_s <=> b.to_s } end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 7a31ce323..78772833e 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -71,10 +71,11 @@ class Puppet::Application::InterfaceBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - unless Puppet::Interface.interface?(@type) - raise "Could not find interface '#{@type}'" + # TODO: These should be configurable versions. + unless Puppet::Interface.interface?(@type, 1) + raise "Could not find version #{1} of interface '#{@type}'" end - @interface = Puppet::Interface.interface(@type) + @interface = Puppet::Interface.interface(@type, 1) @format ||= @interface.default_format # We copy all of the app options to the interface. diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index f82d6235c..7f208f56c 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -10,8 +10,6 @@ class Puppet::Interface include Puppet::Util - @interfaces = {} - # This is just so we can search for actions. We only use its # list of directories to search. # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb @@ -23,20 +21,20 @@ class Puppet::Interface Puppet::Interface::InterfaceCollection.interfaces end - def self.interface?(name) - Puppet::Interface::InterfaceCollection.interface?(name) + def self.interface?(name, version) + Puppet::Interface::InterfaceCollection.interface?(name, version) end def self.register(instance) Puppet::Interface::InterfaceCollection.register(instance) end - def self.interface(name, &blk) - if interface?(name) - interface = Puppet::Interface::InterfaceCollection[name] + def self.interface(name, version, &blk) + if interface?(name, version) + interface = Puppet::Interface::InterfaceCollection[name, version] interface.instance_eval(&blk) if blk else - interface = new(name, &blk) + interface = self.new(name, :version => version, &blk) Puppet::Interface::InterfaceCollection.register(interface) interface.load_actions end @@ -49,10 +47,14 @@ class Puppet::Interface self.default_format = format.to_sym end - attr_accessor :type, :verb, :arguments, :options + attr_accessor :type, :verb, :version, :arguments, :options attr_reader :name def initialize(name, options = {}, &block) + unless options[:version] + raise ArgumentError, "Interface #{name} declared without version!" + end + @name = Puppet::Interface::InterfaceCollection.underscorize(name) @default_format = :pson @@ -86,6 +88,6 @@ class Puppet::Interface end def to_s - "Puppet::Interface(#{name})" + "Puppet::Interface(#{name}, :version => #{version.inspect})" end end diff --git a/lib/puppet/interface/catalog.rb b/lib/puppet/interface/catalog.rb deleted file mode 100644 index defe32127..000000000 --- a/lib/puppet/interface/catalog.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:catalog) 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::Interface.interface(:catalog).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/interface/catalog/select.rb b/lib/puppet/interface/catalog/select.rb deleted file mode 100644 index 32d9b7c45..000000000 --- a/lib/puppet/interface/catalog/select.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Select and show a list of resources of a given type. -Puppet::Interface.interface(:catalog) 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/interface/certificate.rb b/lib/puppet/interface/certificate.rb deleted file mode 100644 index 09da0a6c3..000000000 --- a/lib/puppet/interface/certificate.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:certificate) do -end diff --git a/lib/puppet/interface/certificate_request.rb b/lib/puppet/interface/certificate_request.rb deleted file mode 100644 index b85c15fef..000000000 --- a/lib/puppet/interface/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:certificate_request) do -end diff --git a/lib/puppet/interface/certificate_revocation_list.rb b/lib/puppet/interface/certificate_revocation_list.rb deleted file mode 100644 index 956fb6494..000000000 --- a/lib/puppet/interface/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:certificate_revocation_list) do -end diff --git a/lib/puppet/interface/config.rb b/lib/puppet/interface/config.rb deleted file mode 100644 index 79d2ee7c1..000000000 --- a/lib/puppet/interface/config.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'puppet/interface' - -Puppet::Interface.interface(:config) do - action(:print) do - invoke do |*args| - Puppet.settings[:configprint] = args.join(",") - Puppet.settings.print_config_options - end - end -end diff --git a/lib/puppet/interface/configurer.rb b/lib/puppet/interface/configurer.rb deleted file mode 100644 index 0d21c4d72..000000000 --- a/lib/puppet/interface/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/interface' - -Puppet::Interface.interface(:configurer) do - action(:synchronize) do - invoke do |certname| - facts = Puppet::Interface.interface(:facts).find(certname) - catalog = Puppet::Interface.interface(:catalog).download(certname, facts) - report = Puppet::Interface.interface(:catalog).apply(catalog) - report - end - end -end diff --git a/lib/puppet/interface/facts.rb b/lib/puppet/interface/facts.rb deleted file mode 100644 index 97e22714b..000000000 --- a/lib/puppet/interface/facts.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'puppet/interface/indirector' -require 'puppet/node/facts' - -Puppet::Interface::Indirector.interface(:facts) 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/interface/file.rb b/lib/puppet/interface/file.rb deleted file mode 100644 index f38af2b92..000000000 --- a/lib/puppet/interface/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:file) do - set_indirection_name :file_bucket_file -end diff --git a/lib/puppet/interface/interface_collection.rb b/lib/puppet/interface/interface_collection.rb index 47ed702aa..d626c4f72 100644 --- a/lib/puppet/interface/interface_collection.rb +++ b/lib/puppet/interface/interface_collection.rb @@ -1,7 +1,7 @@ require 'puppet/interface' module Puppet::Interface::InterfaceCollection - @interfaces = {} + @interfaces = Hash.new { |hash, key| hash[key] = {} } def self.interfaces unless @loaded @@ -24,20 +24,22 @@ module Puppet::Interface::InterfaceCollection return @interfaces.keys end - def self.[](name) - @interfaces[underscorize(name)] if interface?(name) + def self.[](name, version) + @interfaces[underscorize(name)][version] if interface?(name, version) end - def self.interface?(name) + def self.interface?(name, version) name = underscorize(name) - require "puppet/interface/#{name}" unless @interfaces.has_key? name - return @interfaces.has_key? name + unless @interfaces.has_key?(name) && @interfaces[name].has_key?(version) + require "puppet/interface/v#{version}/#{name}" + end + return @interfaces.has_key?(name) && @interfaces[name].has_key?(version) rescue LoadError return false end def self.register(interface) - @interfaces[underscorize(interface.name)] = interface + @interfaces[underscorize(interface.name)][interface.version] = interface end def self.underscorize(name) diff --git a/lib/puppet/interface/key.rb b/lib/puppet/interface/key.rb deleted file mode 100644 index 57519883d..000000000 --- a/lib/puppet/interface/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:key) do -end diff --git a/lib/puppet/interface/node.rb b/lib/puppet/interface/node.rb deleted file mode 100644 index 8940fd7dd..000000000 --- a/lib/puppet/interface/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:node) do - set_default_format :yaml -end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/report.rb deleted file mode 100644 index 56a58f6aa..000000000 --- a/lib/puppet/interface/report.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:report) 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/interface/resource.rb b/lib/puppet/interface/resource.rb deleted file mode 100644 index 130f40fce..000000000 --- a/lib/puppet/interface/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:resource) do -end diff --git a/lib/puppet/interface/resource_type.rb b/lib/puppet/interface/resource_type.rb deleted file mode 100644 index 70bf3b95a..000000000 --- a/lib/puppet/interface/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:resource_type) do -end diff --git a/lib/puppet/interface/status.rb b/lib/puppet/interface/status.rb deleted file mode 100644 index 432d1ce54..000000000 --- a/lib/puppet/interface/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:status) do -end diff --git a/lib/puppet/interface/v1/catalog.rb b/lib/puppet/interface/v1/catalog.rb new file mode 100644 index 000000000..2ba642039 --- /dev/null +++ b/lib/puppet/interface/v1/catalog.rb @@ -0,0 +1,40 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:catalog, 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::Interface.interface(:catalog, 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/interface/v1/catalog/select.rb b/lib/puppet/interface/v1/catalog/select.rb new file mode 100644 index 000000000..e37c841b5 --- /dev/null +++ b/lib/puppet/interface/v1/catalog/select.rb @@ -0,0 +1,10 @@ +# Select and show a list of resources of a given type. +Puppet::Interface.interface(:catalog, 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/interface/v1/certificate.rb b/lib/puppet/interface/v1/certificate.rb new file mode 100644 index 000000000..9a88c628a --- /dev/null +++ b/lib/puppet/interface/v1/certificate.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:certificate, 1) do +end diff --git a/lib/puppet/interface/v1/certificate_request.rb b/lib/puppet/interface/v1/certificate_request.rb new file mode 100644 index 000000000..868933e1f --- /dev/null +++ b/lib/puppet/interface/v1/certificate_request.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:certificate_request, 1) do +end diff --git a/lib/puppet/interface/v1/certificate_revocation_list.rb b/lib/puppet/interface/v1/certificate_revocation_list.rb new file mode 100644 index 000000000..09efd8c7a --- /dev/null +++ b/lib/puppet/interface/v1/certificate_revocation_list.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:certificate_revocation_list, 1) do +end diff --git a/lib/puppet/interface/v1/config.rb b/lib/puppet/interface/v1/config.rb new file mode 100644 index 000000000..a072e703c --- /dev/null +++ b/lib/puppet/interface/v1/config.rb @@ -0,0 +1,10 @@ +require 'puppet/interface' + +Puppet::Interface.interface(:config, 1) do + action(:print) do + invoke do |*args| + Puppet.settings[:configprint] = args.join(",") + Puppet.settings.print_config_options + end + end +end diff --git a/lib/puppet/interface/v1/configurer.rb b/lib/puppet/interface/v1/configurer.rb new file mode 100644 index 000000000..1deffce4e --- /dev/null +++ b/lib/puppet/interface/v1/configurer.rb @@ -0,0 +1,12 @@ +require 'puppet/interface' + +Puppet::Interface.interface(:configurer, 1) do + action(:synchronize) do + invoke do |certname| + facts = Puppet::Interface.interface(:facts, 1).find(certname) + catalog = Puppet::Interface.interface(:catalog, 1).download(certname, facts) + report = Puppet::Interface.interface(:catalog, 1).apply(catalog) + report + end + end +end diff --git a/lib/puppet/interface/v1/facts.rb b/lib/puppet/interface/v1/facts.rb new file mode 100644 index 000000000..0be23b781 --- /dev/null +++ b/lib/puppet/interface/v1/facts.rb @@ -0,0 +1,18 @@ +require 'puppet/interface/indirector' +require 'puppet/node/facts' + +Puppet::Interface::Indirector.interface(:facts, 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/interface/v1/file.rb b/lib/puppet/interface/v1/file.rb new file mode 100644 index 000000000..430413a56 --- /dev/null +++ b/lib/puppet/interface/v1/file.rb @@ -0,0 +1,5 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:file, 1) do + set_indirection_name :file_bucket_file +end diff --git a/lib/puppet/interface/v1/key.rb b/lib/puppet/interface/v1/key.rb new file mode 100644 index 000000000..fc82f4d68 --- /dev/null +++ b/lib/puppet/interface/v1/key.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:key, 1) do +end diff --git a/lib/puppet/interface/v1/node.rb b/lib/puppet/interface/v1/node.rb new file mode 100644 index 000000000..c3e527856 --- /dev/null +++ b/lib/puppet/interface/v1/node.rb @@ -0,0 +1,5 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:node, 1) do + set_default_format :yaml +end diff --git a/lib/puppet/interface/v1/report.rb b/lib/puppet/interface/v1/report.rb new file mode 100644 index 000000000..fdc2e2c0f --- /dev/null +++ b/lib/puppet/interface/v1/report.rb @@ -0,0 +1,15 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:report, 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/interface/v1/resource.rb b/lib/puppet/interface/v1/resource.rb new file mode 100644 index 000000000..20dc2837c --- /dev/null +++ b/lib/puppet/interface/v1/resource.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:resource, 1) do +end diff --git a/lib/puppet/interface/v1/resource_type.rb b/lib/puppet/interface/v1/resource_type.rb new file mode 100644 index 000000000..f180dc576 --- /dev/null +++ b/lib/puppet/interface/v1/resource_type.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:resource_type, 1) do +end diff --git a/lib/puppet/interface/v1/status.rb b/lib/puppet/interface/v1/status.rb new file mode 100644 index 000000000..a2493b581 --- /dev/null +++ b/lib/puppet/interface/v1/status.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:status, 1) do +end -- cgit From 635751d809af309c7c36c0c9d7a94a731ef8bd1c Mon Sep 17 00:00:00 2001 From: Richard Crowley Date: Wed, 23 Mar 2011 22:41:21 +0000 Subject: Propagating an argument to search out of core. Puppet::SSL::Host.search (which will proxy to the new indirection) accepts an array of classes (now also class names) to limit the search. Currently, `puppet certificate list` limits itself to certificate requests to mimic the behavior of `puppet cert -l`. --- lib/puppet/interface/certificate.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/certificate.rb b/lib/puppet/interface/certificate.rb index 5c06cdc29..86ac6d6ea 100644 --- a/lib/puppet/interface/certificate.rb +++ b/lib/puppet/interface/certificate.rb @@ -13,10 +13,9 @@ Puppet::Interface::Indirector.interface(:certificate) do action :list do invoke do - Puppet::SSL::Host.indirection.search("*").each do |host| - puts host.inspect - end - nil + Puppet::SSL::Host.indirection.search("*", { + :for => :certificate_request, + }).map { |h| h.inspect } end end -- cgit From 7aa8f2252c7b0512c929fb87a6c3a09a952a142a Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Wed, 23 Mar 2011 16:10:45 -0700 Subject: (#6770) Changing versioning to semver. More information about the versioning scheme can be found at http://semver.org. Paired-With: Nick Lewis --- lib/puppet/application/configurer.rb | 4 +-- lib/puppet/application/interface.rb | 2 +- lib/puppet/application/interface_base.rb | 4 +-- lib/puppet/interface/v0.0.1/catalog.rb | 40 ++++++++++++++++++++++ lib/puppet/interface/v0.0.1/catalog/select.rb | 10 ++++++ lib/puppet/interface/v0.0.1/certificate.rb | 4 +++ lib/puppet/interface/v0.0.1/certificate_request.rb | 4 +++ .../v0.0.1/certificate_revocation_list.rb | 4 +++ lib/puppet/interface/v0.0.1/config.rb | 10 ++++++ lib/puppet/interface/v0.0.1/configurer.rb | 12 +++++++ lib/puppet/interface/v0.0.1/facts.rb | 18 ++++++++++ lib/puppet/interface/v0.0.1/file.rb | 5 +++ lib/puppet/interface/v0.0.1/key.rb | 4 +++ lib/puppet/interface/v0.0.1/node.rb | 5 +++ lib/puppet/interface/v0.0.1/report.rb | 15 ++++++++ lib/puppet/interface/v0.0.1/resource.rb | 4 +++ lib/puppet/interface/v0.0.1/resource_type.rb | 4 +++ lib/puppet/interface/v0.0.1/status.rb | 4 +++ lib/puppet/interface/v1/catalog.rb | 40 ---------------------- lib/puppet/interface/v1/catalog/select.rb | 10 ------ lib/puppet/interface/v1/certificate.rb | 4 --- lib/puppet/interface/v1/certificate_request.rb | 4 --- .../interface/v1/certificate_revocation_list.rb | 4 --- lib/puppet/interface/v1/config.rb | 10 ------ lib/puppet/interface/v1/configurer.rb | 12 ------- lib/puppet/interface/v1/facts.rb | 18 ---------- lib/puppet/interface/v1/file.rb | 5 --- lib/puppet/interface/v1/key.rb | 4 --- lib/puppet/interface/v1/node.rb | 5 --- lib/puppet/interface/v1/report.rb | 15 -------- lib/puppet/interface/v1/resource.rb | 4 --- lib/puppet/interface/v1/resource_type.rb | 4 --- lib/puppet/interface/v1/status.rb | 4 --- 33 files changed, 148 insertions(+), 148 deletions(-) create mode 100644 lib/puppet/interface/v0.0.1/catalog.rb create mode 100644 lib/puppet/interface/v0.0.1/catalog/select.rb create mode 100644 lib/puppet/interface/v0.0.1/certificate.rb create mode 100644 lib/puppet/interface/v0.0.1/certificate_request.rb create mode 100644 lib/puppet/interface/v0.0.1/certificate_revocation_list.rb create mode 100644 lib/puppet/interface/v0.0.1/config.rb create mode 100644 lib/puppet/interface/v0.0.1/configurer.rb create mode 100644 lib/puppet/interface/v0.0.1/facts.rb create mode 100644 lib/puppet/interface/v0.0.1/file.rb create mode 100644 lib/puppet/interface/v0.0.1/key.rb create mode 100644 lib/puppet/interface/v0.0.1/node.rb create mode 100644 lib/puppet/interface/v0.0.1/report.rb create mode 100644 lib/puppet/interface/v0.0.1/resource.rb create mode 100644 lib/puppet/interface/v0.0.1/resource_type.rb create mode 100644 lib/puppet/interface/v0.0.1/status.rb delete mode 100644 lib/puppet/interface/v1/catalog.rb delete mode 100644 lib/puppet/interface/v1/catalog/select.rb delete mode 100644 lib/puppet/interface/v1/certificate.rb delete mode 100644 lib/puppet/interface/v1/certificate_request.rb delete mode 100644 lib/puppet/interface/v1/certificate_revocation_list.rb delete mode 100644 lib/puppet/interface/v1/config.rb delete mode 100644 lib/puppet/interface/v1/configurer.rb delete mode 100644 lib/puppet/interface/v1/facts.rb delete mode 100644 lib/puppet/interface/v1/file.rb delete mode 100644 lib/puppet/interface/v1/key.rb delete mode 100644 lib/puppet/interface/v1/node.rb delete mode 100644 lib/puppet/interface/v1/report.rb delete mode 100644 lib/puppet/interface/v1/resource.rb delete mode 100644 lib/puppet/interface/v1/resource_type.rb delete mode 100644 lib/puppet/interface/v1/status.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index a76aaaf01..92c8d69d0 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -17,7 +17,7 @@ class Puppet::Application::Configurer < Puppet::Application end def run_command - report = Puppet::Interface.interface(:configurer, 1).synchronize(Puppet[:certname]) - Puppet::Interface.interface(:report, 1).submit(report) + report = Puppet::Interface.interface(:configurer, '0.0.1').synchronize(Puppet[:certname]) + Puppet::Interface.interface(:report, '0.0.1').submit(report) end end diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb index 99c10dc16..3771ecead 100644 --- a/lib/puppet/application/interface.rb +++ b/lib/puppet/application/interface.rb @@ -81,7 +81,7 @@ class Puppet::Application::Interface < Puppet::Application end def actions(indirection) - return [] unless interface = Puppet::Interface.interface(indirection, 1) + return [] unless interface = Puppet::Interface.interface(indirection, '0.0.1') interface.load_actions return interface.actions.sort { |a,b| a.to_s <=> b.to_s } end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 78772833e..7d8885b3f 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -72,10 +72,10 @@ class Puppet::Application::InterfaceBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym # TODO: These should be configurable versions. - unless Puppet::Interface.interface?(@type, 1) + unless Puppet::Interface.interface?(@type, '0.0.1') raise "Could not find version #{1} of interface '#{@type}'" end - @interface = Puppet::Interface.interface(@type, 1) + @interface = Puppet::Interface.interface(@type, '0.0.1') @format ||= @interface.default_format # We copy all of the app options to the interface. diff --git a/lib/puppet/interface/v0.0.1/catalog.rb b/lib/puppet/interface/v0.0.1/catalog.rb new file mode 100644 index 000000000..647206251 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/catalog.rb @@ -0,0 +1,40 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(: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::Interface.interface(: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/interface/v0.0.1/catalog/select.rb b/lib/puppet/interface/v0.0.1/catalog/select.rb new file mode 100644 index 000000000..bc65069b8 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/catalog/select.rb @@ -0,0 +1,10 @@ +# Select and show a list of resources of a given type. +Puppet::Interface.interface(: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/interface/v0.0.1/certificate.rb b/lib/puppet/interface/v0.0.1/certificate.rb new file mode 100644 index 000000000..aee123aa6 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/certificate.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:certificate, '0.0.1') do +end diff --git a/lib/puppet/interface/v0.0.1/certificate_request.rb b/lib/puppet/interface/v0.0.1/certificate_request.rb new file mode 100644 index 000000000..169d6e500 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/certificate_request.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:certificate_request, '0.0.1') do +end diff --git a/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb b/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb new file mode 100644 index 000000000..7f4f5176b --- /dev/null +++ b/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:certificate_revocation_list, '0.0.1') do +end diff --git a/lib/puppet/interface/v0.0.1/config.rb b/lib/puppet/interface/v0.0.1/config.rb new file mode 100644 index 000000000..2437712ca --- /dev/null +++ b/lib/puppet/interface/v0.0.1/config.rb @@ -0,0 +1,10 @@ +require 'puppet/interface' + +Puppet::Interface.interface(:config, '0.0.1') do + action(:print) do + invoke do |*args| + Puppet.settings[:configprint] = args.join(",") + Puppet.settings.print_config_options + end + end +end diff --git a/lib/puppet/interface/v0.0.1/configurer.rb b/lib/puppet/interface/v0.0.1/configurer.rb new file mode 100644 index 000000000..0ab71c47a --- /dev/null +++ b/lib/puppet/interface/v0.0.1/configurer.rb @@ -0,0 +1,12 @@ +require 'puppet/interface' + +Puppet::Interface.interface(:configurer, '0.0.1') do + action(:synchronize) do + invoke do |certname| + facts = Puppet::Interface.interface(:facts, '0.0.1').find(certname) + catalog = Puppet::Interface.interface(:catalog, '0.0.1').download(certname, facts) + report = Puppet::Interface.interface(:catalog, '0.0.1').apply(catalog) + report + end + end +end diff --git a/lib/puppet/interface/v0.0.1/facts.rb b/lib/puppet/interface/v0.0.1/facts.rb new file mode 100644 index 000000000..e987d0740 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/facts.rb @@ -0,0 +1,18 @@ +require 'puppet/interface/indirector' +require 'puppet/node/facts' + +Puppet::Interface::Indirector.interface(: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/interface/v0.0.1/file.rb b/lib/puppet/interface/v0.0.1/file.rb new file mode 100644 index 000000000..2f27e434f --- /dev/null +++ b/lib/puppet/interface/v0.0.1/file.rb @@ -0,0 +1,5 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:file, '0.0.1') do + set_indirection_name :file_bucket_file +end diff --git a/lib/puppet/interface/v0.0.1/key.rb b/lib/puppet/interface/v0.0.1/key.rb new file mode 100644 index 000000000..ddd3a6ea8 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/key.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:key, '0.0.1') do +end diff --git a/lib/puppet/interface/v0.0.1/node.rb b/lib/puppet/interface/v0.0.1/node.rb new file mode 100644 index 000000000..898426846 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/node.rb @@ -0,0 +1,5 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:node, '0.0.1') do + set_default_format :yaml +end diff --git a/lib/puppet/interface/v0.0.1/report.rb b/lib/puppet/interface/v0.0.1/report.rb new file mode 100644 index 000000000..3f4e17310 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/report.rb @@ -0,0 +1,15 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(: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/interface/v0.0.1/resource.rb b/lib/puppet/interface/v0.0.1/resource.rb new file mode 100644 index 000000000..61c90cc85 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/resource.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:resource, '0.0.1') do +end diff --git a/lib/puppet/interface/v0.0.1/resource_type.rb b/lib/puppet/interface/v0.0.1/resource_type.rb new file mode 100644 index 000000000..9cc4bef28 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/resource_type.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:resource_type, '0.0.1') do +end diff --git a/lib/puppet/interface/v0.0.1/status.rb b/lib/puppet/interface/v0.0.1/status.rb new file mode 100644 index 000000000..d8cded899 --- /dev/null +++ b/lib/puppet/interface/v0.0.1/status.rb @@ -0,0 +1,4 @@ +require 'puppet/interface/indirector' + +Puppet::Interface::Indirector.interface(:status, '0.0.1') do +end diff --git a/lib/puppet/interface/v1/catalog.rb b/lib/puppet/interface/v1/catalog.rb deleted file mode 100644 index 2ba642039..000000000 --- a/lib/puppet/interface/v1/catalog.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:catalog, 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::Interface.interface(:catalog, 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/interface/v1/catalog/select.rb b/lib/puppet/interface/v1/catalog/select.rb deleted file mode 100644 index e37c841b5..000000000 --- a/lib/puppet/interface/v1/catalog/select.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Select and show a list of resources of a given type. -Puppet::Interface.interface(:catalog, 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/interface/v1/certificate.rb b/lib/puppet/interface/v1/certificate.rb deleted file mode 100644 index 9a88c628a..000000000 --- a/lib/puppet/interface/v1/certificate.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:certificate, 1) do -end diff --git a/lib/puppet/interface/v1/certificate_request.rb b/lib/puppet/interface/v1/certificate_request.rb deleted file mode 100644 index 868933e1f..000000000 --- a/lib/puppet/interface/v1/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:certificate_request, 1) do -end diff --git a/lib/puppet/interface/v1/certificate_revocation_list.rb b/lib/puppet/interface/v1/certificate_revocation_list.rb deleted file mode 100644 index 09efd8c7a..000000000 --- a/lib/puppet/interface/v1/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:certificate_revocation_list, 1) do -end diff --git a/lib/puppet/interface/v1/config.rb b/lib/puppet/interface/v1/config.rb deleted file mode 100644 index a072e703c..000000000 --- a/lib/puppet/interface/v1/config.rb +++ /dev/null @@ -1,10 +0,0 @@ -require 'puppet/interface' - -Puppet::Interface.interface(:config, 1) do - action(:print) do - invoke do |*args| - Puppet.settings[:configprint] = args.join(",") - Puppet.settings.print_config_options - end - end -end diff --git a/lib/puppet/interface/v1/configurer.rb b/lib/puppet/interface/v1/configurer.rb deleted file mode 100644 index 1deffce4e..000000000 --- a/lib/puppet/interface/v1/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/interface' - -Puppet::Interface.interface(:configurer, 1) do - action(:synchronize) do - invoke do |certname| - facts = Puppet::Interface.interface(:facts, 1).find(certname) - catalog = Puppet::Interface.interface(:catalog, 1).download(certname, facts) - report = Puppet::Interface.interface(:catalog, 1).apply(catalog) - report - end - end -end diff --git a/lib/puppet/interface/v1/facts.rb b/lib/puppet/interface/v1/facts.rb deleted file mode 100644 index 0be23b781..000000000 --- a/lib/puppet/interface/v1/facts.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'puppet/interface/indirector' -require 'puppet/node/facts' - -Puppet::Interface::Indirector.interface(:facts, 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/interface/v1/file.rb b/lib/puppet/interface/v1/file.rb deleted file mode 100644 index 430413a56..000000000 --- a/lib/puppet/interface/v1/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:file, 1) do - set_indirection_name :file_bucket_file -end diff --git a/lib/puppet/interface/v1/key.rb b/lib/puppet/interface/v1/key.rb deleted file mode 100644 index fc82f4d68..000000000 --- a/lib/puppet/interface/v1/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:key, 1) do -end diff --git a/lib/puppet/interface/v1/node.rb b/lib/puppet/interface/v1/node.rb deleted file mode 100644 index c3e527856..000000000 --- a/lib/puppet/interface/v1/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:node, 1) do - set_default_format :yaml -end diff --git a/lib/puppet/interface/v1/report.rb b/lib/puppet/interface/v1/report.rb deleted file mode 100644 index fdc2e2c0f..000000000 --- a/lib/puppet/interface/v1/report.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:report, 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/interface/v1/resource.rb b/lib/puppet/interface/v1/resource.rb deleted file mode 100644 index 20dc2837c..000000000 --- a/lib/puppet/interface/v1/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:resource, 1) do -end diff --git a/lib/puppet/interface/v1/resource_type.rb b/lib/puppet/interface/v1/resource_type.rb deleted file mode 100644 index f180dc576..000000000 --- a/lib/puppet/interface/v1/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:resource_type, 1) do -end diff --git a/lib/puppet/interface/v1/status.rb b/lib/puppet/interface/v1/status.rb deleted file mode 100644 index a2493b581..000000000 --- a/lib/puppet/interface/v1/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.interface(:status, 1) do -end -- cgit From c25fb94725c9abfb36e67938356f97823f8b605e Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Wed, 23 Mar 2011 16:28:28 -0700 Subject: (#6770) Rename Puppet::Interface::interface method. Puppet::Interface::interface is now Puppet::Interface::define, also aliased to Puppet::Interface::[] for convenience. Paired-With: Nick Lewis --- lib/puppet/application/configurer.rb | 4 +- lib/puppet/application/interface.rb | 2 +- lib/puppet/application/interface_base.rb | 2 +- lib/puppet/interface.rb | 52 ++++++++++++---------- lib/puppet/interface/v0.0.1/catalog.rb | 4 +- lib/puppet/interface/v0.0.1/catalog/select.rb | 2 +- lib/puppet/interface/v0.0.1/certificate.rb | 2 +- lib/puppet/interface/v0.0.1/certificate_request.rb | 2 +- .../v0.0.1/certificate_revocation_list.rb | 2 +- lib/puppet/interface/v0.0.1/config.rb | 2 +- lib/puppet/interface/v0.0.1/configurer.rb | 8 ++-- lib/puppet/interface/v0.0.1/facts.rb | 2 +- lib/puppet/interface/v0.0.1/file.rb | 2 +- lib/puppet/interface/v0.0.1/key.rb | 2 +- lib/puppet/interface/v0.0.1/node.rb | 2 +- lib/puppet/interface/v0.0.1/report.rb | 2 +- lib/puppet/interface/v0.0.1/resource.rb | 2 +- lib/puppet/interface/v0.0.1/resource_type.rb | 2 +- lib/puppet/interface/v0.0.1/status.rb | 2 +- 19 files changed, 51 insertions(+), 47 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index 92c8d69d0..5c9af37d7 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -17,7 +17,7 @@ class Puppet::Application::Configurer < Puppet::Application end def run_command - report = Puppet::Interface.interface(:configurer, '0.0.1').synchronize(Puppet[:certname]) - Puppet::Interface.interface(:report, '0.0.1').submit(report) + report = Puppet::Interface[:configurer, '0.0.1'].synchronize(Puppet[:certname]) + Puppet::Interface[:report, '0.0.1'].submit(report) end end diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb index 3771ecead..f447dc30d 100644 --- a/lib/puppet/application/interface.rb +++ b/lib/puppet/application/interface.rb @@ -81,7 +81,7 @@ class Puppet::Application::Interface < Puppet::Application end def actions(indirection) - return [] unless interface = Puppet::Interface.interface(indirection, '0.0.1') + return [] unless interface = Puppet::Interface[indirection, '0.0.1'] interface.load_actions return interface.actions.sort { |a,b| a.to_s <=> b.to_s } end diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index 7d8885b3f..c1c02040a 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -75,7 +75,7 @@ class Puppet::Application::InterfaceBase < Puppet::Application unless Puppet::Interface.interface?(@type, '0.0.1') raise "Could not find version #{1} of interface '#{@type}'" end - @interface = Puppet::Interface.interface(@type, '0.0.1') + @interface = Puppet::Interface[@type, '0.0.1'] @format ||= @interface.default_format # We copy all of the app options to the interface. diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 7f208f56c..64f1bfe49 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -10,35 +10,39 @@ class Puppet::Interface include Puppet::Util - # This is just so we can search for actions. We only use its - # list of directories to search. - # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb - def self.autoloader - @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") - end + class << self + # This is just so we can search for actions. We only use its + # list of directories to search. + # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb + def autoloader + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") + end - def self.interfaces - Puppet::Interface::InterfaceCollection.interfaces - end + def interfaces + Puppet::Interface::InterfaceCollection.interfaces + end - def self.interface?(name, version) - Puppet::Interface::InterfaceCollection.interface?(name, version) - end + def interface?(name, version) + Puppet::Interface::InterfaceCollection.interface?(name, version) + end - def self.register(instance) - Puppet::Interface::InterfaceCollection.register(instance) - end + def register(instance) + Puppet::Interface::InterfaceCollection.register(instance) + end - def self.interface(name, version, &blk) - if interface?(name, version) - interface = Puppet::Interface::InterfaceCollection[name, version] - interface.instance_eval(&blk) if blk - else - interface = self.new(name, :version => version, &blk) - Puppet::Interface::InterfaceCollection.register(interface) - interface.load_actions + def define(name, version, &blk) + if interface?(name, version) + interface = Puppet::Interface::InterfaceCollection[name, version] + interface.instance_eval(&blk) if blk + else + interface = self.new(name, :version => version, &blk) + Puppet::Interface::InterfaceCollection.register(interface) + interface.load_actions + end + return interface end - return interface + + alias :[] :define end attr_accessor :default_format diff --git a/lib/puppet/interface/v0.0.1/catalog.rb b/lib/puppet/interface/v0.0.1/catalog.rb index 647206251..7d61528bc 100644 --- a/lib/puppet/interface/v0.0.1/catalog.rb +++ b/lib/puppet/interface/v0.0.1/catalog.rb @@ -1,6 +1,6 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:catalog, '0.0.1') do +Puppet::Interface::Indirector.define(:catalog, '0.0.1') do action(:apply) do invoke do |catalog| report = Puppet::Transaction::Report.new("apply") @@ -28,7 +28,7 @@ Puppet::Interface::Indirector.interface(:catalog, '0.0.1') do facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} catalog = nil retrieval_duration = thinmark do - catalog = Puppet::Interface.interface(:catalog, '0.0.1').find(certname, facts_to_upload) + catalog = Puppet::Interface[:catalog, '0.0.1'].find(certname, facts_to_upload) end catalog = catalog.to_ral catalog.finalize diff --git a/lib/puppet/interface/v0.0.1/catalog/select.rb b/lib/puppet/interface/v0.0.1/catalog/select.rb index bc65069b8..35f1a1e0b 100644 --- a/lib/puppet/interface/v0.0.1/catalog/select.rb +++ b/lib/puppet/interface/v0.0.1/catalog/select.rb @@ -1,5 +1,5 @@ # Select and show a list of resources of a given type. -Puppet::Interface.interface(:catalog, '0.0.1') do +Puppet::Interface.define(:catalog, '0.0.1') do action :select do invoke do |host,type| catalog = Puppet::Resource::Catalog.indirection.find(host) diff --git a/lib/puppet/interface/v0.0.1/certificate.rb b/lib/puppet/interface/v0.0.1/certificate.rb index aee123aa6..52019fddd 100644 --- a/lib/puppet/interface/v0.0.1/certificate.rb +++ b/lib/puppet/interface/v0.0.1/certificate.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:certificate, '0.0.1') do +Puppet::Interface::Indirector.define(:certificate, '0.0.1') do end diff --git a/lib/puppet/interface/v0.0.1/certificate_request.rb b/lib/puppet/interface/v0.0.1/certificate_request.rb index 169d6e500..e5ed1b51e 100644 --- a/lib/puppet/interface/v0.0.1/certificate_request.rb +++ b/lib/puppet/interface/v0.0.1/certificate_request.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:certificate_request, '0.0.1') do +Puppet::Interface::Indirector.define(:certificate_request, '0.0.1') do end diff --git a/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb b/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb index 7f4f5176b..f6d8a3d6d 100644 --- a/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb +++ b/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:certificate_revocation_list, '0.0.1') do +Puppet::Interface::Indirector.define(:certificate_revocation_list, '0.0.1') do end diff --git a/lib/puppet/interface/v0.0.1/config.rb b/lib/puppet/interface/v0.0.1/config.rb index 2437712ca..b33e19bb4 100644 --- a/lib/puppet/interface/v0.0.1/config.rb +++ b/lib/puppet/interface/v0.0.1/config.rb @@ -1,6 +1,6 @@ require 'puppet/interface' -Puppet::Interface.interface(:config, '0.0.1') do +Puppet::Interface.define(:config, '0.0.1') do action(:print) do invoke do |*args| Puppet.settings[:configprint] = args.join(",") diff --git a/lib/puppet/interface/v0.0.1/configurer.rb b/lib/puppet/interface/v0.0.1/configurer.rb index 0ab71c47a..38536b684 100644 --- a/lib/puppet/interface/v0.0.1/configurer.rb +++ b/lib/puppet/interface/v0.0.1/configurer.rb @@ -1,11 +1,11 @@ require 'puppet/interface' -Puppet::Interface.interface(:configurer, '0.0.1') do +Puppet::Interface.define(:configurer, '0.0.1') do action(:synchronize) do invoke do |certname| - facts = Puppet::Interface.interface(:facts, '0.0.1').find(certname) - catalog = Puppet::Interface.interface(:catalog, '0.0.1').download(certname, facts) - report = Puppet::Interface.interface(:catalog, '0.0.1').apply(catalog) + facts = Puppet::Interface[:facts, '0.0.1'].find(certname) + catalog = Puppet::Interface[:catalog, '0.0.1'].download(certname, facts) + report = Puppet::Interface[:catalog, '0.0.1'].apply(catalog) report end end diff --git a/lib/puppet/interface/v0.0.1/facts.rb b/lib/puppet/interface/v0.0.1/facts.rb index e987d0740..c4bbad845 100644 --- a/lib/puppet/interface/v0.0.1/facts.rb +++ b/lib/puppet/interface/v0.0.1/facts.rb @@ -1,7 +1,7 @@ require 'puppet/interface/indirector' require 'puppet/node/facts' -Puppet::Interface::Indirector.interface(:facts, '0.0.1') do +Puppet::Interface::Indirector.define(:facts, '0.0.1') do set_default_format :yaml # Upload our facts to the server diff --git a/lib/puppet/interface/v0.0.1/file.rb b/lib/puppet/interface/v0.0.1/file.rb index 2f27e434f..91904e8e0 100644 --- a/lib/puppet/interface/v0.0.1/file.rb +++ b/lib/puppet/interface/v0.0.1/file.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:file, '0.0.1') do +Puppet::Interface::Indirector.define(:file, '0.0.1') do set_indirection_name :file_bucket_file end diff --git a/lib/puppet/interface/v0.0.1/key.rb b/lib/puppet/interface/v0.0.1/key.rb index ddd3a6ea8..fbc9b67b1 100644 --- a/lib/puppet/interface/v0.0.1/key.rb +++ b/lib/puppet/interface/v0.0.1/key.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:key, '0.0.1') do +Puppet::Interface::Indirector.define(:key, '0.0.1') do end diff --git a/lib/puppet/interface/v0.0.1/node.rb b/lib/puppet/interface/v0.0.1/node.rb index 898426846..4ecec1478 100644 --- a/lib/puppet/interface/v0.0.1/node.rb +++ b/lib/puppet/interface/v0.0.1/node.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:node, '0.0.1') do +Puppet::Interface::Indirector.define(:node, '0.0.1') do set_default_format :yaml end diff --git a/lib/puppet/interface/v0.0.1/report.rb b/lib/puppet/interface/v0.0.1/report.rb index 3f4e17310..bacb46e70 100644 --- a/lib/puppet/interface/v0.0.1/report.rb +++ b/lib/puppet/interface/v0.0.1/report.rb @@ -1,6 +1,6 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:report, '0.0.1') do +Puppet::Interface::Indirector.define(:report, '0.0.1') do action(:submit) do invoke do |report| begin diff --git a/lib/puppet/interface/v0.0.1/resource.rb b/lib/puppet/interface/v0.0.1/resource.rb index 61c90cc85..1a6f3b69d 100644 --- a/lib/puppet/interface/v0.0.1/resource.rb +++ b/lib/puppet/interface/v0.0.1/resource.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:resource, '0.0.1') do +Puppet::Interface::Indirector.define(:resource, '0.0.1') do end diff --git a/lib/puppet/interface/v0.0.1/resource_type.rb b/lib/puppet/interface/v0.0.1/resource_type.rb index 9cc4bef28..6f5547c4d 100644 --- a/lib/puppet/interface/v0.0.1/resource_type.rb +++ b/lib/puppet/interface/v0.0.1/resource_type.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:resource_type, '0.0.1') do +Puppet::Interface::Indirector.define(:resource_type, '0.0.1') do end diff --git a/lib/puppet/interface/v0.0.1/status.rb b/lib/puppet/interface/v0.0.1/status.rb index d8cded899..7f4b56a2b 100644 --- a/lib/puppet/interface/v0.0.1/status.rb +++ b/lib/puppet/interface/v0.0.1/status.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:status, '0.0.1') do +Puppet::Interface::Indirector.define(:status, '0.0.1') do end -- cgit From 633f63cdbc1d5630e546041bb0c1e714216158d0 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 24 Mar 2011 13:33:30 -0700 Subject: (#6833) support 'script' as a short form of 'action' At the moment the action method is a fairly heavy tool: it provides a DSL, and is designed to allow substantial metadata to be added to the action. For some users this is low on value, since they just want to write a little script that drives things a bit differently. Which there is substantial value in the metadata, adding the capability to do these light-weight things quickly is valid. To meet this we add a script action; the contrast is: action :foo do # other metadata goes here invoke do |args| # method body goes here end end script :bar do |args| # method body goes here end # ...and if you want metadata, you have to add it in more ugly, procedural # ways, which we are not going to encourage. Reviewed-By: Pieter van de Bruggen --- lib/puppet/interface/action.rb | 12 +++++++++++- lib/puppet/interface/action_builder.rb | 9 +++------ lib/puppet/interface/action_manager.rb | 9 +++++++++ 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index e4c2a4666..1c19bd08c 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -3,9 +3,11 @@ require 'puppet/interface' class Puppet::Interface::Action attr_reader :name - def initialize(interface, name) + def initialize(interface, name, attrs = {}) name = name.to_s raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/ + + attrs.each do |k,v| send("#{k}=", v) end @interface = interface @name = name end @@ -13,4 +15,12 @@ class Puppet::Interface::Action def invoke(*args, &block) @interface.method(name).call(*args,&block) end + + def invoke=(block) + if @interface.is_a?(Class) + @interface.define_method(@name, &block) + else + @interface.meta_def(@name, &block) + end + end end diff --git a/lib/puppet/interface/action_builder.rb b/lib/puppet/interface/action_builder.rb index e76fb1c6e..e389ea3ea 100644 --- a/lib/puppet/interface/action_builder.rb +++ b/lib/puppet/interface/action_builder.rb @@ -18,13 +18,10 @@ class Puppet::Interface::ActionBuilder end # Ideally the method we're defining here would be added to the action, and a - # method on the interface would defer to it + # method on the interface 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 - if @interface.is_a?(Class) - @interface.define_method(@action.name, &block) - else - @interface.meta_def(@action.name, &block) - end + @action.invoke = block end end diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb index 0db82d612..8b2944bb1 100644 --- a/lib/puppet/interface/action_manager.rb +++ b/lib/puppet/interface/action_manager.rb @@ -14,6 +14,15 @@ module Puppet::Interface::ActionManager @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::Interface::Action.new(self, name, :invoke => block) + end + def actions @actions ||= {} result = @actions.keys -- cgit From 53b0656048c3227048bdc317c5e917ad0c39e850 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Fri, 25 Mar 2011 08:55:24 -0700 Subject: Config#print action always returns nil We were returning 'true', which was getting printed unnecessarily. Signed-off-by: Luke Kanies --- lib/puppet/interface/v0.0.1/config.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/v0.0.1/config.rb b/lib/puppet/interface/v0.0.1/config.rb index b33e19bb4..7b74ce542 100644 --- a/lib/puppet/interface/v0.0.1/config.rb +++ b/lib/puppet/interface/v0.0.1/config.rb @@ -5,6 +5,7 @@ Puppet::Interface.define(:config, '0.0.1') do invoke do |*args| Puppet.settings[:configprint] = args.join(",") Puppet.settings.print_config_options + nil end end end -- cgit From 78371a739bcf1b1d76496e9038fa4b076a27032f Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Thu, 24 Mar 2011 09:25:33 -0700 Subject: (#6770) Refactor Puppet::Interface#initialize. P::I#initialize now takes a name and a version (and an optional block). The options hash has been removed, though it may be reintroduced if a legitimate use case can be made for it (so far, it's only been used for the version number). Reviewed-By: Jacob Helwig --- lib/puppet/interface.rb | 23 ++++++++++------------- lib/puppet/interface/interface_collection.rb | 2 +- 2 files changed, 11 insertions(+), 14 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 64f1bfe49..27cbb7522 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -30,15 +30,17 @@ class Puppet::Interface Puppet::Interface::InterfaceCollection.register(instance) end - def define(name, version, &blk) + def define(name, version, &block) if interface?(name, version) interface = Puppet::Interface::InterfaceCollection[name, version] - interface.instance_eval(&blk) if blk else - interface = self.new(name, :version => version, &blk) + interface = self.new(name, version) Puppet::Interface::InterfaceCollection.register(interface) interface.load_actions end + + interface.instance_eval(&block) if block_given? + return interface end @@ -54,22 +56,17 @@ class Puppet::Interface attr_accessor :type, :verb, :version, :arguments, :options attr_reader :name - def initialize(name, options = {}, &block) - unless options[:version] - raise ArgumentError, "Interface #{name} declared without version!" - end - + def initialize(name, version, &block) @name = Puppet::Interface::InterfaceCollection.underscorize(name) - + @version = version @default_format = :pson - options.each { |opt, val| send(opt.to_s + "=", val) } - instance_eval(&block) if block + instance_eval(&block) if block_given? end # Try to find actions defined in other files. def load_actions - path = "puppet/interface/#{name}" + path = "puppet/interface/v#{version}/#{name}" loaded = [] Puppet::Interface.autoloader.search_directories.each do |dir| @@ -92,6 +89,6 @@ class Puppet::Interface end def to_s - "Puppet::Interface(#{name}, :version => #{version.inspect})" + "Puppet::Interface[#{name.inspect}, #{version.inspect}]" end end diff --git a/lib/puppet/interface/interface_collection.rb b/lib/puppet/interface/interface_collection.rb index d626c4f72..51b7534a0 100644 --- a/lib/puppet/interface/interface_collection.rb +++ b/lib/puppet/interface/interface_collection.rb @@ -9,7 +9,7 @@ module Puppet::Interface::InterfaceCollection $LOAD_PATH.each do |dir| next unless FileTest.directory?(dir) Dir.chdir(dir) do - Dir.glob("puppet/interface/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| + Dir.glob("puppet/interface/v*/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| iname = file.sub(/\.rb/, '') begin require iname -- cgit From 1af9bb232ed73f16789f465e89a0d498c39e1b78 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Thu, 24 Mar 2011 15:06:21 -0700 Subject: (#6770) Add version lookup and comparison. Reviewed-By: Jacob Helwig --- lib/puppet/interface/interface_collection.rb | 35 ++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/interface_collection.rb b/lib/puppet/interface/interface_collection.rb index 51b7534a0..115892397 100644 --- a/lib/puppet/interface/interface_collection.rb +++ b/lib/puppet/interface/interface_collection.rb @@ -1,6 +1,8 @@ require 'puppet/interface' module Puppet::Interface::InterfaceCollection + SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ + @interfaces = Hash.new { |hash, key| hash[key] = {} } def self.interfaces @@ -24,6 +26,39 @@ module Puppet::Interface::InterfaceCollection return @interfaces.keys end + def self.versions(name) + versions = [] + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + v_dir = File.join dir, %w[puppet interface v*] + Dir.glob(File.join v_dir, "#{name}{.rb,/*.rb}").each do |f| + v = f.sub(%r[.*/v([^/]+?)/#{name}(?:(?:/[^/]+)?.rb)$], '\1') + if v =~ SEMVER_VERSION + 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.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) @interfaces[underscorize(name)][version] if interface?(name, version) end -- cgit From 6aea116701b8e03558ef7a5a15766b267af14281 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Thu, 24 Mar 2011 18:55:32 -0700 Subject: (#6770) Add support for version :latest. Specifying a version of `:latest` will find the most recent version of the named interface installed in your RUBYLIB, and attempt to load that. This is unlikely to provide a stable dependency in the future, so should be used sparingly, acknowledging the dangers. Reviewed-By: Daniel Pittman --- lib/puppet/application/interface_base.rb | 6 +++--- lib/puppet/interface.rb | 4 ++++ lib/puppet/interface/interface_collection.rb | 15 +++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb index c1c02040a..841f3ca12 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -72,10 +72,10 @@ class Puppet::Application::InterfaceBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym # TODO: These should be configurable versions. - unless Puppet::Interface.interface?(@type, '0.0.1') - raise "Could not find version #{1} of interface '#{@type}'" + unless Puppet::Interface.interface?(@type, :latest) + raise "Could not find any version of interface '#{@type}'" end - @interface = Puppet::Interface[@type, '0.0.1'] + @interface = Puppet::Interface[@type, :latest] @format ||= @interface.default_format # We copy all of the app options to the interface. diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 27cbb7522..a667c6b75 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -57,6 +57,10 @@ class Puppet::Interface attr_reader :name def initialize(name, version, &block) + unless Puppet::Interface::InterfaceCollection.validate_version(version) + raise ArgumentError, "Cannot create interface with invalid version number '#{version}'!" + end + @name = Puppet::Interface::InterfaceCollection.underscorize(name) @version = version @default_format = :pson diff --git a/lib/puppet/interface/interface_collection.rb b/lib/puppet/interface/interface_collection.rb index 115892397..92e2933fe 100644 --- a/lib/puppet/interface/interface_collection.rb +++ b/lib/puppet/interface/interface_collection.rb @@ -33,7 +33,7 @@ module Puppet::Interface::InterfaceCollection v_dir = File.join dir, %w[puppet interface v*] Dir.glob(File.join v_dir, "#{name}{.rb,/*.rb}").each do |f| v = f.sub(%r[.*/v([^/]+?)/#{name}(?:(?:/[^/]+)?.rb)$], '\1') - if v =~ SEMVER_VERSION + if validate_version(v) versions << v else warn "'#{v}' (#{f}) is not a valid version string; skipping" @@ -43,6 +43,10 @@ module Puppet::Interface::InterfaceCollection 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] @@ -60,11 +64,18 @@ module Puppet::Interface::InterfaceCollection end def self.[](name, version) - @interfaces[underscorize(name)][version] if interface?(name, version) + version = versions(name).last if version == :latest + unless version.nil? + @interfaces[underscorize(name)][version] if interface?(name, version) + end end def self.interface?(name, version) + version = versions(name).last if version == :latest + return false if version.nil? + name = underscorize(name) + unless @interfaces.has_key?(name) && @interfaces[name].has_key?(version) require "puppet/interface/v#{version}/#{name}" end -- cgit From 88aeb04a50d8997b5e1e0ed7a5a2239508b174ee Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 25 Mar 2011 10:38:40 -0700 Subject: MAINT: fix the misordered invocations in action. When initializing we need to set the name and interface before we do anything else, since the reasonable assumption for users is that those invariants are there when their setter is called. This allows someone to override the interface or name by misusing the call to new, but they could already screw up by passing the wrong values, so whatever. --- lib/puppet/interface/action.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb index 1c19bd08c..1a5730d1b 100644 --- a/lib/puppet/interface/action.rb +++ b/lib/puppet/interface/action.rb @@ -7,9 +7,9 @@ class Puppet::Interface::Action name = name.to_s raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/ - attrs.each do |k,v| send("#{k}=", v) end @interface = interface - @name = name + @name = name + attrs.each do |k,v| send("#{k}=", v) end end def invoke(*args, &block) -- cgit From b859baa04737644e40002f511c5941d002a956e3 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Sat, 26 Mar 2011 00:12:17 -0700 Subject: MAINT: the API is officially named "string" as of this moment. Now that we have settled on the final public name for the API, "Puppet::String", mass-rename and mass-edit all the files to follow. Reviewed-By: Randall Hansen --- lib/puppet/application/config.rb | 4 +- lib/puppet/application/configurer.rb | 6 +- lib/puppet/application/indirection_base.rb | 10 +-- lib/puppet/application/interface.rb | 95 --------------------- lib/puppet/application/interface_base.rb | 97 --------------------- lib/puppet/application/string.rb | 95 +++++++++++++++++++++ lib/puppet/application/string_base.rb | 97 +++++++++++++++++++++ lib/puppet/interface.rb | 98 ---------------------- lib/puppet/interface/action.rb | 26 ------ lib/puppet/interface/action_builder.rb | 27 ------ lib/puppet/interface/action_manager.rb | 45 ---------- lib/puppet/interface/indirector.rb | 79 ----------------- lib/puppet/interface/interface_collection.rb | 98 ---------------------- lib/puppet/interface/v0.0.1/catalog.rb | 40 --------- lib/puppet/interface/v0.0.1/catalog/select.rb | 10 --- lib/puppet/interface/v0.0.1/certificate.rb | 28 ------- lib/puppet/interface/v0.0.1/certificate_request.rb | 4 - .../v0.0.1/certificate_revocation_list.rb | 4 - lib/puppet/interface/v0.0.1/config.rb | 11 --- lib/puppet/interface/v0.0.1/configurer.rb | 12 --- lib/puppet/interface/v0.0.1/facts.rb | 18 ---- lib/puppet/interface/v0.0.1/file.rb | 5 -- lib/puppet/interface/v0.0.1/key.rb | 4 - lib/puppet/interface/v0.0.1/node.rb | 5 -- lib/puppet/interface/v0.0.1/report.rb | 15 ---- lib/puppet/interface/v0.0.1/resource.rb | 4 - lib/puppet/interface/v0.0.1/resource_type.rb | 4 - lib/puppet/interface/v0.0.1/status.rb | 4 - lib/puppet/string.rb | 98 ++++++++++++++++++++++ lib/puppet/string/action.rb | 26 ++++++ lib/puppet/string/action_builder.rb | 27 ++++++ lib/puppet/string/action_manager.rb | 45 ++++++++++ lib/puppet/string/indirector.rb | 79 +++++++++++++++++ lib/puppet/string/string_collection.rb | 98 ++++++++++++++++++++++ lib/puppet/string/v0.0.1/catalog.rb | 40 +++++++++ lib/puppet/string/v0.0.1/catalog/select.rb | 10 +++ lib/puppet/string/v0.0.1/certificate.rb | 28 +++++++ lib/puppet/string/v0.0.1/certificate_request.rb | 4 + .../string/v0.0.1/certificate_revocation_list.rb | 4 + lib/puppet/string/v0.0.1/config.rb | 11 +++ lib/puppet/string/v0.0.1/configurer.rb | 12 +++ lib/puppet/string/v0.0.1/facts.rb | 18 ++++ lib/puppet/string/v0.0.1/file.rb | 5 ++ lib/puppet/string/v0.0.1/key.rb | 4 + lib/puppet/string/v0.0.1/node.rb | 5 ++ lib/puppet/string/v0.0.1/report.rb | 15 ++++ lib/puppet/string/v0.0.1/resource.rb | 4 + lib/puppet/string/v0.0.1/resource_type.rb | 4 + lib/puppet/string/v0.0.1/status.rb | 4 + 49 files changed, 743 insertions(+), 743 deletions(-) delete mode 100644 lib/puppet/application/interface.rb delete mode 100644 lib/puppet/application/interface_base.rb create mode 100644 lib/puppet/application/string.rb create mode 100644 lib/puppet/application/string_base.rb delete mode 100644 lib/puppet/interface.rb delete mode 100644 lib/puppet/interface/action.rb delete mode 100644 lib/puppet/interface/action_builder.rb delete mode 100644 lib/puppet/interface/action_manager.rb delete mode 100644 lib/puppet/interface/indirector.rb delete mode 100644 lib/puppet/interface/interface_collection.rb delete mode 100644 lib/puppet/interface/v0.0.1/catalog.rb delete mode 100644 lib/puppet/interface/v0.0.1/catalog/select.rb delete mode 100644 lib/puppet/interface/v0.0.1/certificate.rb delete mode 100644 lib/puppet/interface/v0.0.1/certificate_request.rb delete mode 100644 lib/puppet/interface/v0.0.1/certificate_revocation_list.rb delete mode 100644 lib/puppet/interface/v0.0.1/config.rb delete mode 100644 lib/puppet/interface/v0.0.1/configurer.rb delete mode 100644 lib/puppet/interface/v0.0.1/facts.rb delete mode 100644 lib/puppet/interface/v0.0.1/file.rb delete mode 100644 lib/puppet/interface/v0.0.1/key.rb delete mode 100644 lib/puppet/interface/v0.0.1/node.rb delete mode 100644 lib/puppet/interface/v0.0.1/report.rb delete mode 100644 lib/puppet/interface/v0.0.1/resource.rb delete mode 100644 lib/puppet/interface/v0.0.1/resource_type.rb delete mode 100644 lib/puppet/interface/v0.0.1/status.rb create mode 100644 lib/puppet/string.rb create mode 100644 lib/puppet/string/action.rb create mode 100644 lib/puppet/string/action_builder.rb create mode 100644 lib/puppet/string/action_manager.rb create mode 100644 lib/puppet/string/indirector.rb create mode 100644 lib/puppet/string/string_collection.rb create mode 100644 lib/puppet/string/v0.0.1/catalog.rb create mode 100644 lib/puppet/string/v0.0.1/catalog/select.rb create mode 100644 lib/puppet/string/v0.0.1/certificate.rb create mode 100644 lib/puppet/string/v0.0.1/certificate_request.rb create mode 100644 lib/puppet/string/v0.0.1/certificate_revocation_list.rb create mode 100644 lib/puppet/string/v0.0.1/config.rb create mode 100644 lib/puppet/string/v0.0.1/configurer.rb create mode 100644 lib/puppet/string/v0.0.1/facts.rb create mode 100644 lib/puppet/string/v0.0.1/file.rb create mode 100644 lib/puppet/string/v0.0.1/key.rb create mode 100644 lib/puppet/string/v0.0.1/node.rb create mode 100644 lib/puppet/string/v0.0.1/report.rb create mode 100644 lib/puppet/string/v0.0.1/resource.rb create mode 100644 lib/puppet/string/v0.0.1/resource_type.rb create mode 100644 lib/puppet/string/v0.0.1/status.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/config.rb b/lib/puppet/application/config.rb index 90c5f53c4..f6559277b 100644 --- a/lib/puppet/application/config.rb +++ b/lib/puppet/application/config.rb @@ -1,4 +1,4 @@ -require 'puppet/application/interface_base' +require 'puppet/application/string_base' -class Puppet::Application::Config < Puppet::Application::InterfaceBase +class Puppet::Application::Config < Puppet::Application::StringBase end diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index 5c9af37d7..b440098ee 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -1,5 +1,5 @@ require 'puppet/application' -require 'puppet/interface' +require 'puppet/string' class Puppet::Application::Configurer < Puppet::Application should_parse_config @@ -17,7 +17,7 @@ class Puppet::Application::Configurer < Puppet::Application end def run_command - report = Puppet::Interface[:configurer, '0.0.1'].synchronize(Puppet[:certname]) - Puppet::Interface[:report, '0.0.1'].submit(report) + report = Puppet::String[:configurer, '0.0.1'].synchronize(Puppet[:certname]) + Puppet::String[:report, '0.0.1'].submit(report) end end diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index 7d1c851cf..da61f408d 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -1,6 +1,6 @@ -require 'puppet/application/interface_base' +require 'puppet/application/string_base' -class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase +class Puppet::Application::IndirectionBase < Puppet::Application::StringBase option("--terminus TERMINUS") do |arg| @terminus = arg end @@ -10,10 +10,10 @@ class Puppet::Application::IndirectionBase < Puppet::Application::InterfaceBase def setup super - if interface.respond_to?(:indirection) - raise "Could not find data type #{type} for application #{self.class.name}" unless interface.indirection + if string.respond_to?(:indirection) + raise "Could not find data type #{type} for application #{self.class.name}" unless string.indirection - interface.set_terminus(terminus) if terminus + string.set_terminus(terminus) if terminus end end end diff --git a/lib/puppet/application/interface.rb b/lib/puppet/application/interface.rb deleted file mode 100644 index f447dc30d..000000000 --- a/lib/puppet/application/interface.rb +++ /dev/null @@ -1,95 +0,0 @@ -require 'puppet/application' -require 'puppet/interface' - -class Puppet::Application::Interface < Puppet::Application - - should_parse_config - run_mode :agent - - option("--debug", "-d") do |arg| - Puppet::Util::Log.level = :debug - end - - option("--verbose", "-v") do - Puppet::Util::Log.level = :info - end - - def list(*arguments) - if arguments.empty? - arguments = %w{terminuses actions} - end - interfaces.each do |name| - str = "#{name}:\n" - if arguments.include?("terminuses") - begin - terms = terminus_classes(name.to_sym) - str << "\tTerminuses: #{terms.join(", ")}\n" - rescue => detail - puts detail.backtrace if Puppet[:trace] - $stderr.puts "Could not load terminuses for #{name}: #{detail}" - end - end - - if arguments.include?("actions") - begin - actions = actions(name.to_sym) - str << "\tActions: #{actions.join(", ")}\n" - rescue => detail - puts detail.backtrace if Puppet[:trace] - $stderr.puts "Could not load actions for #{name}: #{detail}" - end - end - - print str - end - end - - attr_accessor :verb, :name, :arguments - - def main - # Call the method associated with the provided action (e.g., 'find'). - send(verb, *arguments) - end - - def setup - Puppet::Util::Log.newdestination :console - - load_applications # Call this to load all of the apps - - @verb, @arguments = command_line.args - @arguments ||= [] - - validate - end - - def validate - unless verb - raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" - end - - unless respond_to?(verb) - raise "Command '#{verb}' not found for 'interface'" - end - end - - def interfaces - Puppet::Interface.interfaces - end - - def terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort - end - - def actions(indirection) - return [] unless interface = Puppet::Interface[indirection, '0.0.1'] - interface.load_actions - return interface.actions.sort { |a,b| a.to_s <=> b.to_s } - end - - def load_applications - command_line.available_subcommands.each do |app| - command_line.require_application app - end - end -end - diff --git a/lib/puppet/application/interface_base.rb b/lib/puppet/application/interface_base.rb deleted file mode 100644 index 841f3ca12..000000000 --- a/lib/puppet/application/interface_base.rb +++ /dev/null @@ -1,97 +0,0 @@ -require 'puppet/application' -require 'puppet/interface' - -class Puppet::Application::InterfaceBase < Puppet::Application - should_parse_config - run_mode :agent - - def preinit - super - trap(:INT) do - $stderr.puts "Cancelling Interface" - exit(0) - end - end - - option("--debug", "-d") do |arg| - Puppet::Util::Log.level = :debug - end - - option("--verbose", "-v") do - Puppet::Util::Log.level = :info - end - - option("--format FORMAT") do |arg| - @format = arg.to_sym - end - - option("--mode RUNMODE", "-r") do |arg| - raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) - self.class.run_mode(arg.to_sym) - set_run_mode self.class.run_mode - end - - - attr_accessor :interface, :type, :verb, :arguments, :format - attr_writer :exit_code - - # This allows you to set the exit code if you don't want to just exit - # immediately but you need to indicate a failure. - def exit_code - @exit_code || 0 - end - - def main - # Call the method associated with the provided action (e.g., 'find'). - if result = interface.send(verb, *arguments) - puts render(result) - end - exit(exit_code) - end - - # Override this if you need custom rendering. - def render(result) - render_method = Puppet::Network::FormatHandler.format(format).render_method - if render_method == "to_pson" - jj result - exit(0) - else - result.send(render_method) - end - end - - def setup - Puppet::Util::Log.newdestination :console - - @verb = command_line.args.shift - @arguments = command_line.args - @arguments ||= [] - - @arguments = Array(@arguments) - - @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - - # TODO: These should be configurable versions. - unless Puppet::Interface.interface?(@type, :latest) - raise "Could not find any version of interface '#{@type}'" - end - @interface = Puppet::Interface[@type, :latest] - @format ||= @interface.default_format - - # We copy all of the app options to the interface. - # This allows each action to read in the options. - @interface.options = options - - validate - end - - def validate - unless verb - raise "You must specify #{interface.actions.join(", ")} as a verb; 'save' probably does not work right now" - end - - unless interface.action?(verb) - raise "Command '#{verb}' not found for #{type}" - end - end -end diff --git a/lib/puppet/application/string.rb b/lib/puppet/application/string.rb new file mode 100644 index 000000000..aa369e669 --- /dev/null +++ b/lib/puppet/application/string.rb @@ -0,0 +1,95 @@ +require 'puppet/application' +require 'puppet/string' + +class Puppet::Application::String < Puppet::Application + + should_parse_config + run_mode :agent + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + def list(*arguments) + if arguments.empty? + arguments = %w{terminuses actions} + end + strings.each do |name| + str = "#{name}:\n" + if arguments.include?("terminuses") + begin + terms = terminus_classes(name.to_sym) + str << "\tTerminuses: #{terms.join(", ")}\n" + rescue => detail + puts detail.backtrace if Puppet[:trace] + $stderr.puts "Could not load terminuses for #{name}: #{detail}" + end + end + + if arguments.include?("actions") + begin + actions = actions(name.to_sym) + str << "\tActions: #{actions.join(", ")}\n" + rescue => detail + puts detail.backtrace if Puppet[:trace] + $stderr.puts "Could not load actions for #{name}: #{detail}" + end + end + + print str + end + end + + attr_accessor :verb, :name, :arguments + + def main + # Call the method associated with the provided action (e.g., 'find'). + send(verb, *arguments) + end + + def setup + Puppet::Util::Log.newdestination :console + + load_applications # Call this to load all of the apps + + @verb, @arguments = command_line.args + @arguments ||= [] + + validate + end + + def validate + unless verb + raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" + end + + unless respond_to?(verb) + raise "Command '#{verb}' not found for 'string'" + end + end + + def strings + Puppet::String.strings + end + + def terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + end + + def actions(indirection) + return [] unless string = Puppet::String[indirection, '0.0.1'] + string.load_actions + return string.actions.sort { |a,b| a.to_s <=> b.to_s } + end + + def load_applications + command_line.available_subcommands.each do |app| + command_line.require_application app + end + end +end + diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb new file mode 100644 index 000000000..5b701597d --- /dev/null +++ b/lib/puppet/application/string_base.rb @@ -0,0 +1,97 @@ +require 'puppet/application' +require 'puppet/string' + +class Puppet::Application::StringBase < Puppet::Application + should_parse_config + run_mode :agent + + def preinit + super + trap(:INT) do + $stderr.puts "Cancelling String" + exit(0) + end + end + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + option("--format FORMAT") do |arg| + @format = arg.to_sym + end + + option("--mode RUNMODE", "-r") do |arg| + raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) + self.class.run_mode(arg.to_sym) + set_run_mode self.class.run_mode + end + + + attr_accessor :string, :type, :verb, :arguments, :format + attr_writer :exit_code + + # This allows you to set the exit code if you don't want to just exit + # immediately but you need to indicate a failure. + def exit_code + @exit_code || 0 + end + + def main + # Call the method associated with the provided action (e.g., 'find'). + if result = string.send(verb, *arguments) + puts render(result) + end + exit(exit_code) + end + + # Override this if you need custom rendering. + def render(result) + render_method = Puppet::Network::FormatHandler.format(format).render_method + if render_method == "to_pson" + jj result + exit(0) + else + result.send(render_method) + end + end + + def setup + Puppet::Util::Log.newdestination :console + + @verb = command_line.args.shift + @arguments = command_line.args + @arguments ||= [] + + @arguments = Array(@arguments) + + @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym + + # TODO: These should be configurable versions. + unless Puppet::String.string?(@type, :latest) + raise "Could not find any version of string '#{@type}'" + end + @string = Puppet::String[@type, :latest] + @format ||= @string.default_format + + # We copy all of the app options to the string. + # This allows each action to read in the options. + @string.options = options + + validate + end + + def validate + unless verb + raise "You must specify #{string.actions.join(", ")} as a verb; 'save' probably does not work right now" + end + + unless string.action?(verb) + raise "Command '#{verb}' not found for #{type}" + end + end +end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb deleted file mode 100644 index a667c6b75..000000000 --- a/lib/puppet/interface.rb +++ /dev/null @@ -1,98 +0,0 @@ -require 'puppet' -require 'puppet/util/autoload' - -class Puppet::Interface - require 'puppet/interface/action_manager' - require 'puppet/interface/interface_collection' - - include Puppet::Interface::ActionManager - extend Puppet::Interface::ActionManager - - include Puppet::Util - - class << self - # This is just so we can search for actions. We only use its - # list of directories to search. - # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb - def autoloader - @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") - end - - def interfaces - Puppet::Interface::InterfaceCollection.interfaces - end - - def interface?(name, version) - Puppet::Interface::InterfaceCollection.interface?(name, version) - end - - def register(instance) - Puppet::Interface::InterfaceCollection.register(instance) - end - - def define(name, version, &block) - if interface?(name, version) - interface = Puppet::Interface::InterfaceCollection[name, version] - else - interface = self.new(name, version) - Puppet::Interface::InterfaceCollection.register(interface) - interface.load_actions - end - - interface.instance_eval(&block) if block_given? - - return interface - end - - alias :[] :define - end - - attr_accessor :default_format - - def set_default_format(format) - self.default_format = format.to_sym - end - - attr_accessor :type, :verb, :version, :arguments, :options - attr_reader :name - - def initialize(name, version, &block) - unless Puppet::Interface::InterfaceCollection.validate_version(version) - raise ArgumentError, "Cannot create interface with invalid version number '#{version}'!" - end - - @name = Puppet::Interface::InterfaceCollection.underscorize(name) - @version = version - @default_format = :pson - - instance_eval(&block) if block_given? - end - - # Try to find actions defined in other files. - def load_actions - path = "puppet/interface/v#{version}/#{name}" - - loaded = [] - Puppet::Interface.autoloader.search_directories.each do |dir| - fdir = ::File.join(dir, path) - next unless FileTest.directory?(fdir) - - Dir.chdir(fdir) do - Dir.glob("*.rb").each do |file| - aname = file.sub(/\.rb/, '') - if loaded.include?(aname) - Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - next - end - loaded << aname - Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - require "#{path}/#{aname}" - end - end - end - end - - def to_s - "Puppet::Interface[#{name.inspect}, #{version.inspect}]" - end -end diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb deleted file mode 100644 index 1a5730d1b..000000000 --- a/lib/puppet/interface/action.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'puppet/interface' - -class Puppet::Interface::Action - attr_reader :name - - def initialize(interface, name, attrs = {}) - name = name.to_s - raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/ - - @interface = interface - @name = name - attrs.each do |k,v| send("#{k}=", v) end - end - - def invoke(*args, &block) - @interface.method(name).call(*args,&block) - end - - def invoke=(block) - if @interface.is_a?(Class) - @interface.define_method(@name, &block) - else - @interface.meta_def(@name, &block) - end - end -end diff --git a/lib/puppet/interface/action_builder.rb b/lib/puppet/interface/action_builder.rb deleted file mode 100644 index e389ea3ea..000000000 --- a/lib/puppet/interface/action_builder.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'puppet/interface' -require 'puppet/interface/action' - -class Puppet::Interface::ActionBuilder - attr_reader :action - - def self.build(interface, name, &block) - name = name.to_s - raise "Action '#{name}' must specify a block" unless block - builder = new(interface, name, &block) - builder.action - end - - def initialize(interface, name, &block) - @interface = interface - @action = Puppet::Interface::Action.new(interface, name) - instance_eval(&block) - end - - # Ideally the method we're defining here would be added to the action, and a - # method on the interface 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/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb deleted file mode 100644 index 8b2944bb1..000000000 --- a/lib/puppet/interface/action_manager.rb +++ /dev/null @@ -1,45 +0,0 @@ -require 'puppet/interface/action_builder' - -module Puppet::Interface::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::Interface::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::Interface::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/interface/indirector.rb b/lib/puppet/interface/indirector.rb deleted file mode 100644 index 485af4779..000000000 --- a/lib/puppet/interface/indirector.rb +++ /dev/null @@ -1,79 +0,0 @@ -require 'puppet' -require 'puppet/interface' - -class Puppet::Interface::Indirector < Puppet::Interface - 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 interface. - def set_indirection_name(name) - @indirection_name = name - end - - # Return an indirection associated with an interface, 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/interface/interface_collection.rb b/lib/puppet/interface/interface_collection.rb deleted file mode 100644 index 92e2933fe..000000000 --- a/lib/puppet/interface/interface_collection.rb +++ /dev/null @@ -1,98 +0,0 @@ -require 'puppet/interface' - -module Puppet::Interface::InterfaceCollection - SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ - - @interfaces = Hash.new { |hash, key| hash[key] = {} } - - def self.interfaces - unless @loaded - @loaded = true - $LOAD_PATH.each do |dir| - next unless FileTest.directory?(dir) - Dir.chdir(dir) do - Dir.glob("puppet/interface/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 @interfaces.keys - end - - def self.versions(name) - versions = [] - $LOAD_PATH.each do |dir| - next unless FileTest.directory?(dir) - v_dir = File.join dir, %w[puppet interface 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? - @interfaces[underscorize(name)][version] if interface?(name, version) - end - end - - def self.interface?(name, version) - version = versions(name).last if version == :latest - return false if version.nil? - - name = underscorize(name) - - unless @interfaces.has_key?(name) && @interfaces[name].has_key?(version) - require "puppet/interface/v#{version}/#{name}" - end - return @interfaces.has_key?(name) && @interfaces[name].has_key?(version) - rescue LoadError - return false - end - - def self.register(interface) - @interfaces[underscorize(interface.name)][interface.version] = interface - end - - def self.underscorize(name) - unless name.to_s =~ /^[-_a-z]+$/i then - raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid interface name" - end - - name.to_s.downcase.split(/[-_]/).join('_').to_sym - end -end diff --git a/lib/puppet/interface/v0.0.1/catalog.rb b/lib/puppet/interface/v0.0.1/catalog.rb deleted file mode 100644 index 7d61528bc..000000000 --- a/lib/puppet/interface/v0.0.1/catalog.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::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::Interface[: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/interface/v0.0.1/catalog/select.rb b/lib/puppet/interface/v0.0.1/catalog/select.rb deleted file mode 100644 index 35f1a1e0b..000000000 --- a/lib/puppet/interface/v0.0.1/catalog/select.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Select and show a list of resources of a given type. -Puppet::Interface.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/interface/v0.0.1/certificate.rb b/lib/puppet/interface/v0.0.1/certificate.rb deleted file mode 100644 index 2615e3d86..000000000 --- a/lib/puppet/interface/v0.0.1/certificate.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'puppet/interface/indirector' -require 'puppet/ssl/host' - -Puppet::Interface::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/interface/v0.0.1/certificate_request.rb b/lib/puppet/interface/v0.0.1/certificate_request.rb deleted file mode 100644 index e5ed1b51e..000000000 --- a/lib/puppet/interface/v0.0.1/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:certificate_request, '0.0.1') do -end diff --git a/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb b/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb deleted file mode 100644 index f6d8a3d6d..000000000 --- a/lib/puppet/interface/v0.0.1/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:certificate_revocation_list, '0.0.1') do -end diff --git a/lib/puppet/interface/v0.0.1/config.rb b/lib/puppet/interface/v0.0.1/config.rb deleted file mode 100644 index 7b74ce542..000000000 --- a/lib/puppet/interface/v0.0.1/config.rb +++ /dev/null @@ -1,11 +0,0 @@ -require 'puppet/interface' - -Puppet::Interface.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/interface/v0.0.1/configurer.rb b/lib/puppet/interface/v0.0.1/configurer.rb deleted file mode 100644 index 38536b684..000000000 --- a/lib/puppet/interface/v0.0.1/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/interface' - -Puppet::Interface.define(:configurer, '0.0.1') do - action(:synchronize) do - invoke do |certname| - facts = Puppet::Interface[:facts, '0.0.1'].find(certname) - catalog = Puppet::Interface[:catalog, '0.0.1'].download(certname, facts) - report = Puppet::Interface[:catalog, '0.0.1'].apply(catalog) - report - end - end -end diff --git a/lib/puppet/interface/v0.0.1/facts.rb b/lib/puppet/interface/v0.0.1/facts.rb deleted file mode 100644 index c4bbad845..000000000 --- a/lib/puppet/interface/v0.0.1/facts.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'puppet/interface/indirector' -require 'puppet/node/facts' - -Puppet::Interface::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/interface/v0.0.1/file.rb b/lib/puppet/interface/v0.0.1/file.rb deleted file mode 100644 index 91904e8e0..000000000 --- a/lib/puppet/interface/v0.0.1/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:file, '0.0.1') do - set_indirection_name :file_bucket_file -end diff --git a/lib/puppet/interface/v0.0.1/key.rb b/lib/puppet/interface/v0.0.1/key.rb deleted file mode 100644 index fbc9b67b1..000000000 --- a/lib/puppet/interface/v0.0.1/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:key, '0.0.1') do -end diff --git a/lib/puppet/interface/v0.0.1/node.rb b/lib/puppet/interface/v0.0.1/node.rb deleted file mode 100644 index 4ecec1478..000000000 --- a/lib/puppet/interface/v0.0.1/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:node, '0.0.1') do - set_default_format :yaml -end diff --git a/lib/puppet/interface/v0.0.1/report.rb b/lib/puppet/interface/v0.0.1/report.rb deleted file mode 100644 index bacb46e70..000000000 --- a/lib/puppet/interface/v0.0.1/report.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::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/interface/v0.0.1/resource.rb b/lib/puppet/interface/v0.0.1/resource.rb deleted file mode 100644 index 1a6f3b69d..000000000 --- a/lib/puppet/interface/v0.0.1/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:resource, '0.0.1') do -end diff --git a/lib/puppet/interface/v0.0.1/resource_type.rb b/lib/puppet/interface/v0.0.1/resource_type.rb deleted file mode 100644 index 6f5547c4d..000000000 --- a/lib/puppet/interface/v0.0.1/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:resource_type, '0.0.1') do -end diff --git a/lib/puppet/interface/v0.0.1/status.rb b/lib/puppet/interface/v0.0.1/status.rb deleted file mode 100644 index 7f4b56a2b..000000000 --- a/lib/puppet/interface/v0.0.1/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/interface/indirector' - -Puppet::Interface::Indirector.define(:status, '0.0.1') do -end diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb new file mode 100644 index 000000000..b5f7b9048 --- /dev/null +++ b/lib/puppet/string.rb @@ -0,0 +1,98 @@ +require 'puppet' +require 'puppet/util/autoload' + +class Puppet::String + require 'puppet/string/action_manager' + require 'puppet/string/string_collection' + + include Puppet::String::ActionManager + extend Puppet::String::ActionManager + + include Puppet::Util + + class << self + # This is just so we can search for actions. We only use its + # list of directories to search. + # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb + def autoloader + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/string") + end + + def strings + Puppet::String::StringCollection.strings + end + + def string?(name, version) + Puppet::String::StringCollection.string?(name, version) + end + + def register(instance) + Puppet::String::StringCollection.register(instance) + end + + def define(name, version, &block) + if string?(name, version) + string = Puppet::String::StringCollection[name, version] + else + string = self.new(name, version) + Puppet::String::StringCollection.register(string) + string.load_actions + end + + string.instance_eval(&block) if block_given? + + return string + end + + alias :[] :define + end + + attr_accessor :default_format + + def set_default_format(format) + self.default_format = format.to_sym + end + + attr_accessor :type, :verb, :version, :arguments, :options + attr_reader :name + + def initialize(name, version, &block) + unless Puppet::String::StringCollection.validate_version(version) + raise ArgumentError, "Cannot create string with invalid version number '#{version}'!" + end + + @name = Puppet::String::StringCollection.underscorize(name) + @version = version + @default_format = :pson + + instance_eval(&block) if block_given? + end + + # Try to find actions defined in other files. + def load_actions + path = "puppet/string/v#{version}/#{name}" + + loaded = [] + Puppet::String.autoloader.search_directories.each do |dir| + fdir = ::File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.chdir(fdir) do + Dir.glob("*.rb").each do |file| + aname = file.sub(/\.rb/, '') + if loaded.include?(aname) + Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + next + end + loaded << aname + Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + require "#{path}/#{aname}" + end + end + end + end + + def to_s + "Puppet::String[#{name.inspect}, #{version.inspect}]" + end +end 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 -- cgit From 4609e203fd47f8159118bb74a8308f9c6aee179f Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Fri, 25 Mar 2011 14:52:48 -0700 Subject: (#6770) Change versioning; adopt :current over :latest. As per discussion with Luke, versions of an interface are first looked up by requiring 'puppet/interface/{name}', and secondarily looked up by requiring '{name}@{version}/puppet/interface/{name}' if the first failed. A version of `:current` can be used to represent the version living in 'puppet/interface/{name}'. Paired-With: Nick Lewis --- lib/puppet/application/string_base.rb | 4 +- lib/puppet/string.rb | 30 +++++----- lib/puppet/string/catalog.rb | 40 +++++++++++++ lib/puppet/string/catalog/select.rb | 10 ++++ lib/puppet/string/certificate.rb | 28 +++++++++ lib/puppet/string/certificate_request.rb | 4 ++ lib/puppet/string/certificate_revocation_list.rb | 4 ++ lib/puppet/string/config.rb | 11 ++++ lib/puppet/string/configurer.rb | 12 ++++ lib/puppet/string/facts.rb | 18 ++++++ lib/puppet/string/file.rb | 5 ++ lib/puppet/string/key.rb | 4 ++ lib/puppet/string/node.rb | 5 ++ lib/puppet/string/report.rb | 15 +++++ lib/puppet/string/resource.rb | 4 ++ lib/puppet/string/resource_type.rb | 4 ++ lib/puppet/string/status.rb | 4 ++ lib/puppet/string/string_collection.rb | 66 ++++++++-------------- lib/puppet/string/v0.0.1/catalog.rb | 40 ------------- lib/puppet/string/v0.0.1/catalog/select.rb | 10 ---- lib/puppet/string/v0.0.1/certificate.rb | 28 --------- lib/puppet/string/v0.0.1/certificate_request.rb | 4 -- .../string/v0.0.1/certificate_revocation_list.rb | 4 -- lib/puppet/string/v0.0.1/config.rb | 11 ---- lib/puppet/string/v0.0.1/configurer.rb | 12 ---- lib/puppet/string/v0.0.1/facts.rb | 18 ------ lib/puppet/string/v0.0.1/file.rb | 5 -- lib/puppet/string/v0.0.1/key.rb | 4 -- lib/puppet/string/v0.0.1/node.rb | 5 -- lib/puppet/string/v0.0.1/report.rb | 15 ----- lib/puppet/string/v0.0.1/resource.rb | 4 -- lib/puppet/string/v0.0.1/resource_type.rb | 4 -- lib/puppet/string/v0.0.1/status.rb | 4 -- 33 files changed, 208 insertions(+), 228 deletions(-) create mode 100644 lib/puppet/string/catalog.rb create mode 100644 lib/puppet/string/catalog/select.rb create mode 100644 lib/puppet/string/certificate.rb create mode 100644 lib/puppet/string/certificate_request.rb create mode 100644 lib/puppet/string/certificate_revocation_list.rb create mode 100644 lib/puppet/string/config.rb create mode 100644 lib/puppet/string/configurer.rb create mode 100644 lib/puppet/string/facts.rb create mode 100644 lib/puppet/string/file.rb create mode 100644 lib/puppet/string/key.rb create mode 100644 lib/puppet/string/node.rb create mode 100644 lib/puppet/string/report.rb create mode 100644 lib/puppet/string/resource.rb create mode 100644 lib/puppet/string/resource_type.rb create mode 100644 lib/puppet/string/status.rb delete mode 100644 lib/puppet/string/v0.0.1/catalog.rb delete mode 100644 lib/puppet/string/v0.0.1/catalog/select.rb delete mode 100644 lib/puppet/string/v0.0.1/certificate.rb delete mode 100644 lib/puppet/string/v0.0.1/certificate_request.rb delete mode 100644 lib/puppet/string/v0.0.1/certificate_revocation_list.rb delete mode 100644 lib/puppet/string/v0.0.1/config.rb delete mode 100644 lib/puppet/string/v0.0.1/configurer.rb delete mode 100644 lib/puppet/string/v0.0.1/facts.rb delete mode 100644 lib/puppet/string/v0.0.1/file.rb delete mode 100644 lib/puppet/string/v0.0.1/key.rb delete mode 100644 lib/puppet/string/v0.0.1/node.rb delete mode 100644 lib/puppet/string/v0.0.1/report.rb delete mode 100644 lib/puppet/string/v0.0.1/resource.rb delete mode 100644 lib/puppet/string/v0.0.1/resource_type.rb delete mode 100644 lib/puppet/string/v0.0.1/status.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 5b701597d..bc627adde 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -72,10 +72,10 @@ class Puppet::Application::StringBase < Puppet::Application @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym # TODO: These should be configurable versions. - unless Puppet::String.string?(@type, :latest) + unless Puppet::String.string?(@type, :current) raise "Could not find any version of string '#{@type}'" end - @string = Puppet::String[@type, :latest] + @string = Puppet::String[@type, :current] @format ||= @string.default_format # We copy all of the app options to the string. diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb index b5f7b9048..9a223a40c 100644 --- a/lib/puppet/string.rb +++ b/lib/puppet/string.rb @@ -70,23 +70,25 @@ class Puppet::String # Try to find actions defined in other files. def load_actions - path = "puppet/string/v#{version}/#{name}" + path = "puppet/string/#{name}" loaded = [] - Puppet::String.autoloader.search_directories.each do |dir| - fdir = ::File.join(dir, path) - next unless FileTest.directory?(fdir) - - Dir.chdir(fdir) do - Dir.glob("*.rb").each do |file| - aname = file.sub(/\.rb/, '') - if loaded.include?(aname) - Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - next + [path, "#{name}@#{version}/#{path}"].each do |path| + Puppet::String.autoloader.search_directories.each do |dir| + fdir = ::File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.chdir(fdir) do + Dir.glob("*.rb").each do |file| + aname = file.sub(/\.rb/, '') + if loaded.include?(aname) + Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + next + end + loaded << aname + Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + require "#{path}/#{aname}" end - loaded << aname - Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - require "#{path}/#{aname}" end end end diff --git a/lib/puppet/string/catalog.rb b/lib/puppet/string/catalog.rb new file mode 100644 index 000000000..0ddd83176 --- /dev/null +++ b/lib/puppet/string/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/catalog/select.rb b/lib/puppet/string/catalog/select.rb new file mode 100644 index 000000000..52c77d3ce --- /dev/null +++ b/lib/puppet/string/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/certificate.rb b/lib/puppet/string/certificate.rb new file mode 100644 index 000000000..7b2e5f397 --- /dev/null +++ b/lib/puppet/string/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/certificate_request.rb b/lib/puppet/string/certificate_request.rb new file mode 100644 index 000000000..218b40b98 --- /dev/null +++ b/lib/puppet/string/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/certificate_revocation_list.rb b/lib/puppet/string/certificate_revocation_list.rb new file mode 100644 index 000000000..9731b4f2d --- /dev/null +++ b/lib/puppet/string/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/config.rb b/lib/puppet/string/config.rb new file mode 100644 index 000000000..ae1a408cf --- /dev/null +++ b/lib/puppet/string/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/configurer.rb b/lib/puppet/string/configurer.rb new file mode 100644 index 000000000..a6ea74b6a --- /dev/null +++ b/lib/puppet/string/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/facts.rb b/lib/puppet/string/facts.rb new file mode 100644 index 000000000..73acb0df6 --- /dev/null +++ b/lib/puppet/string/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/file.rb b/lib/puppet/string/file.rb new file mode 100644 index 000000000..cc5737f28 --- /dev/null +++ b/lib/puppet/string/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/key.rb b/lib/puppet/string/key.rb new file mode 100644 index 000000000..95aceade5 --- /dev/null +++ b/lib/puppet/string/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/node.rb b/lib/puppet/string/node.rb new file mode 100644 index 000000000..bc31a2cf3 --- /dev/null +++ b/lib/puppet/string/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/report.rb b/lib/puppet/string/report.rb new file mode 100644 index 000000000..55a008533 --- /dev/null +++ b/lib/puppet/string/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/resource.rb b/lib/puppet/string/resource.rb new file mode 100644 index 000000000..9838be0fa --- /dev/null +++ b/lib/puppet/string/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/resource_type.rb b/lib/puppet/string/resource_type.rb new file mode 100644 index 000000000..8ca31ea6c --- /dev/null +++ b/lib/puppet/string/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/status.rb b/lib/puppet/string/status.rb new file mode 100644 index 000000000..41de2bb99 --- /dev/null +++ b/lib/puppet/string/status.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:status, '0.0.1') do +end diff --git a/lib/puppet/string/string_collection.rb b/lib/puppet/string/string_collection.rb index e9cba7f55..45a192703 100644 --- a/lib/puppet/string/string_collection.rb +++ b/lib/puppet/string/string_collection.rb @@ -26,61 +26,39 @@ module Puppet::String::StringCollection 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 + @strings[underscorize(name)][version] if string?(name, version) end def self.string?(name, version) - version = versions(name).last if version == :latest - return false if version.nil? - name = underscorize(name) + cache = @strings[name] + return true if cache.has_key?(version) - unless @strings.has_key?(name) && @strings[name].has_key?(version) - require "puppet/string/v#{version}/#{name}" + loaded = cache.keys + + files = ["puppet/string/#{name}"] + unless version == :current + files << "#{name}@#{version}/puppet/string/#{name}" end - return @strings.has_key?(name) && @strings[name].has_key?(version) - rescue LoadError + + files.each do |file| + begin + require file + if version == :current || !file.include?('@') + loaded = (cache.keys - loaded).first + cache[:current] = cache[loaded] unless loaded.nil? + end + return true if cache.has_key?(version) + rescue LoadError + # pass + end + end + return false end diff --git a/lib/puppet/string/v0.0.1/catalog.rb b/lib/puppet/string/v0.0.1/catalog.rb deleted file mode 100644 index 0ddd83176..000000000 --- a/lib/puppet/string/v0.0.1/catalog.rb +++ /dev/null @@ -1,40 +0,0 @@ -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 deleted file mode 100644 index 52c77d3ce..000000000 --- a/lib/puppet/string/v0.0.1/catalog/select.rb +++ /dev/null @@ -1,10 +0,0 @@ -# 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 deleted file mode 100644 index 7b2e5f397..000000000 --- a/lib/puppet/string/v0.0.1/certificate.rb +++ /dev/null @@ -1,28 +0,0 @@ -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 deleted file mode 100644 index 218b40b98..000000000 --- a/lib/puppet/string/v0.0.1/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index 9731b4f2d..000000000 --- a/lib/puppet/string/v0.0.1/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index ae1a408cf..000000000 --- a/lib/puppet/string/v0.0.1/config.rb +++ /dev/null @@ -1,11 +0,0 @@ -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 deleted file mode 100644 index a6ea74b6a..000000000 --- a/lib/puppet/string/v0.0.1/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 index 73acb0df6..000000000 --- a/lib/puppet/string/v0.0.1/facts.rb +++ /dev/null @@ -1,18 +0,0 @@ -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 deleted file mode 100644 index cc5737f28..000000000 --- a/lib/puppet/string/v0.0.1/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 95aceade5..000000000 --- a/lib/puppet/string/v0.0.1/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index bc31a2cf3..000000000 --- a/lib/puppet/string/v0.0.1/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -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 deleted file mode 100644 index 55a008533..000000000 --- a/lib/puppet/string/v0.0.1/report.rb +++ /dev/null @@ -1,15 +0,0 @@ -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 deleted file mode 100644 index 9838be0fa..000000000 --- a/lib/puppet/string/v0.0.1/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index 8ca31ea6c..000000000 --- a/lib/puppet/string/v0.0.1/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -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 deleted file mode 100644 index 41de2bb99..000000000 --- a/lib/puppet/string/v0.0.1/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:status, '0.0.1') do -end -- cgit From f7f1e5822f3921336872956fe07c4da4406ce8eb Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Tue, 29 Mar 2011 13:29:01 -0700 Subject: (#6770) Fix Puppet::String#load_actions. Reviewed-By: Nick Lewis --- lib/puppet/string.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb index 9a223a40c..783b6afe0 100644 --- a/lib/puppet/string.rb +++ b/lib/puppet/string.rb @@ -87,7 +87,7 @@ class Puppet::String end loaded << aname Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - require "#{path}/#{aname}" + require "#{Dir.pwd}/#{aname}" end end end -- cgit From 505a48c0d316aad7ff26ae2c0ade294707ca081e Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Wed, 30 Mar 2011 15:27:59 -0700 Subject: (Maint) Bugfix for failing requires inside Puppet Strings. Paired-With: Matt Robinson --- lib/puppet/string/string_collection.rb | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/string_collection.rb b/lib/puppet/string/string_collection.rb index 45a192703..f8fa38b9c 100644 --- a/lib/puppet/string/string_collection.rb +++ b/lib/puppet/string/string_collection.rb @@ -41,20 +41,21 @@ module Puppet::String::StringCollection loaded = cache.keys - files = ["puppet/string/#{name}"] + module_names = ["puppet/string/#{name}"] unless version == :current - files << "#{name}@#{version}/puppet/string/#{name}" + module_names << "#{name}@#{version}/puppet/string/#{name}" end - files.each do |file| + module_names.each do |module_name| begin - require file - if version == :current || !file.include?('@') + require module_name + if version == :current || !module_name.include?('@') loaded = (cache.keys - loaded).first cache[:current] = cache[loaded] unless loaded.nil? end return true if cache.has_key?(version) - rescue LoadError + rescue LoadError => e + raise unless e.message =~ /-- #{module_name}$/ # pass end end -- cgit From a3f5f974251e14f02e8f83e12f4589581dd21828 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 29 Mar 2011 11:56:43 -0700 Subject: MAINT: fix error reporting when you set terminus incorrectly. Previously we tried to invoke a class method on an instance, and threw another exception, which wasn't the most helpful behaviour. This fixes that to correctly report the array of available terminus classes to the user. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/indirector.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index 15984e39e..48ec32680 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -62,7 +62,7 @@ class Puppet::String::Indirector < Puppet::String 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(", ") }" + raise "Could not set '#{indirection.name}' terminus to '#{from}' (#{detail}); valid terminus types are #{self.class.terminus_classes(indirection.name).join(", ") }" end end -- cgit From 05b434dca10bbc18d794358a9d08db89a46424f9 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 28 Mar 2011 21:37:05 -0700 Subject: (#6758) Pass options as an argument to string actions. Earlier in their implementation the String prototype would set global state on a String object to reflect options set on the command line. As we move strings away from a CLI-only prototype, this becomes troublesome because we can easily have, for example, HTTP access to a string, which means load balancers can really make this confusing. It also encourages global state pollution, where one invocation can adversely influence another. A better approach is that we pass options to the string action invocation directly; this makes the interaction stateless. Changes required to your code to adapt to the new world: - action(:foo) do |some, args| + action(:foo) do |some, args, options={}| if options[:whatever] then Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/string_base.rb | 13 +++++-------- lib/puppet/string.rb | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index bc627adde..762fbfda8 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -63,11 +63,12 @@ class Puppet::Application::StringBase < Puppet::Application def setup Puppet::Util::Log.newdestination :console + # We copy all of the app options to the end of the call; This allows each + # action to read in the options. This replaces the older model where we + # would invoke the action with options set as global state in the + # interface object. --daniel 2011-03-28 @verb = command_line.args.shift - @arguments = command_line.args - @arguments ||= [] - - @arguments = Array(@arguments) + @arguments = Array(command_line.args) << options @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym @@ -78,10 +79,6 @@ class Puppet::Application::StringBase < Puppet::Application @string = Puppet::String[@type, :current] @format ||= @string.default_format - # We copy all of the app options to the string. - # This allows each action to read in the options. - @string.options = options - validate end diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb index 783b6afe0..04db1f33b 100644 --- a/lib/puppet/string.rb +++ b/lib/puppet/string.rb @@ -53,7 +53,7 @@ class Puppet::String self.default_format = format.to_sym end - attr_accessor :type, :verb, :version, :arguments, :options + attr_accessor :type, :verb, :version, :arguments attr_reader :name def initialize(name, version, &block) -- cgit From 1400fec62e4e692badc5b68eb7d6d947997d7204 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 1 Apr 2011 13:10:42 -0700 Subject: MAINT: nicer to_s for actions, for user-focused rendering. This makes it possible for us to just print the Action object directly and get a human-focused output string. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/action.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index 4db9e97e2..5a7f3f203 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -3,6 +3,10 @@ require 'puppet/string' class Puppet::String::Action attr_reader :name + def to_s + "#{@string}##{@name}" + end + def initialize(string, name, attrs = {}) name = name.to_s raise "'#{name}' is an invalid action name" unless name =~ /^[a-z]\w*$/ -- cgit From 5bba1a26140cd3326739b00c2d60dff9321d4044 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 24 Mar 2011 13:10:27 -0700 Subject: (#6749) Implement support for options on strings and actions. We want to support both strings and actions specifying options, to support generic wrappers that present strings to the user across multiple distinct front-ends. At the moment we focus on implementation of a generic CLI providing full control to all the strings, but we aim to support other programmatic interfaces including Ruby and RPC invocation as part of the overall change. We also detect, at the time they are declared, duplicate options. They are reported, like any duplicate, with an error thrown. Specifically: It is illegal to declare a duplicate option in the same scope, such as within the same string, or within the same action. This is unchanged. It is illegal to declare an option in an action that duplicates an option in the string, or vice-versa. This is reported when the duplicate is declared, so may report on either the string or action depending on sequence. It remains legal to duplicate the same option across multiple actions, with different meanings. There is no conflict, as the same option can't be passed to both simultaneously. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string.rb | 8 +++++-- lib/puppet/string/action.rb | 32 ++++++++++++++++++++++---- lib/puppet/string/action_builder.rb | 11 +++++---- lib/puppet/string/action_manager.rb | 10 +++----- lib/puppet/string/option.rb | 24 +++++++++++++++++++ lib/puppet/string/option_builder.rb | 25 ++++++++++++++++++++ lib/puppet/string/option_manager.rb | 46 +++++++++++++++++++++++++++++++++++++ 7 files changed, 138 insertions(+), 18 deletions(-) create mode 100644 lib/puppet/string/option.rb create mode 100644 lib/puppet/string/option_builder.rb create mode 100644 lib/puppet/string/option_manager.rb (limited to 'lib/puppet') diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb index 04db1f33b..517cf4506 100644 --- a/lib/puppet/string.rb +++ b/lib/puppet/string.rb @@ -2,12 +2,16 @@ require 'puppet' require 'puppet/util/autoload' class Puppet::String - require 'puppet/string/action_manager' require 'puppet/string/string_collection' + require 'puppet/string/action_manager' include Puppet::String::ActionManager extend Puppet::String::ActionManager + require 'puppet/string/option_manager' + include Puppet::String::OptionManager + extend Puppet::String::OptionManager + include Puppet::Util class << self @@ -58,7 +62,7 @@ class Puppet::String def initialize(name, version, &block) unless Puppet::String::StringCollection.validate_version(version) - raise ArgumentError, "Cannot create string with invalid version number '#{version}'!" + raise ArgumentError, "Cannot create string #{name.inspect} with invalid version number '#{version}'!" end @name = Puppet::String::StringCollection.underscorize(name) diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index 5a7f3f203..4219aca0a 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -1,4 +1,5 @@ require 'puppet/string' +require 'puppet/string/option' class Puppet::String::Action attr_reader :name @@ -8,11 +9,10 @@ class Puppet::String::Action end 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 + raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ + @string = string + @name = name.to_sym + @options = {} attrs.each do |k,v| send("#{k}=", v) end end @@ -27,4 +27,26 @@ class Puppet::String::Action @string.meta_def(@name, &block) end end + + def add_option(option) + if option? option.name then + raise ArgumentError, "#{option.name} duplicates an existing option on #{self}" + elsif @string.option? option.name then + raise ArgumentError, "#{option.name} duplicates an existing option on #{@string}" + end + + @options[option.name] = option + end + + def option?(name) + @options.include? name.to_sym + end + + def options + (@options.keys + @string.options).sort + end + + def get_option(name) + @options[name.to_sym] || @string.get_option(name) + end end diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb index b3db51104..fb2a749ae 100644 --- a/lib/puppet/string/action_builder.rb +++ b/lib/puppet/string/action_builder.rb @@ -5,10 +5,8 @@ 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 + raise "Action #{name.inspect} must specify a block" unless block + new(string, name, &block).action end def initialize(string, name, &block) @@ -24,4 +22,9 @@ class Puppet::String::ActionBuilder raise "Invoke called on an ActionBuilder with no corresponding Action" unless @action @action.invoke = block end + + def option(name, attrs = {}, &block) + option = Puppet::String::OptionBuilder.build(@action, name, attrs, &block) + @action.add_option(option) + end end diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb index c29dbf454..c980142ce 100644 --- a/lib/puppet/string/action_manager.rb +++ b/lib/puppet/string/action_manager.rb @@ -5,20 +5,15 @@ module Puppet::String::ActionManager # 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 + @actions[action.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 @@ -36,7 +31,8 @@ module Puppet::String::ActionManager end def get_action(name) - @actions[name].dup + @actions ||= {} + @actions[name.to_sym] end def action?(name) diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb new file mode 100644 index 000000000..bdc3e07c5 --- /dev/null +++ b/lib/puppet/string/option.rb @@ -0,0 +1,24 @@ +class Puppet::String::Option + attr_reader :name, :string + + def initialize(string, name, attrs = {}) + raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ + @string = string + @name = name.to_sym + attrs.each do |k,v| send("#{k}=", v) end + end + + def to_s + @name.to_s.tr('_', '-') + end + + Types = [:boolean, :string] + def type + @type ||= :boolean + end + def type=(input) + value = begin input.to_sym rescue nil end + Types.include?(value) or raise ArgumentError, "#{input.inspect} is not a valid type" + @type = value + end +end diff --git a/lib/puppet/string/option_builder.rb b/lib/puppet/string/option_builder.rb new file mode 100644 index 000000000..2087cbc99 --- /dev/null +++ b/lib/puppet/string/option_builder.rb @@ -0,0 +1,25 @@ +require 'puppet/string/option' + +class Puppet::String::OptionBuilder + attr_reader :option + + def self.build(string, name, attrs = {}, &block) + new(string, name, attrs, &block).option + end + + private + def initialize(string, name, attrs, &block) + @string = string + @option = Puppet::String::Option.new(string, name, attrs) + block and instance_eval(&block) + @option + end + + # Metaprogram the simple DSL from the option class. + Puppet::String::Option.instance_methods.grep(/=$/).each do |setter| + next if setter =~ /^=/ # special case, darn it... + + dsl = setter.sub(/=$/, '') + define_method(dsl) do |value| @option.send(setter, value) end + end +end diff --git a/lib/puppet/string/option_manager.rb b/lib/puppet/string/option_manager.rb new file mode 100644 index 000000000..df3ae6b4b --- /dev/null +++ b/lib/puppet/string/option_manager.rb @@ -0,0 +1,46 @@ +require 'puppet/string/option_builder' + +module Puppet::String::OptionManager + # Declare that this app can take a specific option, and provide + # the code to do so. + def option(name, attrs = {}, &block) + @options ||= {} + raise ArgumentError, "Option #{name} already defined for #{self}" if option?(name) + actions.each do |action| + if get_action(action).option?(name) then + raise ArgumentError, "Option #{name} already defined on action #{action} for #{self}" + end + end + option = Puppet::String::OptionBuilder.build(self, name, &block) + @options[option.name] = option + end + + def options + @options ||= {} + result = @options.keys + + if self.is_a?(Class) and superclass.respond_to?(:options) + result += superclass.options + elsif self.class.respond_to?(:options) + result += self.class.options + end + result.sort + end + + def get_option(name) + @options ||= {} + result = @options[name.to_sym] + unless result then + if self.is_a?(Class) and superclass.respond_to?(:get_option) + result = superclass.get_option(name) + elsif self.class.respond_to?(:get_option) + result = self.class.get_option(name) + end + end + return result + end + + def option?(name) + options.include? name.to_sym + end +end -- cgit From a113e8f03d257375bf4eb2416a6ad7e1958d7868 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 29 Mar 2011 15:34:23 -0700 Subject: (#6749) implementing option handling in CLI string wrapper The purpose of this is to adapt the generic option support in our strings to the command line; we adapt the generic option information to optparse, and establish our environment early in the process to ensure that we can play nice with Puppet::Application for the moment. In the process we ensure that we detect, and report, conflicts in option naming across the board. Additionally, when an option is declared with multiple aliases, we insist that either all, or none, of them take an argument. To support this we support introspecting options having an optional argument, as well as documentation and all. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/indirection_base.rb | 5 +- lib/puppet/application/string_base.rb | 43 ++++++++++++++---- lib/puppet/string/action.rb | 16 +++++-- lib/puppet/string/action_builder.rb | 4 +- lib/puppet/string/indirector.rb | 6 +++ lib/puppet/string/option.rb | 73 ++++++++++++++++++++++++------ lib/puppet/string/option_builder.rb | 8 ++-- lib/puppet/string/option_manager.rb | 26 +++++++---- 8 files changed, 134 insertions(+), 47 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index da61f408d..61cfb435e 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -1,15 +1,12 @@ require 'puppet/application/string_base' class Puppet::Application::IndirectionBase < Puppet::Application::StringBase - option("--terminus TERMINUS") do |arg| - @terminus = arg - end - attr_accessor :terminus, :indirection def setup super + # REVISIT: need to implement this in terms of the string options, eh. if string.respond_to?(:indirection) raise "Could not find data type #{type} for application #{self.class.name}" unless string.indirection diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 762fbfda8..ffd49e8c0 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -60,6 +60,39 @@ class Puppet::Application::StringBase < Puppet::Application end end + def preinit + # We need to parse enough of the command line out early, to identify what + # the action is, so that we can obtain the full set of options to parse. + # + # This requires a partial parse first, and removing the options that we + # understood, then identification of the next item, then another round of + # the same until we have the string and action all set. --daniel 2011-03-29 + # + # NOTE: We can't use the Puppet::Application implementation of option + # parsing because it is (*ahem*) going to puts on $stderr and exit when it + # hits a parse problem, not actually let us reuse stuff. --daniel 2011-03-29 + + # TODO: These should be configurable versions, through a global + # '--version' option, but we don't implement that yet... --daniel 2011-03-29 + @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym + @string = Puppet::String[@type, :current] + @format = @string.default_format + + # Now, collect the global and string options and parse the command line. + begin + @string.options.inject OptionParser.new do |options, option| + option = @string.get_option option # turn it into the object, bleh + options.on(*option.to_optparse) do |value| + puts "REVISIT: do something with #{value.inspect}" + end + end.parse! command_line.args.dup + rescue OptionParser::InvalidOption => e + puts e.inspect # ...and ignore?? + end + + fail "REVISIT: Finish this code, eh..." + end + def setup Puppet::Util::Log.newdestination :console @@ -69,16 +102,6 @@ class Puppet::Application::StringBase < Puppet::Application # interface object. --daniel 2011-03-28 @verb = command_line.args.shift @arguments = Array(command_line.args) << options - - @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - - # TODO: These should be configurable versions. - unless Puppet::String.string?(@type, :current) - raise "Could not find any version of string '#{@type}'" - end - @string = Puppet::String[@type, :current] - @format ||= @string.default_format - validate end diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index 4219aca0a..692e467b4 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -29,13 +29,19 @@ class Puppet::String::Action end def add_option(option) - if option? option.name then - raise ArgumentError, "#{option.name} duplicates an existing option on #{self}" - elsif @string.option? option.name then - raise ArgumentError, "#{option.name} duplicates an existing option on #{@string}" + option.aliases.each do |name| + if conflict = get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" + elsif conflict = @string.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@string}" + end end - @options[option.name] = option + option.aliases.each do |name| + @options[name] = option + end + + option end def option?(name) diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb index fb2a749ae..e76044470 100644 --- a/lib/puppet/string/action_builder.rb +++ b/lib/puppet/string/action_builder.rb @@ -23,8 +23,8 @@ class Puppet::String::ActionBuilder @action.invoke = block end - def option(name, attrs = {}, &block) - option = Puppet::String::OptionBuilder.build(@action, name, attrs, &block) + def option(*declaration, &block) + option = Puppet::String::OptionBuilder.build(@action, *declaration, &block) @action.add_option(option) end end diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index 48ec32680..71b1f3b12 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -2,6 +2,12 @@ require 'puppet' require 'puppet/string' class Puppet::String::Indirector < Puppet::String + warn "REVISIT: Need to redefine this to take arguments again, eh." + option "--terminus TERMINUS" do + desc "REVISIT: You can select a terminus, which has some bigger effect +that we should describe in this file somehow." + end + def self.indirections Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort end diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb index bdc3e07c5..26b769c2e 100644 --- a/lib/puppet/string/option.rb +++ b/lib/puppet/string/option.rb @@ -1,24 +1,69 @@ class Puppet::String::Option - attr_reader :name, :string + attr_reader :string + attr_reader :name + attr_reader :aliases + attr_accessor :desc - def initialize(string, name, attrs = {}) - raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ - @string = string - @name = name.to_sym - attrs.each do |k,v| send("#{k}=", v) end + def takes_argument? + !!@argument + end + def optional_argument? + !!@optional_argument end + def initialize(string, *declaration, &block) + @string = string + @optparse = [] + + # Collect and sort the arguments in the declaration. + declaration.each do |item| + if item.is_a? String and item.to_s =~ /^-/ then + unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then + raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" + end + @optparse << item + else + raise ArgumentError, "#{item.inspect} is not valid for an option argument" + end + end + + if @optparse.empty? then + raise ArgumentError, "No option declarations found while building" + end + + # Now, infer the name from the options; we prefer the first long option as + # the name, rather than just the first option. + @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) + @aliases = @optparse.map { |o| optparse_to_name(o) } + + # Do we take an argument? If so, are we consistent about it, because + # incoherence here makes our life super-difficult, and we can more easily + # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 + @argument = @optparse.any? { |o| o =~ /[ =]/ } + if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then + raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" + end + + # Is our argument optional? The rules about consistency apply here, also, + # just like they do to taking arguments at all. --daniel 2011-03-30 + @optional_argument = @optparse.any? { |o| o.include? "[" } + if @optional_argument and not @optparse.all? { |o| o.include? "[" } then + raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" + end + end + + # to_s and optparse_to_name are roughly mirrored, because they are used to + # transform strings to name symbols, and vice-versa. def to_s @name.to_s.tr('_', '-') end - Types = [:boolean, :string] - def type - @type ||= :boolean - end - def type=(input) - value = begin input.to_sym rescue nil end - Types.include?(value) or raise ArgumentError, "#{input.inspect} is not a valid type" - @type = value + def optparse_to_name(declaration) + unless found = declaration.match(/^-+([^= ]+)/) or found.length != 1 then + raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" + end + name = found.captures.first.tr('-', '_') + raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ + name.to_sym end end diff --git a/lib/puppet/string/option_builder.rb b/lib/puppet/string/option_builder.rb index 2087cbc99..da0d213fb 100644 --- a/lib/puppet/string/option_builder.rb +++ b/lib/puppet/string/option_builder.rb @@ -3,14 +3,14 @@ require 'puppet/string/option' class Puppet::String::OptionBuilder attr_reader :option - def self.build(string, name, attrs = {}, &block) - new(string, name, attrs, &block).option + def self.build(string, *declaration, &block) + new(string, *declaration, &block).option end private - def initialize(string, name, attrs, &block) + def initialize(string, *declaration, &block) @string = string - @option = Puppet::String::Option.new(string, name, attrs) + @option = Puppet::String::Option.new(string, *declaration) block and instance_eval(&block) @option end diff --git a/lib/puppet/string/option_manager.rb b/lib/puppet/string/option_manager.rb index df3ae6b4b..f952ad4f0 100644 --- a/lib/puppet/string/option_manager.rb +++ b/lib/puppet/string/option_manager.rb @@ -3,16 +3,26 @@ require 'puppet/string/option_builder' module Puppet::String::OptionManager # Declare that this app can take a specific option, and provide # the code to do so. - def option(name, attrs = {}, &block) - @options ||= {} - raise ArgumentError, "Option #{name} already defined for #{self}" if option?(name) - actions.each do |action| - if get_action(action).option?(name) then - raise ArgumentError, "Option #{name} already defined on action #{action} for #{self}" + def option(*declaration, &block) + add_option Puppet::String::OptionBuilder.build(self, *declaration, &block) + end + + def add_option(option) + option.aliases.each do |name| + if conflict = get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" + end + + actions.each do |action| + action = get_action(action) + if conflict = action.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{action}" + end end end - option = Puppet::String::OptionBuilder.build(self, name, &block) - @options[option.name] = option + + option.aliases.each { |name| @options[name] = option } + option end def options -- cgit From 3bb614525f625a688baf8d67c5a580f8a51f4cad Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 30 Mar 2011 16:56:08 -0700 Subject: (#6749) fix an inheritance bug in ActionManager When we wrote class inheritance of actions for strings we didn't implement method (ahem, action) lookup correctly. This changes that, by providing the implementation to our standards, along with appropriate tests. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/action_manager.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb index c980142ce..7d22a0c52 100644 --- a/lib/puppet/string/action_manager.rb +++ b/lib/puppet/string/action_manager.rb @@ -32,7 +32,15 @@ module Puppet::String::ActionManager def get_action(name) @actions ||= {} - @actions[name.to_sym] + result = @actions[name.to_sym] + if result.nil? + if self.is_a?(Class) and superclass.respond_to?(:get_action) + result = superclass.get_action(name) + elsif self.class.respond_to?(:get_action) + result = self.class.get_action(name) + end + end + return result end def action?(name) -- cgit From 512778f95058a423a3d2e08d1803eb4a90fb975a Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 30 Mar 2011 16:56:40 -0700 Subject: (#6749) detect duplicate aliases in a single option statement. This ensures that an option declaration that shadows itself is found, and reported to the user, rather than silently eating one of the two. This could have actually lost, for example, the distinction between an argument-requiring and an argument-missing variant of the same thing. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/option.rb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb index 26b769c2e..70d62a01f 100644 --- a/lib/puppet/string/option.rb +++ b/lib/puppet/string/option.rb @@ -1,5 +1,5 @@ class Puppet::String::Option - attr_reader :string + attr_reader :parent attr_reader :name attr_reader :aliases attr_accessor :desc @@ -11,17 +11,26 @@ class Puppet::String::Option !!@optional_argument end - def initialize(string, *declaration, &block) - @string = string + def initialize(parent, *declaration, &block) + @parent = parent @optparse = [] # Collect and sort the arguments in the declaration. + dups = {} declaration.each do |item| if item.is_a? String and item.to_s =~ /^-/ then unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" end @optparse << item + + # Duplicate checking... + name = optparse_to_name(item) + if dup = dups[name] then + raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" + else + dups[name] = item + end else raise ArgumentError, "#{item.inspect} is not valid for an option argument" end -- cgit From 423fe1f6b7c5bc0ca9b53a87f636668514802ad7 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 30 Mar 2011 16:58:17 -0700 Subject: (#6749) string cli base: implement preinit CLI parsing In order to identify the full set of options we need to know the action that is being invoked; that actually requires a pre-processing step to identify that out of the global options. Notably, our spec is that options can be to the right of their declaration point, but not to the left: that means that we can now extract the full set of options, and interact with the standard Puppet option handling code, resulting in at least vaguely saner behaviour... Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/string_base.rb | 90 +++++++++++++++++++---------------- lib/puppet/string/option.rb | 1 + 2 files changed, 50 insertions(+), 41 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index ffd49e8c0..1169a45a4 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -5,14 +5,6 @@ class Puppet::Application::StringBase < Puppet::Application should_parse_config run_mode :agent - def preinit - super - trap(:INT) do - $stderr.puts "Cancelling String" - exit(0) - end - end - option("--debug", "-d") do |arg| Puppet::Util::Log.level = :debug end @@ -32,7 +24,7 @@ class Puppet::Application::StringBase < Puppet::Application end - attr_accessor :string, :type, :verb, :arguments, :format + attr_accessor :string, :action, :type, :arguments, :format attr_writer :exit_code # This allows you to set the exit code if you don't want to just exit @@ -41,14 +33,6 @@ class Puppet::Application::StringBase < Puppet::Application @exit_code || 0 end - def main - # Call the method associated with the provided action (e.g., 'find'). - if result = string.send(verb, *arguments) - puts render(result) - end - exit(exit_code) - end - # Override this if you need custom rendering. def render(result) render_method = Puppet::Network::FormatHandler.format(format).render_method @@ -61,16 +45,14 @@ class Puppet::Application::StringBase < Puppet::Application end def preinit + super + trap(:INT) do + $stderr.puts "Cancelling String" + exit(0) + end + # We need to parse enough of the command line out early, to identify what # the action is, so that we can obtain the full set of options to parse. - # - # This requires a partial parse first, and removing the options that we - # understood, then identification of the next item, then another round of - # the same until we have the string and action all set. --daniel 2011-03-29 - # - # NOTE: We can't use the Puppet::Application implementation of option - # parsing because it is (*ahem*) going to puts on $stderr and exit when it - # hits a parse problem, not actually let us reuse stuff. --daniel 2011-03-29 # TODO: These should be configurable versions, through a global # '--version' option, but we don't implement that yet... --daniel 2011-03-29 @@ -78,19 +60,42 @@ class Puppet::Application::StringBase < Puppet::Application @string = Puppet::String[@type, :current] @format = @string.default_format - # Now, collect the global and string options and parse the command line. - begin - @string.options.inject OptionParser.new do |options, option| - option = @string.get_option option # turn it into the object, bleh - options.on(*option.to_optparse) do |value| - puts "REVISIT: do something with #{value.inspect}" + # Now, walk the command line and identify the action. We skip over + # arguments based on introspecting the action and all, and find the first + # non-option word to use as the action. + action = nil + cli = command_line.args.dup # we destroy this copy, but... + while @action.nil? and not cli.empty? do + item = cli.shift + if item =~ /^-/ then + option = @string.options.find { |a| item =~ /^-+#{a}\b/ } + if option then + if @string.get_option(option).takes_argument? then + # We don't validate if the argument is optional or mandatory, + # because it doesn't matter here. We just assume that errors will + # be caught later. --daniel 2011-03-30 + cli.shift unless cli.first =~ /^-/ + end + else + raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" end - end.parse! command_line.args.dup - rescue OptionParser::InvalidOption => e - puts e.inspect # ...and ignore?? + else + action = @string.get_action(item.to_sym) + if action.nil? then + raise ArgumentError, "#{@string} does not have an #{item.inspect} action!" + end + @action = action + end end - fail "REVISIT: Finish this code, eh..." + @action or raise ArgumentError, "No action given on the command line!" + + # Finally, we can interact with the default option code to build behaviour + # around the full set of options we now know we support. + @action.options.each do |option| + option = @action.get_option(option) # make it the object. + self.class.option(*option.optparse) # ...and make the CLI parse it. + end end def setup @@ -100,18 +105,21 @@ class Puppet::Application::StringBase < Puppet::Application # action to read in the options. This replaces the older model where we # would invoke the action with options set as global state in the # interface object. --daniel 2011-03-28 - @verb = command_line.args.shift @arguments = Array(command_line.args) << options validate end + + def main + # Call the method associated with the provided action (e.g., 'find'). + if result = @string.send(@action.name, *arguments) + puts render(result) + end + exit(exit_code) + end def validate - unless verb + unless @action raise "You must specify #{string.actions.join(", ")} as a verb; 'save' probably does not work right now" end - - unless string.action?(verb) - raise "Command '#{verb}' not found for #{type}" - end end end diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb index 70d62a01f..e7b6f187c 100644 --- a/lib/puppet/string/option.rb +++ b/lib/puppet/string/option.rb @@ -2,6 +2,7 @@ class Puppet::String::Option attr_reader :parent attr_reader :name attr_reader :aliases + attr_reader :optparse attr_accessor :desc def takes_argument? -- cgit From 1635454755fa8fdc0dedf032c543d3f4006aa568 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 31 Mar 2011 10:45:33 -0700 Subject: (#6749) Remove "save does not work" language from strings. Now we are pushing into production we can eliminate this language, which was a legacy from the prototype that is no longer relevant globally. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/string_base.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 1169a45a4..09e42a5ef 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -119,7 +119,7 @@ class Puppet::Application::StringBase < Puppet::Application end def validate unless @action - raise "You must specify #{string.actions.join(", ")} as a verb; 'save' probably does not work right now" + raise "You must specify #{string.actions.join(", ")} as a verb" end end end -- cgit From c52261c7aa86e7e75f215ba0f6b8c140003c4ead Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 31 Mar 2011 13:36:19 -0700 Subject: (#6749) disable Action#invoke for this release. So, we have Action#invoke, but it binds to the declaring class, not to the correct instance. Solving all the subtle issues around threads, global state, and bindings without causing us too much pain is actually pretty hard, so instead we pull the feature. It can be enabled again in a future release and, being a strict extension feature, we can do that without overly hurting anyone. We still have full access to the invocation through a marginally less pleasant syntax, but one that people MUST be able to arrange to allow invoke to work, so on that front we are clean. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/action.rb | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index 692e467b4..9e82f4d5d 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'puppet/string' require 'puppet/string/option' @@ -16,9 +17,39 @@ class Puppet::String::Action attrs.each do |k,v| send("#{k}=", v) end end - def invoke(*args, &block) - @string.method(name).call(*args,&block) - end + # Initially, this was defined to allow the @action.invoke pattern, which is + # a very natural way to invoke behaviour given our introspection + # capabilities. Heck, our initial plan was to have the string delegate to + # the action object for invocation and all. + # + # It turns out that we have a binding problem to solve: @string was bound to + # the parent class, not the subclass instance, and we don't pass the + # appropriate context or change the binding enough to make this work. + # + # We could hack around it, by either mandating that you pass the context in + # to invoke, or try to get the binding right, but that has probably got + # subtleties that we don't instantly think of – especially around threads. + # + # So, we are pulling this method for now, and will return it to life when we + # have the time to resolve the problem. For now, you should replace... + # + # @action = @string.get_action(name) + # @action.invoke(arg1, arg2, arg3) + # + # ...with... + # + # @action = @string.get_action(name) + # @string.send(@action.name, arg1, arg2, arg3) + # + # I understand that is somewhat cumbersome, but it functions as desired. + # --daniel 2011-03-31 + # + # PS: This code is left present, but commented, to support this chunk of + # documentation, for the benefit of the reader. + # + # def invoke(*args, &block) + # @string.send(name, *args, &block) + # end def invoke=(block) if @string.is_a?(Class) -- cgit From 3d88808270e9a0cb848a66825c66676598559dc3 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 31 Mar 2011 16:46:43 -0700 Subject: (#6749) base indirector string should fail on invalid terminus. We used to generate an info-level message, then carry on, which typically resulted in raising because 'nil' doesn't implement the expected method that we immediately try to call. So, instead, raise a clear error at the time we fail to load, which gives a pleasant rather than confusing error to the user. Which at least means they know why things have gone wrong... Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/indirector.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index 71b1f3b12..0f5f405ff 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -59,7 +59,8 @@ that we should describe in this file somehow." # One usually does. def indirection unless @indirection - Puppet.info("Could not find terminus for #{indirection_name}") unless @indirection = Puppet::Indirector::Indirection.instance(indirection_name) + @indirection = Puppet::Indirector::Indirection.instance(indirection_name) + @indirection or raise "Could not find terminus for #{indirection_name}" end @indirection end -- cgit From 8723b1c2102a181d23c9fe4ede7d58294f7c18ba Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 31 Mar 2011 16:48:50 -0700 Subject: (#6749) code and test cleanup of Application/StringBase. This removes dead code now we have terminus in the base string, and disables some tests on StringBase app until they can be rewritten. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/indirection_base.rb | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index 61cfb435e..cfa1ea529 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -1,16 +1,4 @@ require 'puppet/application/string_base' class Puppet::Application::IndirectionBase < Puppet::Application::StringBase - attr_accessor :terminus, :indirection - - def setup - super - - # REVISIT: need to implement this in terms of the string options, eh. - if string.respond_to?(:indirection) - raise "Could not find data type #{type} for application #{self.class.name}" unless string.indirection - - string.set_terminus(terminus) if terminus - end - end end -- cgit From eb4c4fbdc3951c220a76ec01abc33a7654d89e53 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 1 Apr 2011 10:44:35 -0700 Subject: (#6749) Start porting existing strings to the options API. This provides a solid test of the new code, by migrating the existing strings to match. This also gives us a chance to determine any weak points in the code as written. Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/configurer.rb | 4 ++-- lib/puppet/application/string.rb | 2 +- lib/puppet/string/action.rb | 2 +- lib/puppet/string/catalog.rb | 4 ++-- lib/puppet/string/catalog/select.rb | 2 +- lib/puppet/string/certificate.rb | 6 +++--- lib/puppet/string/config.rb | 1 + lib/puppet/string/configurer.rb | 2 +- lib/puppet/string/facts.rb | 2 +- lib/puppet/string/report.rb | 2 +- 10 files changed, 14 insertions(+), 13 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index b440098ee..be018338f 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -5,8 +5,8 @@ class Puppet::Application::Configurer < Puppet::Application should_parse_config run_mode :agent - option("--debug","-d") - option("--verbose","-v") + option("--debug", "-d") + option("--verbose", "-v") def setup if options[:debug] or options[:verbose] diff --git a/lib/puppet/application/string.rb b/lib/puppet/application/string.rb index aa369e669..0a6a798ce 100644 --- a/lib/puppet/application/string.rb +++ b/lib/puppet/application/string.rb @@ -83,7 +83,7 @@ class Puppet::Application::String < Puppet::Application def actions(indirection) return [] unless string = Puppet::String[indirection, '0.0.1'] string.load_actions - return string.actions.sort { |a,b| a.to_s <=> b.to_s } + return string.actions.sort { |a, b| a.to_s <=> b.to_s } end def load_applications diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index 9e82f4d5d..ff419c090 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -14,7 +14,7 @@ class Puppet::String::Action @string = string @name = name.to_sym @options = {} - attrs.each do |k,v| send("#{k}=", v) end + attrs.each do |k, v| send("#{k}=", v) end end # Initially, this was defined to allow the @action.invoke pattern, which is diff --git a/lib/puppet/string/catalog.rb b/lib/puppet/string/catalog.rb index 0ddd83176..c6de47708 100644 --- a/lib/puppet/string/catalog.rb +++ b/lib/puppet/string/catalog.rb @@ -2,7 +2,7 @@ require 'puppet/string/indirector' Puppet::String::Indirector.define(:catalog, '0.0.1') do action(:apply) do - invoke do |catalog| + invoke do |catalog, options| report = Puppet::Transaction::Report.new("apply") report.configuration_version = catalog.version @@ -23,7 +23,7 @@ Puppet::String::Indirector.define(:catalog, '0.0.1') do end action(:download) do - invoke do |certname,facts| + invoke do |certname, facts, options| Puppet::Resource::Catalog.terminus_class = :rest facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} catalog = nil diff --git a/lib/puppet/string/catalog/select.rb b/lib/puppet/string/catalog/select.rb index 52c77d3ce..a8f4480cd 100644 --- a/lib/puppet/string/catalog/select.rb +++ b/lib/puppet/string/catalog/select.rb @@ -1,7 +1,7 @@ # 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| + invoke do |host, type, options| catalog = Puppet::Resource::Catalog.indirection.find(host) catalog.resources.reject { |res| res.type != type }.each { |res| puts res } diff --git a/lib/puppet/string/certificate.rb b/lib/puppet/string/certificate.rb index 7b2e5f397..53f731e81 100644 --- a/lib/puppet/string/certificate.rb +++ b/lib/puppet/string/certificate.rb @@ -4,7 +4,7 @@ require 'puppet/ssl/host' Puppet::String::Indirector.define(:certificate, '0.0.1') do action :generate do - invoke do |name| + invoke do |name, options| host = Puppet::SSL::Host.new(name) host.generate_certificate_request host.certificate_request.class.indirection.save(host.certificate_request) @@ -12,7 +12,7 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do end action :list do - invoke do + invoke do |options| Puppet::SSL::Host.indirection.search("*", { :for => :certificate_request, }).map { |h| h.inspect } @@ -20,7 +20,7 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do end action :sign do - invoke do |name| + invoke do |name, options| Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) end end diff --git a/lib/puppet/string/config.rb b/lib/puppet/string/config.rb index ae1a408cf..49a1688fc 100644 --- a/lib/puppet/string/config.rb +++ b/lib/puppet/string/config.rb @@ -3,6 +3,7 @@ require 'puppet/string' Puppet::String.define(:config, '0.0.1') do action(:print) do invoke do |*args| + options = args.pop Puppet.settings[:configprint] = args.join(",") Puppet.settings.print_config_options nil diff --git a/lib/puppet/string/configurer.rb b/lib/puppet/string/configurer.rb index a6ea74b6a..2520d4188 100644 --- a/lib/puppet/string/configurer.rb +++ b/lib/puppet/string/configurer.rb @@ -2,7 +2,7 @@ require 'puppet/string' Puppet::String.define(:configurer, '0.0.1') do action(:synchronize) do - invoke do |certname| + invoke do |certname, options| 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) diff --git a/lib/puppet/string/facts.rb b/lib/puppet/string/facts.rb index 73acb0df6..31298813b 100644 --- a/lib/puppet/string/facts.rb +++ b/lib/puppet/string/facts.rb @@ -6,7 +6,7 @@ Puppet::String::Indirector.define(:facts, '0.0.1') do # Upload our facts to the server action(:upload) do - invoke do |*args| + invoke do |options| Puppet::Node::Facts.indirection.terminus_class = :facter facts = Puppet::Node::Facts.indirection.find(Puppet[:certname]) Puppet::Node::Facts.indirection.terminus_class = :rest diff --git a/lib/puppet/string/report.rb b/lib/puppet/string/report.rb index 55a008533..5b617e49e 100644 --- a/lib/puppet/string/report.rb +++ b/lib/puppet/string/report.rb @@ -2,7 +2,7 @@ require 'puppet/string/indirector' Puppet::String::Indirector.define(:report, '0.0.1') do action(:submit) do - invoke do |report| + invoke do |report, options| begin Puppet::Transaction::Report.terminus_class = :rest report.save -- cgit From 4d23d60fc331220418d4502930bd2fad7ee44b84 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 1 Apr 2011 10:48:07 -0700 Subject: (#6749) add a shim around the action implementation. To present a pleasant Ruby API to folks invoking actions we want to have default values for the trailing 'options' argument, and to be able to pass a block to the code to allow yield to work. Given limitations of Ruby 1.8 regarding blocks, we can't use either of those because the block slot is bound at declaration time, and you can't give optional arguments. To work around this we inject, using eval, a full regular Ruby method into the final block of code. This can provide the default argument at the end in an intelligent way (albeit by emulating what the interpreter would do). This doesn't solve the yield problem, but the same method can pass the block explicitly, and allows other hooks to be injected, which makes it easier to do smarter things in future... Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/action.rb | 36 ++++++++++++++++++++++++++++++++++-- lib/puppet/string/indirector.rb | 2 +- 2 files changed, 35 insertions(+), 3 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index ff419c090..ee3b2991b 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -52,10 +52,42 @@ class Puppet::String::Action # end def invoke=(block) + # We need to build an instance method as a wrapper, using normal code, to + # be able to expose argument defaulting between the caller and definer in + # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. + # + # In future this also gives us a place to hook in additional behaviour + # such as calling out to the action instance to validate and coerce + # parameters, which avoids any exciting context switching and all. + # + # Hopefully we can improve this when we finally shuffle off the last of + # Ruby 1.8 support, but that looks to be a few "enterprise" release eras + # away, so we are pretty stuck with this for now. + # + # Patches to make this work more nicely with Ruby 1.9 using runtime + # version checking and all are welcome, but they can't actually help if + # the results are not totally hidden away in here. + # + # Incidentally, we though about vendoring evil-ruby and actually adjusting + # the internal C structure implementation details under the hood to make + # this stuff work, because it would have been cleaner. Which gives you an + # idea how motivated we were to make this cleaner. Sorry. --daniel 2011-03-31 + + internal_name = "#{@name} implementation, required on Ruby 1.8".to_sym + file = __FILE__ + "+eval" + line = __LINE__ + 1 + wrapper = "def #{@name}(*args, &block) + args << {} unless args.last.is_a? Hash + args << block if block_given? + self.__send__(#{internal_name.inspect}, *args) + end" + if @string.is_a?(Class) - @string.define_method(@name, &block) + @string.class_eval do eval wrapper, nil, file, line end + @string.define_method(internal_name, &block) else - @string.meta_def(@name, &block) + @string.instance_eval do eval wrapper, nil, file, line end + @string.meta_def(internal_name, &block) end end diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index 0f5f405ff..48280cc77 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -75,7 +75,7 @@ that we should describe in this file somehow." def call_indirection_method(method, *args) begin - result = indirection.send(method, *args) + result = indirection.__send__(method, *args) rescue => detail puts detail.backtrace if Puppet[:trace] raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" -- cgit From d328af73e688df136ee6fe10340adf7ba72b951e Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 1 Apr 2011 12:46:12 -0700 Subject: (#6760) set terminus in indirector string base class. We now accept a terminus option to each invocation, and set the terminus based on that call. This is probably incomplete, because it only sets the terminus when given, and doesn't try to reset it to the default afterwards. This also resets the terminus class after every invocation, to stop it leaking state across calls. This make, sadly, have some effects if you are not just using the strings to invoke the terminus, but it beats having the strings broken as well... Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/indirector.rb | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index 48280cc77..bb081533f 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -2,7 +2,6 @@ require 'puppet' require 'puppet/string' class Puppet::String::Indirector < Puppet::String - warn "REVISIT: Need to redefine this to take arguments again, eh." option "--terminus TERMINUS" do desc "REVISIT: You can select a terminus, which has some bigger effect that we should describe in this file somehow." @@ -16,6 +15,21 @@ that we should describe in this file somehow." Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort end + def call_indirection_method(method, *args) + options = args.pop + options.has_key?(:terminus) and set_terminus(options[:terminus]) + + begin + result = indirection.__send__(method, *args) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" + end + + indirection.reset_terminus_class + return result + end + action :destroy do invoke { |*args| call_indirection_method(:destroy, *args) } end @@ -35,11 +49,16 @@ that we should describe in this file somehow." # Print the configuration for the current terminus class action :info do invoke do |*args| + options = args.pop + options.has_key?(:terminus) and set_terminus(options[:terminus]) + 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 + + indirection.reset_terminus_class end end @@ -72,15 +91,4 @@ that we should describe in this file somehow." raise "Could not set '#{indirection.name}' terminus to '#{from}' (#{detail}); valid terminus types are #{self.class.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 -- cgit From 8b37d7038c89bd830b076e838686419ff0068b56 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Fri, 1 Apr 2011 15:16:55 -0700 Subject: (#6749) Polish the CLI option pre-parse implementation This improves handling of the pre-parse of the command line to be non-destructive, which cuts down the volume of garbage generated in the process. It also improves testing to verify that we get the darn thing right... Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/string_base.rb | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 09e42a5ef..6032e32f8 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -64,9 +64,9 @@ class Puppet::Application::StringBase < Puppet::Application # arguments based on introspecting the action and all, and find the first # non-option word to use as the action. action = nil - cli = command_line.args.dup # we destroy this copy, but... - while @action.nil? and not cli.empty? do - item = cli.shift + index = -1 + while (index += 1) < command_line.args.length do + item = command_line.args[index] if item =~ /^-/ then option = @string.options.find { |a| item =~ /^-+#{a}\b/ } if option then @@ -74,7 +74,7 @@ class Puppet::Application::StringBase < Puppet::Application # We don't validate if the argument is optional or mandatory, # because it doesn't matter here. We just assume that errors will # be caught later. --daniel 2011-03-30 - cli.shift unless cli.first =~ /^-/ + index += 1 unless command_line.args[index + 1] =~ /^-/ end else raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" @@ -85,6 +85,7 @@ class Puppet::Application::StringBase < Puppet::Application raise ArgumentError, "#{@string} does not have an #{item.inspect} action!" end @action = action + command_line.args.delete_at(index) end end @@ -105,8 +106,8 @@ class Puppet::Application::StringBase < Puppet::Application # action to read in the options. This replaces the older model where we # would invoke the action with options set as global state in the # interface object. --daniel 2011-03-28 - @arguments = Array(command_line.args) << options - validate + @arguments = command_line.args + @arguments << options end @@ -117,9 +118,4 @@ class Puppet::Application::StringBase < Puppet::Application end exit(exit_code) end - def validate - unless @action - raise "You must specify #{string.actions.join(", ")} as a verb" - end - end end -- cgit From 5a0b547f3289cb8e13b197d021322e03d05bee8e Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 4 Apr 2011 11:04:17 -0700 Subject: (#6749) Fix optional vs mandatory argument handling. optparse will treat '--foo --bar' as "foo with the argument --bar" when foo takes a mandatory argument. We need to emulate that behaviour in our pre-parse of the command line. Incidentally, fix up a bug in boolean options, and improve our testing. Reviewed-By: Nick Lewis --- lib/puppet/application/string_base.rb | 11 +++++------ lib/puppet/string/option.rb | 5 +++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 6032e32f8..a082ba0e2 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -65,16 +65,15 @@ class Puppet::Application::StringBase < Puppet::Application # non-option word to use as the action. action = nil index = -1 - while (index += 1) < command_line.args.length do + until @action or (index += 1) >= command_line.args.length do item = command_line.args[index] if item =~ /^-/ then option = @string.options.find { |a| item =~ /^-+#{a}\b/ } if option then - if @string.get_option(option).takes_argument? then - # We don't validate if the argument is optional or mandatory, - # because it doesn't matter here. We just assume that errors will - # be caught later. --daniel 2011-03-30 - index += 1 unless command_line.args[index + 1] =~ /^-/ + option = @string.get_option(option) + if option.takes_argument? then + index += 1 unless + (option.optional_argument? and command_line.args[index + 1] =~ /^-/) end else raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb index e7b6f187c..f499e4b95 100644 --- a/lib/puppet/string/option.rb +++ b/lib/puppet/string/option.rb @@ -63,7 +63,8 @@ class Puppet::String::Option end # to_s and optparse_to_name are roughly mirrored, because they are used to - # transform strings to name symbols, and vice-versa. + # transform strings to name symbols, and vice-versa. This isn't a full + # bidirectional transformation though. def to_s @name.to_s.tr('_', '-') end @@ -72,7 +73,7 @@ class Puppet::String::Option unless found = declaration.match(/^-+([^= ]+)/) or found.length != 1 then raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" end - name = found.captures.first.tr('-', '_') + name = found.captures.first.sub('[no-]', '').tr('-', '_') raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ name.to_sym end -- cgit From cec3b6e2627ea2340e46c2e498f4d41522140094 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 4 Apr 2011 11:19:26 -0700 Subject: (#6749) Extract the action from the arguments cleanly. This adds a test to verify that we are correctly removing the action name from the set of arguments passed to the string action, then cleans up the previous code so we don't need to mutilate the command line arguments: we can just extract it from the resultant set of information. Reviewed-By: Nick Lewis --- lib/puppet/application/string_base.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index a082ba0e2..8284a3185 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -84,7 +84,6 @@ class Puppet::Application::StringBase < Puppet::Application raise ArgumentError, "#{@string} does not have an #{item.inspect} action!" end @action = action - command_line.args.delete_at(index) end end @@ -105,7 +104,12 @@ class Puppet::Application::StringBase < Puppet::Application # action to read in the options. This replaces the older model where we # would invoke the action with options set as global state in the # interface object. --daniel 2011-03-28 - @arguments = command_line.args + # + # Note: because of our definition of where the action is set, we end up + # with it *always* being the first word of the remaining set of command + # line arguments. So, strip that off when we construct the arguments to + # pass down to the string action. --daniel 2011-04-04 + @arguments = command_line.args[1, -1] || [] @arguments << options end -- cgit From 0c74495529bd697cdc42986882fc3efb4cdc9903 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 4 Apr 2011 11:35:46 -0700 Subject: (#6749) Handle options with inline arguments. We didn't correctly handle '--foo=bar' as having supplied an argument during the pre-parse phase. Now we have a test for it, and a fix in the code. Reviewed-By: Nick Lewis --- lib/puppet/application/string_base.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 8284a3185..06e5789be 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -71,7 +71,11 @@ class Puppet::Application::StringBase < Puppet::Application option = @string.options.find { |a| item =~ /^-+#{a}\b/ } if option then option = @string.get_option(option) - if option.takes_argument? then + # If we have an inline argument, just carry on. We don't need to + # care about optional vs mandatory in that case because we do a real + # parse later, and that will totally take care of raising the error + # when we get there. --daniel 2011-04-04 + if option.takes_argument? and !item.index('=') then index += 1 unless (option.optional_argument? and command_line.args[index + 1] =~ /^-/) end -- cgit From 4d2a367b0cf5bf03588b1e6bbfafdf437bea249e Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 4 Apr 2011 14:34:51 -0700 Subject: (#6964) use 'when_invoked' rather than 'invoke' for actions. In the DSL we want to use 'when_invoked do' because it reads much more naturally for users. Reviewed-By: Pieter van de Bruggen --- lib/puppet/string/action.rb | 2 +- lib/puppet/string/action_builder.rb | 7 ++++--- lib/puppet/string/action_manager.rb | 2 +- lib/puppet/string/catalog.rb | 4 ++-- lib/puppet/string/catalog/select.rb | 2 +- lib/puppet/string/certificate.rb | 6 +++--- lib/puppet/string/config.rb | 2 +- lib/puppet/string/configurer.rb | 2 +- lib/puppet/string/facts.rb | 2 +- lib/puppet/string/indirector.rb | 10 +++++----- lib/puppet/string/report.rb | 2 +- 11 files changed, 21 insertions(+), 20 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb index ee3b2991b..0f5032ffb 100644 --- a/lib/puppet/string/action.rb +++ b/lib/puppet/string/action.rb @@ -51,7 +51,7 @@ class Puppet::String::Action # @string.send(name, *args, &block) # end - def invoke=(block) + def when_invoked=(block) # We need to build an instance method as a wrapper, using normal code, to # be able to expose argument defaulting between the caller and definer in # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb index e76044470..e7c03273b 100644 --- a/lib/puppet/string/action_builder.rb +++ b/lib/puppet/string/action_builder.rb @@ -9,6 +9,7 @@ class Puppet::String::ActionBuilder new(string, name, &block).action end + private def initialize(string, name, &block) @string = string @action = Puppet::String::Action.new(string, name) @@ -18,9 +19,9 @@ class Puppet::String::ActionBuilder # 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 + def when_invoked(&block) + raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action + @action.when_invoked = block end def option(*declaration, &block) diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb index 7d22a0c52..9f0aa7582 100644 --- a/lib/puppet/string/action_manager.rb +++ b/lib/puppet/string/action_manager.rb @@ -15,7 +15,7 @@ module Puppet::String::ActionManager def script(name, &block) @actions ||= {} raise "Action #{name} already defined for #{self}" if action?(name) - @actions[name] = Puppet::String::Action.new(self, name, :invoke => block) + @actions[name] = Puppet::String::Action.new(self, name, :when_invoked => block) end def actions diff --git a/lib/puppet/string/catalog.rb b/lib/puppet/string/catalog.rb index c6de47708..441c7ee7d 100644 --- a/lib/puppet/string/catalog.rb +++ b/lib/puppet/string/catalog.rb @@ -2,7 +2,7 @@ require 'puppet/string/indirector' Puppet::String::Indirector.define(:catalog, '0.0.1') do action(:apply) do - invoke do |catalog, options| + when_invoked do |catalog, options| report = Puppet::Transaction::Report.new("apply") report.configuration_version = catalog.version @@ -23,7 +23,7 @@ Puppet::String::Indirector.define(:catalog, '0.0.1') do end action(:download) do - invoke do |certname, facts, options| + when_invoked do |certname, facts, options| Puppet::Resource::Catalog.terminus_class = :rest facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} catalog = nil diff --git a/lib/puppet/string/catalog/select.rb b/lib/puppet/string/catalog/select.rb index a8f4480cd..11670e2e7 100644 --- a/lib/puppet/string/catalog/select.rb +++ b/lib/puppet/string/catalog/select.rb @@ -1,7 +1,7 @@ # 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, options| + when_invoked do |host, type, options| catalog = Puppet::Resource::Catalog.indirection.find(host) catalog.resources.reject { |res| res.type != type }.each { |res| puts res } diff --git a/lib/puppet/string/certificate.rb b/lib/puppet/string/certificate.rb index 53f731e81..7b72b112c 100644 --- a/lib/puppet/string/certificate.rb +++ b/lib/puppet/string/certificate.rb @@ -4,7 +4,7 @@ require 'puppet/ssl/host' Puppet::String::Indirector.define(:certificate, '0.0.1') do action :generate do - invoke do |name, options| + when_invoked do |name, options| host = Puppet::SSL::Host.new(name) host.generate_certificate_request host.certificate_request.class.indirection.save(host.certificate_request) @@ -12,7 +12,7 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do end action :list do - invoke do |options| + when_invoked do |options| Puppet::SSL::Host.indirection.search("*", { :for => :certificate_request, }).map { |h| h.inspect } @@ -20,7 +20,7 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do end action :sign do - invoke do |name, options| + when_invoked do |name, options| Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) end end diff --git a/lib/puppet/string/config.rb b/lib/puppet/string/config.rb index 49a1688fc..8a9417148 100644 --- a/lib/puppet/string/config.rb +++ b/lib/puppet/string/config.rb @@ -2,7 +2,7 @@ require 'puppet/string' Puppet::String.define(:config, '0.0.1') do action(:print) do - invoke do |*args| + when_invoked do |*args| options = args.pop Puppet.settings[:configprint] = args.join(",") Puppet.settings.print_config_options diff --git a/lib/puppet/string/configurer.rb b/lib/puppet/string/configurer.rb index 2520d4188..257f97e90 100644 --- a/lib/puppet/string/configurer.rb +++ b/lib/puppet/string/configurer.rb @@ -2,7 +2,7 @@ require 'puppet/string' Puppet::String.define(:configurer, '0.0.1') do action(:synchronize) do - invoke do |certname, options| + when_invoked do |certname, options| 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) diff --git a/lib/puppet/string/facts.rb b/lib/puppet/string/facts.rb index 31298813b..6bd9904b0 100644 --- a/lib/puppet/string/facts.rb +++ b/lib/puppet/string/facts.rb @@ -6,7 +6,7 @@ Puppet::String::Indirector.define(:facts, '0.0.1') do # Upload our facts to the server action(:upload) do - invoke do |options| + when_invoked do |options| Puppet::Node::Facts.indirection.terminus_class = :facter facts = Puppet::Node::Facts.indirection.find(Puppet[:certname]) Puppet::Node::Facts.indirection.terminus_class = :rest diff --git a/lib/puppet/string/indirector.rb b/lib/puppet/string/indirector.rb index bb081533f..0c7d043bb 100644 --- a/lib/puppet/string/indirector.rb +++ b/lib/puppet/string/indirector.rb @@ -31,24 +31,24 @@ that we should describe in this file somehow." end action :destroy do - invoke { |*args| call_indirection_method(:destroy, *args) } + when_invoked { |*args| call_indirection_method(:destroy, *args) } end action :find do - invoke { |*args| call_indirection_method(:find, *args) } + when_invoked { |*args| call_indirection_method(:find, *args) } end action :save do - invoke { |*args| call_indirection_method(:save, *args) } + when_invoked { |*args| call_indirection_method(:save, *args) } end action :search do - invoke { |*args| call_indirection_method(:search, *args) } + when_invoked { |*args| call_indirection_method(:search, *args) } end # Print the configuration for the current terminus class action :info do - invoke do |*args| + when_invoked do |*args| options = args.pop options.has_key?(:terminus) and set_terminus(options[:terminus]) diff --git a/lib/puppet/string/report.rb b/lib/puppet/string/report.rb index 5b617e49e..da3ca8504 100644 --- a/lib/puppet/string/report.rb +++ b/lib/puppet/string/report.rb @@ -2,7 +2,7 @@ require 'puppet/string/indirector' Puppet::String::Indirector.define(:report, '0.0.1') do action(:submit) do - invoke do |report, options| + when_invoked do |report, options| begin Puppet::Transaction::Report.terminus_class = :rest report.save -- cgit From 0950d09d12ec06e97915d264e8724e736c84e36a Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Mon, 4 Apr 2011 14:46:21 -0700 Subject: (#6949) Fix passing positional arguments to actions. We had a logic failure that didn't pass positional arguments at all, but which our testing didn't verify. This entirely broke things. Now fixed, and a test added to ensure we don't bug out further... Reviewed-By: Pieter van de Bruggen --- lib/puppet/application/string_base.rb | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 06e5789be..76b0a46fd 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -104,16 +104,18 @@ class Puppet::Application::StringBase < Puppet::Application def setup Puppet::Util::Log.newdestination :console - # We copy all of the app options to the end of the call; This allows each - # action to read in the options. This replaces the older model where we - # would invoke the action with options set as global state in the - # interface object. --daniel 2011-03-28 - # + @arguments = command_line.args + # Note: because of our definition of where the action is set, we end up # with it *always* being the first word of the remaining set of command # line arguments. So, strip that off when we construct the arguments to # pass down to the string action. --daniel 2011-04-04 - @arguments = command_line.args[1, -1] || [] + @arguments.delete_at(0) + + # We copy all of the app options to the end of the call; This allows each + # action to read in the options. This replaces the older model where we + # would invoke the action with options set as global state in the + # interface object. --daniel 2011-03-28 @arguments << options end -- cgit From 8ddd9947382579082cc4554b332ca1ec62d94942 Mon Sep 17 00:00:00 2001 From: Pieter van de Bruggen Date: Tue, 5 Apr 2011 16:41:14 -0700 Subject: (#6982) Patch the Certificate String against (#5528). Reviewed-By: Matt Robinson --- lib/puppet/string/certificate.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/certificate.rb b/lib/puppet/string/certificate.rb index 7b72b112c..b231cafb1 100644 --- a/lib/puppet/string/certificate.rb +++ b/lib/puppet/string/certificate.rb @@ -21,7 +21,9 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do action :sign do when_invoked do |name, options| - Puppet::SSL::Host.indirection.save(Puppet::SSL::Host.new(name)) + host = Puppet::SSL::Host.new(name) + host.desired_state = 'signed' + Puppet::SSL::Host.indirection.save(host) end end -- cgit From d4012dbf2e7e041e8e24eda6cd896b6f6e4fac4d Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Wed, 6 Apr 2011 16:28:56 -0700 Subject: (#6995) Fix indexing of :current on string load. We do this by implementing a standard mechanism for finding the current version out of the default file, and only supporting that one file. This implements our decision to lazy-evaluate the extra version support stuff as much as possible. Reviewed-By: Dan Bode --- lib/puppet/string/string_collection.rb | 86 ++++++++++++++++++++++++++-------- 1 file changed, 66 insertions(+), 20 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/string_collection.rb b/lib/puppet/string/string_collection.rb index f8fa38b9c..ecd99359d 100644 --- a/lib/puppet/string/string_collection.rb +++ b/lib/puppet/string/string_collection.rb @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- require 'puppet/string' module Puppet::String::StringCollection @@ -30,37 +31,82 @@ module Puppet::String::StringCollection !!(SEMVER_VERSION =~ version.to_s) end + def self.cmp_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) @strings[underscorize(name)][version] if string?(name, version) end def self.string?(name, version) name = underscorize(name) - cache = @strings[name] - return true if cache.has_key?(version) - - loaded = cache.keys + return true if @strings[name].has_key?(version) - module_names = ["puppet/string/#{name}"] - unless version == :current - module_names << "#{name}@#{version}/puppet/string/#{name}" - end + # We always load the current version file; the common case is that we have + # the expected version and any compatibility versions in the same file, + # the default. Which means that this is almost always the case. + # + # We use require to avoid executing the code multiple times, like any + # other Ruby library that we might want to use. --daniel 2011-04-06 + begin + require "puppet/string/#{name}" - module_names.each do |module_name| - begin - require module_name - if version == :current || !module_name.include?('@') - loaded = (cache.keys - loaded).first - cache[:current] = cache[loaded] unless loaded.nil? - end - return true if cache.has_key?(version) - rescue LoadError => e - raise unless e.message =~ /-- #{module_name}$/ - # pass + # If we wanted :current, we need to index to find that; direct version + # requests just work™ as they go. --daniel 2011-04-06 + if version == :current then + # We need to find current out of this. This is the largest version + # number that doesn't have a dedicated on-disk file present; those + # represent "experimental" versions of strings, which we don't fully + # support yet. + # + # We walk the versions from highest to lowest and take the first version + # that is not defined in an explicitly versioned file on disk as the + # current version. + # + # This constrains us to only ship experimental versions with *one* + # version in the file, not multiple, but given you can't reliably load + # them except by side-effect when you ignore that rule this seems safe + # enough... + # + # Given those constraints, and that we are not going to ship a versioned + # interface that is not :current in this release, we are going to leave + # these thoughts in place, and just punt on the actual versioning. + # + # When we upgrade the core to support multiple versions we can solve the + # problems then; as lazy as possible. + # + # We do support multiple versions in the same file, though, so we sort + # versions here and return the last item in that set. + # + # --daniel 2011-04-06 + latest_ver = @strings[name].keys.sort {|a, b| cmp_versions(a, b) }.last + @strings[name][:current] = @strings[name][latest_ver] end + rescue LoadError => e + raise unless e.message =~ %r{-- puppet/string/#{name}$} + # ...guess we didn't find the file; return a much better problem. end - return false + # Now, either we have the version in our set of strings, or we didn't find + # the version they were looking for. In the future we will support + # loading versioned stuff from some look-aside part of the Ruby load path, + # but we don't need that right now. + # + # So, this comment is a place-holder for that. --daniel 2011-04-06 + return !! @strings[name].has_key?(version) end def self.register(string) -- cgit From 0b97bd0df57dd6732db5f52fc7360f61e74dba2e Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 5 Apr 2011 11:36:18 -0700 Subject: (#6972) Clean up OptParse name extraction a little. During testing, an obvious cleanup showed up for the name extraction here, so we implement it. This extends the regexp to better extract the data we want rather than hacking it up post-match and having to do extra validation to make sure it actually worked. Reviewed-By: Dan Bode --- lib/puppet/string/option.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb index f499e4b95..be7bbb76e 100644 --- a/lib/puppet/string/option.rb +++ b/lib/puppet/string/option.rb @@ -70,10 +70,10 @@ class Puppet::String::Option end def optparse_to_name(declaration) - unless found = declaration.match(/^-+([^= ]+)/) or found.length != 1 then + unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" end - name = found.captures.first.sub('[no-]', '').tr('-', '_') + name = found.captures.first.tr('-', '_') raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ name.to_sym end -- cgit From 7e7d246bf46349c904c76a31951d4a40c200790b Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 5 Apr 2011 11:37:51 -0700 Subject: (#6972) Recognize puppet global options in pre-parse. This extends the CLI pre-parse phase to identify both string *and* global options out of the Puppet settings/defaults system. This makes the regular CLI support for setting Puppet configuration globals work as expected. This moves us along the line of supporting these options more fully. Reviewed-By: Dan Bode --- lib/puppet/application/string_base.rb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb index 76b0a46fd..09d02c079 100644 --- a/lib/puppet/application/string_base.rb +++ b/lib/puppet/application/string_base.rb @@ -68,7 +68,9 @@ class Puppet::Application::StringBase < Puppet::Application until @action or (index += 1) >= command_line.args.length do item = command_line.args[index] if item =~ /^-/ then - option = @string.options.find { |a| item =~ /^-+#{a}\b/ } + option = @string.options.find do |name| + item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/ + end if option then option = @string.get_option(option) # If we have an inline argument, just carry on. We don't need to @@ -79,6 +81,12 @@ class Puppet::Application::StringBase < Puppet::Application index += 1 unless (option.optional_argument? and command_line.args[index + 1] =~ /^-/) end + elsif option = find_global_settings_argument(item) then + unless Puppet.settings.boolean? option.name then + # As far as I can tell, we treat non-bool options as always having + # a mandatory argument. --daniel 2011-04-05 + index += 1 # ...so skip the argument. + end else raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" end @@ -101,6 +109,18 @@ class Puppet::Application::StringBase < Puppet::Application end end + def find_global_settings_argument(item) + Puppet.settings.each do |name, object| + object.optparse_args.each do |arg| + next unless arg =~ /^-/ + # sadly, we have to emulate some of optparse here... + pattern = /^#{arg.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/ + pattern.match item and return object + end + end + return nil # nothing found. + end + def setup Puppet::Util::Log.newdestination :console -- cgit From a03790d82a2c190d6f00ee7677617a7be04aa85d Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 5 Apr 2011 18:39:19 -0700 Subject: (#6972) Handle ca-location in the certificate string. This ports the existing certificate location configuration to be a string option, and then uses that to change the configuration. This will leak state between calls, which is somewhat unavoidable, but should at least get the basic stuff right for the CLI. We eventually need the CA string to be supported by a stateless internal CA implementation that allows us to do the right thing overall. Reviewed-By: Dan Bode --- lib/puppet/application/certificate.rb | 15 +++------------ lib/puppet/string/certificate.rb | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 12 deletions(-) (limited to 'lib/puppet') diff --git a/lib/puppet/application/certificate.rb b/lib/puppet/application/certificate.rb index f4b13ffe0..eacb830b2 100644 --- a/lib/puppet/application/certificate.rb +++ b/lib/puppet/application/certificate.rb @@ -1,18 +1,10 @@ require 'puppet/application/indirection_base' class Puppet::Application::Certificate < Puppet::Application::IndirectionBase - - # Luke used to call this --ca but that's taken by the global boolean --ca. - # Since these options map CA terminology to indirector terminology, it's - # now called --ca-location. - option "--ca-location CA_LOCATION" do |arg| - Puppet::SSL::Host.ca_location = arg.to_sym - end - def setup - - unless Puppet::SSL::Host.ca_location - raise ArgumentError, "You must have a CA location specified; use --ca-location to specify the location (remote, local, only)" + unless options[:ca_location] + raise ArgumentError, "You must have a CA location specified;\n" + + "use --ca-location to specify the location (remote, local, only)" end location = Puppet::SSL::Host.ca_location @@ -23,5 +15,4 @@ class Puppet::Application::Certificate < Puppet::Application::IndirectionBase super end - end diff --git a/lib/puppet/string/certificate.rb b/lib/puppet/string/certificate.rb index b231cafb1..fdb0bc9f4 100644 --- a/lib/puppet/string/certificate.rb +++ b/lib/puppet/string/certificate.rb @@ -2,9 +2,24 @@ require 'puppet/string/indirector' require 'puppet/ssl/host' Puppet::String::Indirector.define(:certificate, '0.0.1') do + # REVISIT: This should use a pre-invoke hook to run the common code that + # needs to happen before we invoke any action; that would be much nicer than + # the "please repeat yourself" stuff found in here right now. + # + # option "--ca-location LOCATION" do + # type [:whatever, :location, :symbols] + # hook :before do |value| + # Puppet::SSL::Host.ca_location = value + # end + # end + # + # ...but should I pass the arguments as well? + # --daniel 2011-04-05 + option "--ca-location LOCATION" action :generate do when_invoked do |name, options| + Puppet::SSL::Host.ca_location = options[:ca_location].to_sym host = Puppet::SSL::Host.new(name) host.generate_certificate_request host.certificate_request.class.indirection.save(host.certificate_request) @@ -13,6 +28,7 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do action :list do when_invoked do |options| + Puppet::SSL::Host.ca_location = options[:ca_location].to_sym Puppet::SSL::Host.indirection.search("*", { :for => :certificate_request, }).map { |h| h.inspect } @@ -21,6 +37,7 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do action :sign do when_invoked do |name, options| + Puppet::SSL::Host.ca_location = options[:ca_location].to_sym host = Puppet::SSL::Host.new(name) host.desired_state = 'signed' Puppet::SSL::Host.indirection.save(host) -- cgit From 27bd1adb7cc43bfdeb8fb941418cfce3a7f694ef Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Tue, 5 Apr 2011 19:08:54 -0700 Subject: (#6983) mark test pending until string is fixed... The certificate string is broken, and won't allow you to either search or save certificates. Given that, mark the test on it broken until that is completed. Reviewed-By: Dan Bode --- lib/puppet/string/certificate.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/string/certificate.rb b/lib/puppet/string/certificate.rb index fdb0bc9f4..e8773ae2e 100644 --- a/lib/puppet/string/certificate.rb +++ b/lib/puppet/string/certificate.rb @@ -43,5 +43,4 @@ Puppet::String::Indirector.define(:certificate, '0.0.1') do Puppet::SSL::Host.indirection.save(host) end end - end -- cgit From 03afbad012b6054797111ddd6e4ad8db8df45406 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 7 Apr 2011 11:18:46 -0700 Subject: (#7006) Add a missing require to puppet/string/option.rb This was causing failure in some cases, based on load order; we should always satisfy our external dependencies. Reviewed-By: Dan Bode --- lib/puppet/string/option.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/puppet') diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb index be7bbb76e..352f7e5ef 100644 --- a/lib/puppet/string/option.rb +++ b/lib/puppet/string/option.rb @@ -1,3 +1,5 @@ +require 'puppet/string' + class Puppet::String::Option attr_reader :parent attr_reader :name -- cgit From 5592034fdb8bf3a72ab3133d69443490f9ad7b78 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 7 Apr 2011 13:18:26 -0700 Subject: (#7012) global rename of strings to faces. This just changes filenames and directories; files are exact copies rather than having additional modifications to make clearer each step of this process. This does leave a currently broken build. :/ --- lib/puppet/application/faces.rb | 95 ++++++++++++++ lib/puppet/application/faces_base.rb | 150 +++++++++++++++++++++++ lib/puppet/application/string.rb | 95 -------------- lib/puppet/application/string_base.rb | 150 ----------------------- lib/puppet/faces.rb | 104 ++++++++++++++++ lib/puppet/faces/action.rb | 121 ++++++++++++++++++ lib/puppet/faces/action_builder.rb | 31 +++++ lib/puppet/faces/action_manager.rb | 49 ++++++++ lib/puppet/faces/catalog.rb | 40 ++++++ lib/puppet/faces/catalog/select.rb | 10 ++ lib/puppet/faces/certificate.rb | 46 +++++++ lib/puppet/faces/certificate_request.rb | 4 + lib/puppet/faces/certificate_revocation_list.rb | 4 + lib/puppet/faces/config.rb | 12 ++ lib/puppet/faces/configurer.rb | 12 ++ lib/puppet/faces/faces_collection.rb | 123 +++++++++++++++++++ lib/puppet/faces/facts.rb | 18 +++ lib/puppet/faces/file.rb | 5 + lib/puppet/faces/indirector.rb | 94 ++++++++++++++ lib/puppet/faces/key.rb | 4 + lib/puppet/faces/node.rb | 5 + lib/puppet/faces/option.rb | 82 +++++++++++++ lib/puppet/faces/option_builder.rb | 25 ++++ lib/puppet/faces/option_manager.rb | 56 +++++++++ lib/puppet/faces/report.rb | 15 +++ lib/puppet/faces/resource.rb | 4 + lib/puppet/faces/resource_type.rb | 4 + lib/puppet/faces/status.rb | 4 + lib/puppet/string.rb | 104 ---------------- lib/puppet/string/action.rb | 121 ------------------ lib/puppet/string/action_builder.rb | 31 ----- lib/puppet/string/action_manager.rb | 49 -------- lib/puppet/string/catalog.rb | 40 ------ lib/puppet/string/catalog/select.rb | 10 -- lib/puppet/string/certificate.rb | 46 ------- lib/puppet/string/certificate_request.rb | 4 - lib/puppet/string/certificate_revocation_list.rb | 4 - lib/puppet/string/config.rb | 12 -- lib/puppet/string/configurer.rb | 12 -- lib/puppet/string/facts.rb | 18 --- lib/puppet/string/file.rb | 5 - lib/puppet/string/indirector.rb | 94 -------------- lib/puppet/string/key.rb | 4 - lib/puppet/string/node.rb | 5 - lib/puppet/string/option.rb | 82 ------------- lib/puppet/string/option_builder.rb | 25 ---- lib/puppet/string/option_manager.rb | 56 --------- lib/puppet/string/report.rb | 15 --- lib/puppet/string/resource.rb | 4 - lib/puppet/string/resource_type.rb | 4 - lib/puppet/string/status.rb | 4 - lib/puppet/string/string_collection.rb | 123 ------------------- 52 files changed, 1117 insertions(+), 1117 deletions(-) create mode 100644 lib/puppet/application/faces.rb create mode 100644 lib/puppet/application/faces_base.rb delete mode 100644 lib/puppet/application/string.rb delete mode 100644 lib/puppet/application/string_base.rb create mode 100644 lib/puppet/faces.rb create mode 100644 lib/puppet/faces/action.rb create mode 100644 lib/puppet/faces/action_builder.rb create mode 100644 lib/puppet/faces/action_manager.rb create mode 100644 lib/puppet/faces/catalog.rb create mode 100644 lib/puppet/faces/catalog/select.rb create mode 100644 lib/puppet/faces/certificate.rb create mode 100644 lib/puppet/faces/certificate_request.rb create mode 100644 lib/puppet/faces/certificate_revocation_list.rb create mode 100644 lib/puppet/faces/config.rb create mode 100644 lib/puppet/faces/configurer.rb create mode 100644 lib/puppet/faces/faces_collection.rb create mode 100644 lib/puppet/faces/facts.rb create mode 100644 lib/puppet/faces/file.rb create mode 100644 lib/puppet/faces/indirector.rb create mode 100644 lib/puppet/faces/key.rb create mode 100644 lib/puppet/faces/node.rb create mode 100644 lib/puppet/faces/option.rb create mode 100644 lib/puppet/faces/option_builder.rb create mode 100644 lib/puppet/faces/option_manager.rb create mode 100644 lib/puppet/faces/report.rb create mode 100644 lib/puppet/faces/resource.rb create mode 100644 lib/puppet/faces/resource_type.rb create mode 100644 lib/puppet/faces/status.rb delete mode 100644 lib/puppet/string.rb delete mode 100644 lib/puppet/string/action.rb delete mode 100644 lib/puppet/string/action_builder.rb delete mode 100644 lib/puppet/string/action_manager.rb delete mode 100644 lib/puppet/string/catalog.rb delete mode 100644 lib/puppet/string/catalog/select.rb delete mode 100644 lib/puppet/string/certificate.rb delete mode 100644 lib/puppet/string/certificate_request.rb delete mode 100644 lib/puppet/string/certificate_revocation_list.rb delete mode 100644 lib/puppet/string/config.rb delete mode 100644 lib/puppet/string/configurer.rb delete mode 100644 lib/puppet/string/facts.rb delete mode 100644 lib/puppet/string/file.rb delete mode 100644 lib/puppet/string/indirector.rb delete mode 100644 lib/puppet/string/key.rb delete mode 100644 lib/puppet/string/node.rb delete mode 100644 lib/puppet/string/option.rb delete mode 100644 lib/puppet/string/option_builder.rb delete mode 100644 lib/puppet/string/option_manager.rb delete mode 100644 lib/puppet/string/report.rb delete mode 100644 lib/puppet/string/resource.rb delete mode 100644 lib/puppet/string/resource_type.rb delete mode 100644 lib/puppet/string/status.rb delete mode 100644 lib/puppet/string/string_collection.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/faces.rb b/lib/puppet/application/faces.rb new file mode 100644 index 000000000..0a6a798ce --- /dev/null +++ b/lib/puppet/application/faces.rb @@ -0,0 +1,95 @@ +require 'puppet/application' +require 'puppet/string' + +class Puppet::Application::String < Puppet::Application + + should_parse_config + run_mode :agent + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + def list(*arguments) + if arguments.empty? + arguments = %w{terminuses actions} + end + strings.each do |name| + str = "#{name}:\n" + if arguments.include?("terminuses") + begin + terms = terminus_classes(name.to_sym) + str << "\tTerminuses: #{terms.join(", ")}\n" + rescue => detail + puts detail.backtrace if Puppet[:trace] + $stderr.puts "Could not load terminuses for #{name}: #{detail}" + end + end + + if arguments.include?("actions") + begin + actions = actions(name.to_sym) + str << "\tActions: #{actions.join(", ")}\n" + rescue => detail + puts detail.backtrace if Puppet[:trace] + $stderr.puts "Could not load actions for #{name}: #{detail}" + end + end + + print str + end + end + + attr_accessor :verb, :name, :arguments + + def main + # Call the method associated with the provided action (e.g., 'find'). + send(verb, *arguments) + end + + def setup + Puppet::Util::Log.newdestination :console + + load_applications # Call this to load all of the apps + + @verb, @arguments = command_line.args + @arguments ||= [] + + validate + end + + def validate + unless verb + raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" + end + + unless respond_to?(verb) + raise "Command '#{verb}' not found for 'string'" + end + end + + def strings + Puppet::String.strings + end + + def terminus_classes(indirection) + Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort + end + + def actions(indirection) + return [] unless string = Puppet::String[indirection, '0.0.1'] + string.load_actions + return string.actions.sort { |a, b| a.to_s <=> b.to_s } + end + + def load_applications + command_line.available_subcommands.each do |app| + command_line.require_application app + end + end +end + diff --git a/lib/puppet/application/faces_base.rb b/lib/puppet/application/faces_base.rb new file mode 100644 index 000000000..09d02c079 --- /dev/null +++ b/lib/puppet/application/faces_base.rb @@ -0,0 +1,150 @@ +require 'puppet/application' +require 'puppet/string' + +class Puppet::Application::StringBase < Puppet::Application + should_parse_config + run_mode :agent + + option("--debug", "-d") do |arg| + Puppet::Util::Log.level = :debug + end + + option("--verbose", "-v") do + Puppet::Util::Log.level = :info + end + + option("--format FORMAT") do |arg| + @format = arg.to_sym + end + + option("--mode RUNMODE", "-r") do |arg| + raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) + self.class.run_mode(arg.to_sym) + set_run_mode self.class.run_mode + end + + + attr_accessor :string, :action, :type, :arguments, :format + attr_writer :exit_code + + # This allows you to set the exit code if you don't want to just exit + # immediately but you need to indicate a failure. + def exit_code + @exit_code || 0 + end + + # Override this if you need custom rendering. + def render(result) + render_method = Puppet::Network::FormatHandler.format(format).render_method + if render_method == "to_pson" + jj result + exit(0) + else + result.send(render_method) + end + end + + def preinit + super + trap(:INT) do + $stderr.puts "Cancelling String" + exit(0) + end + + # We need to parse enough of the command line out early, to identify what + # the action is, so that we can obtain the full set of options to parse. + + # TODO: These should be configurable versions, through a global + # '--version' option, but we don't implement that yet... --daniel 2011-03-29 + @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym + @string = Puppet::String[@type, :current] + @format = @string.default_format + + # Now, walk the command line and identify the action. We skip over + # arguments based on introspecting the action and all, and find the first + # non-option word to use as the action. + action = nil + index = -1 + until @action or (index += 1) >= command_line.args.length do + item = command_line.args[index] + if item =~ /^-/ then + option = @string.options.find do |name| + item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/ + end + if option then + option = @string.get_option(option) + # If we have an inline argument, just carry on. We don't need to + # care about optional vs mandatory in that case because we do a real + # parse later, and that will totally take care of raising the error + # when we get there. --daniel 2011-04-04 + if option.takes_argument? and !item.index('=') then + index += 1 unless + (option.optional_argument? and command_line.args[index + 1] =~ /^-/) + end + elsif option = find_global_settings_argument(item) then + unless Puppet.settings.boolean? option.name then + # As far as I can tell, we treat non-bool options as always having + # a mandatory argument. --daniel 2011-04-05 + index += 1 # ...so skip the argument. + end + else + raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" + end + else + action = @string.get_action(item.to_sym) + if action.nil? then + raise ArgumentError, "#{@string} does not have an #{item.inspect} action!" + end + @action = action + end + end + + @action or raise ArgumentError, "No action given on the command line!" + + # Finally, we can interact with the default option code to build behaviour + # around the full set of options we now know we support. + @action.options.each do |option| + option = @action.get_option(option) # make it the object. + self.class.option(*option.optparse) # ...and make the CLI parse it. + end + end + + def find_global_settings_argument(item) + Puppet.settings.each do |name, object| + object.optparse_args.each do |arg| + next unless arg =~ /^-/ + # sadly, we have to emulate some of optparse here... + pattern = /^#{arg.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/ + pattern.match item and return object + end + end + return nil # nothing found. + end + + def setup + Puppet::Util::Log.newdestination :console + + @arguments = command_line.args + + # Note: because of our definition of where the action is set, we end up + # with it *always* being the first word of the remaining set of command + # line arguments. So, strip that off when we construct the arguments to + # pass down to the string action. --daniel 2011-04-04 + @arguments.delete_at(0) + + # We copy all of the app options to the end of the call; This allows each + # action to read in the options. This replaces the older model where we + # would invoke the action with options set as global state in the + # interface object. --daniel 2011-03-28 + @arguments << options + end + + + def main + # Call the method associated with the provided action (e.g., 'find'). + if result = @string.send(@action.name, *arguments) + puts render(result) + end + exit(exit_code) + end +end diff --git a/lib/puppet/application/string.rb b/lib/puppet/application/string.rb deleted file mode 100644 index 0a6a798ce..000000000 --- a/lib/puppet/application/string.rb +++ /dev/null @@ -1,95 +0,0 @@ -require 'puppet/application' -require 'puppet/string' - -class Puppet::Application::String < Puppet::Application - - should_parse_config - run_mode :agent - - option("--debug", "-d") do |arg| - Puppet::Util::Log.level = :debug - end - - option("--verbose", "-v") do - Puppet::Util::Log.level = :info - end - - def list(*arguments) - if arguments.empty? - arguments = %w{terminuses actions} - end - strings.each do |name| - str = "#{name}:\n" - if arguments.include?("terminuses") - begin - terms = terminus_classes(name.to_sym) - str << "\tTerminuses: #{terms.join(", ")}\n" - rescue => detail - puts detail.backtrace if Puppet[:trace] - $stderr.puts "Could not load terminuses for #{name}: #{detail}" - end - end - - if arguments.include?("actions") - begin - actions = actions(name.to_sym) - str << "\tActions: #{actions.join(", ")}\n" - rescue => detail - puts detail.backtrace if Puppet[:trace] - $stderr.puts "Could not load actions for #{name}: #{detail}" - end - end - - print str - end - end - - attr_accessor :verb, :name, :arguments - - def main - # Call the method associated with the provided action (e.g., 'find'). - send(verb, *arguments) - end - - def setup - Puppet::Util::Log.newdestination :console - - load_applications # Call this to load all of the apps - - @verb, @arguments = command_line.args - @arguments ||= [] - - validate - end - - def validate - unless verb - raise "You must specify 'find', 'search', 'save', or 'destroy' as a verb; 'save' probably does not work right now" - end - - unless respond_to?(verb) - raise "Command '#{verb}' not found for 'string'" - end - end - - def strings - Puppet::String.strings - end - - def terminus_classes(indirection) - Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort - end - - def actions(indirection) - return [] unless string = Puppet::String[indirection, '0.0.1'] - string.load_actions - return string.actions.sort { |a, b| a.to_s <=> b.to_s } - end - - def load_applications - command_line.available_subcommands.each do |app| - command_line.require_application app - end - end -end - diff --git a/lib/puppet/application/string_base.rb b/lib/puppet/application/string_base.rb deleted file mode 100644 index 09d02c079..000000000 --- a/lib/puppet/application/string_base.rb +++ /dev/null @@ -1,150 +0,0 @@ -require 'puppet/application' -require 'puppet/string' - -class Puppet::Application::StringBase < Puppet::Application - should_parse_config - run_mode :agent - - option("--debug", "-d") do |arg| - Puppet::Util::Log.level = :debug - end - - option("--verbose", "-v") do - Puppet::Util::Log.level = :info - end - - option("--format FORMAT") do |arg| - @format = arg.to_sym - end - - option("--mode RUNMODE", "-r") do |arg| - raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) - self.class.run_mode(arg.to_sym) - set_run_mode self.class.run_mode - end - - - attr_accessor :string, :action, :type, :arguments, :format - attr_writer :exit_code - - # This allows you to set the exit code if you don't want to just exit - # immediately but you need to indicate a failure. - def exit_code - @exit_code || 0 - end - - # Override this if you need custom rendering. - def render(result) - render_method = Puppet::Network::FormatHandler.format(format).render_method - if render_method == "to_pson" - jj result - exit(0) - else - result.send(render_method) - end - end - - def preinit - super - trap(:INT) do - $stderr.puts "Cancelling String" - exit(0) - end - - # We need to parse enough of the command line out early, to identify what - # the action is, so that we can obtain the full set of options to parse. - - # TODO: These should be configurable versions, through a global - # '--version' option, but we don't implement that yet... --daniel 2011-03-29 - @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - @string = Puppet::String[@type, :current] - @format = @string.default_format - - # Now, walk the command line and identify the action. We skip over - # arguments based on introspecting the action and all, and find the first - # non-option word to use as the action. - action = nil - index = -1 - until @action or (index += 1) >= command_line.args.length do - item = command_line.args[index] - if item =~ /^-/ then - option = @string.options.find do |name| - item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/ - end - if option then - option = @string.get_option(option) - # If we have an inline argument, just carry on. We don't need to - # care about optional vs mandatory in that case because we do a real - # parse later, and that will totally take care of raising the error - # when we get there. --daniel 2011-04-04 - if option.takes_argument? and !item.index('=') then - index += 1 unless - (option.optional_argument? and command_line.args[index + 1] =~ /^-/) - end - elsif option = find_global_settings_argument(item) then - unless Puppet.settings.boolean? option.name then - # As far as I can tell, we treat non-bool options as always having - # a mandatory argument. --daniel 2011-04-05 - index += 1 # ...so skip the argument. - end - else - raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" - end - else - action = @string.get_action(item.to_sym) - if action.nil? then - raise ArgumentError, "#{@string} does not have an #{item.inspect} action!" - end - @action = action - end - end - - @action or raise ArgumentError, "No action given on the command line!" - - # Finally, we can interact with the default option code to build behaviour - # around the full set of options we now know we support. - @action.options.each do |option| - option = @action.get_option(option) # make it the object. - self.class.option(*option.optparse) # ...and make the CLI parse it. - end - end - - def find_global_settings_argument(item) - Puppet.settings.each do |name, object| - object.optparse_args.each do |arg| - next unless arg =~ /^-/ - # sadly, we have to emulate some of optparse here... - pattern = /^#{arg.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/ - pattern.match item and return object - end - end - return nil # nothing found. - end - - def setup - Puppet::Util::Log.newdestination :console - - @arguments = command_line.args - - # Note: because of our definition of where the action is set, we end up - # with it *always* being the first word of the remaining set of command - # line arguments. So, strip that off when we construct the arguments to - # pass down to the string action. --daniel 2011-04-04 - @arguments.delete_at(0) - - # We copy all of the app options to the end of the call; This allows each - # action to read in the options. This replaces the older model where we - # would invoke the action with options set as global state in the - # interface object. --daniel 2011-03-28 - @arguments << options - end - - - def main - # Call the method associated with the provided action (e.g., 'find'). - if result = @string.send(@action.name, *arguments) - puts render(result) - end - exit(exit_code) - end -end diff --git a/lib/puppet/faces.rb b/lib/puppet/faces.rb new file mode 100644 index 000000000..517cf4506 --- /dev/null +++ b/lib/puppet/faces.rb @@ -0,0 +1,104 @@ +require 'puppet' +require 'puppet/util/autoload' + +class Puppet::String + require 'puppet/string/string_collection' + + require 'puppet/string/action_manager' + include Puppet::String::ActionManager + extend Puppet::String::ActionManager + + require 'puppet/string/option_manager' + include Puppet::String::OptionManager + extend Puppet::String::OptionManager + + include Puppet::Util + + class << self + # This is just so we can search for actions. We only use its + # list of directories to search. + # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb + def autoloader + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/string") + end + + def strings + Puppet::String::StringCollection.strings + end + + def string?(name, version) + Puppet::String::StringCollection.string?(name, version) + end + + def register(instance) + Puppet::String::StringCollection.register(instance) + end + + def define(name, version, &block) + if string?(name, version) + string = Puppet::String::StringCollection[name, version] + else + string = self.new(name, version) + Puppet::String::StringCollection.register(string) + string.load_actions + end + + string.instance_eval(&block) if block_given? + + return string + end + + alias :[] :define + end + + attr_accessor :default_format + + def set_default_format(format) + self.default_format = format.to_sym + end + + attr_accessor :type, :verb, :version, :arguments + attr_reader :name + + def initialize(name, version, &block) + unless Puppet::String::StringCollection.validate_version(version) + raise ArgumentError, "Cannot create string #{name.inspect} with invalid version number '#{version}'!" + end + + @name = Puppet::String::StringCollection.underscorize(name) + @version = version + @default_format = :pson + + instance_eval(&block) if block_given? + end + + # Try to find actions defined in other files. + def load_actions + path = "puppet/string/#{name}" + + loaded = [] + [path, "#{name}@#{version}/#{path}"].each do |path| + Puppet::String.autoloader.search_directories.each do |dir| + fdir = ::File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.chdir(fdir) do + Dir.glob("*.rb").each do |file| + aname = file.sub(/\.rb/, '') + if loaded.include?(aname) + Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + next + end + loaded << aname + Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + require "#{Dir.pwd}/#{aname}" + end + end + end + end + end + + def to_s + "Puppet::String[#{name.inspect}, #{version.inspect}]" + end +end diff --git a/lib/puppet/faces/action.rb b/lib/puppet/faces/action.rb new file mode 100644 index 000000000..0f5032ffb --- /dev/null +++ b/lib/puppet/faces/action.rb @@ -0,0 +1,121 @@ +# -*- coding: utf-8 -*- +require 'puppet/string' +require 'puppet/string/option' + +class Puppet::String::Action + attr_reader :name + + def to_s + "#{@string}##{@name}" + end + + def initialize(string, name, attrs = {}) + raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ + @string = string + @name = name.to_sym + @options = {} + attrs.each do |k, v| send("#{k}=", v) end + end + + # Initially, this was defined to allow the @action.invoke pattern, which is + # a very natural way to invoke behaviour given our introspection + # capabilities. Heck, our initial plan was to have the string delegate to + # the action object for invocation and all. + # + # It turns out that we have a binding problem to solve: @string was bound to + # the parent class, not the subclass instance, and we don't pass the + # appropriate context or change the binding enough to make this work. + # + # We could hack around it, by either mandating that you pass the context in + # to invoke, or try to get the binding right, but that has probably got + # subtleties that we don't instantly think of – especially around threads. + # + # So, we are pulling this method for now, and will return it to life when we + # have the time to resolve the problem. For now, you should replace... + # + # @action = @string.get_action(name) + # @action.invoke(arg1, arg2, arg3) + # + # ...with... + # + # @action = @string.get_action(name) + # @string.send(@action.name, arg1, arg2, arg3) + # + # I understand that is somewhat cumbersome, but it functions as desired. + # --daniel 2011-03-31 + # + # PS: This code is left present, but commented, to support this chunk of + # documentation, for the benefit of the reader. + # + # def invoke(*args, &block) + # @string.send(name, *args, &block) + # end + + def when_invoked=(block) + # We need to build an instance method as a wrapper, using normal code, to + # be able to expose argument defaulting between the caller and definer in + # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. + # + # In future this also gives us a place to hook in additional behaviour + # such as calling out to the action instance to validate and coerce + # parameters, which avoids any exciting context switching and all. + # + # Hopefully we can improve this when we finally shuffle off the last of + # Ruby 1.8 support, but that looks to be a few "enterprise" release eras + # away, so we are pretty stuck with this for now. + # + # Patches to make this work more nicely with Ruby 1.9 using runtime + # version checking and all are welcome, but they can't actually help if + # the results are not totally hidden away in here. + # + # Incidentally, we though about vendoring evil-ruby and actually adjusting + # the internal C structure implementation details under the hood to make + # this stuff work, because it would have been cleaner. Which gives you an + # idea how motivated we were to make this cleaner. Sorry. --daniel 2011-03-31 + + internal_name = "#{@name} implementation, required on Ruby 1.8".to_sym + file = __FILE__ + "+eval" + line = __LINE__ + 1 + wrapper = "def #{@name}(*args, &block) + args << {} unless args.last.is_a? Hash + args << block if block_given? + self.__send__(#{internal_name.inspect}, *args) + end" + + if @string.is_a?(Class) + @string.class_eval do eval wrapper, nil, file, line end + @string.define_method(internal_name, &block) + else + @string.instance_eval do eval wrapper, nil, file, line end + @string.meta_def(internal_name, &block) + end + end + + def add_option(option) + option.aliases.each do |name| + if conflict = get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" + elsif conflict = @string.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@string}" + end + end + + option.aliases.each do |name| + @options[name] = option + end + + option + end + + def option?(name) + @options.include? name.to_sym + end + + def options + (@options.keys + @string.options).sort + end + + def get_option(name) + @options[name.to_sym] || @string.get_option(name) + end +end diff --git a/lib/puppet/faces/action_builder.rb b/lib/puppet/faces/action_builder.rb new file mode 100644 index 000000000..e7c03273b --- /dev/null +++ b/lib/puppet/faces/action_builder.rb @@ -0,0 +1,31 @@ +require 'puppet/string' +require 'puppet/string/action' + +class Puppet::String::ActionBuilder + attr_reader :action + + def self.build(string, name, &block) + raise "Action #{name.inspect} must specify a block" unless block + new(string, name, &block).action + end + + private + 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 when_invoked(&block) + raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action + @action.when_invoked = block + end + + def option(*declaration, &block) + option = Puppet::String::OptionBuilder.build(@action, *declaration, &block) + @action.add_option(option) + end +end diff --git a/lib/puppet/faces/action_manager.rb b/lib/puppet/faces/action_manager.rb new file mode 100644 index 000000000..9f0aa7582 --- /dev/null +++ b/lib/puppet/faces/action_manager.rb @@ -0,0 +1,49 @@ +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 ||= {} + raise "Action #{name} already defined for #{self}" if action?(name) + action = Puppet::String::ActionBuilder.build(self, name, &block) + @actions[action.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 ||= {} + raise "Action #{name} already defined for #{self}" if action?(name) + @actions[name] = Puppet::String::Action.new(self, name, :when_invoked => 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 ||= {} + result = @actions[name.to_sym] + if result.nil? + if self.is_a?(Class) and superclass.respond_to?(:get_action) + result = superclass.get_action(name) + elsif self.class.respond_to?(:get_action) + result = self.class.get_action(name) + end + end + return result + end + + def action?(name) + actions.include?(name.to_sym) + end +end diff --git a/lib/puppet/faces/catalog.rb b/lib/puppet/faces/catalog.rb new file mode 100644 index 000000000..441c7ee7d --- /dev/null +++ b/lib/puppet/faces/catalog.rb @@ -0,0 +1,40 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:catalog, '0.0.1') do + action(:apply) do + when_invoked do |catalog, options| + 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 + when_invoked do |certname, facts, options| + 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/faces/catalog/select.rb b/lib/puppet/faces/catalog/select.rb new file mode 100644 index 000000000..11670e2e7 --- /dev/null +++ b/lib/puppet/faces/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 + when_invoked do |host, type, options| + 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/faces/certificate.rb b/lib/puppet/faces/certificate.rb new file mode 100644 index 000000000..e8773ae2e --- /dev/null +++ b/lib/puppet/faces/certificate.rb @@ -0,0 +1,46 @@ +require 'puppet/string/indirector' +require 'puppet/ssl/host' + +Puppet::String::Indirector.define(:certificate, '0.0.1') do + # REVISIT: This should use a pre-invoke hook to run the common code that + # needs to happen before we invoke any action; that would be much nicer than + # the "please repeat yourself" stuff found in here right now. + # + # option "--ca-location LOCATION" do + # type [:whatever, :location, :symbols] + # hook :before do |value| + # Puppet::SSL::Host.ca_location = value + # end + # end + # + # ...but should I pass the arguments as well? + # --daniel 2011-04-05 + option "--ca-location LOCATION" + + action :generate do + when_invoked do |name, options| + Puppet::SSL::Host.ca_location = options[:ca_location].to_sym + host = Puppet::SSL::Host.new(name) + host.generate_certificate_request + host.certificate_request.class.indirection.save(host.certificate_request) + end + end + + action :list do + when_invoked do |options| + Puppet::SSL::Host.ca_location = options[:ca_location].to_sym + Puppet::SSL::Host.indirection.search("*", { + :for => :certificate_request, + }).map { |h| h.inspect } + end + end + + action :sign do + when_invoked do |name, options| + Puppet::SSL::Host.ca_location = options[:ca_location].to_sym + host = Puppet::SSL::Host.new(name) + host.desired_state = 'signed' + Puppet::SSL::Host.indirection.save(host) + end + end +end diff --git a/lib/puppet/faces/certificate_request.rb b/lib/puppet/faces/certificate_request.rb new file mode 100644 index 000000000..218b40b98 --- /dev/null +++ b/lib/puppet/faces/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/faces/certificate_revocation_list.rb b/lib/puppet/faces/certificate_revocation_list.rb new file mode 100644 index 000000000..9731b4f2d --- /dev/null +++ b/lib/puppet/faces/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/faces/config.rb b/lib/puppet/faces/config.rb new file mode 100644 index 000000000..8a9417148 --- /dev/null +++ b/lib/puppet/faces/config.rb @@ -0,0 +1,12 @@ +require 'puppet/string' + +Puppet::String.define(:config, '0.0.1') do + action(:print) do + when_invoked do |*args| + options = args.pop + Puppet.settings[:configprint] = args.join(",") + Puppet.settings.print_config_options + nil + end + end +end diff --git a/lib/puppet/faces/configurer.rb b/lib/puppet/faces/configurer.rb new file mode 100644 index 000000000..257f97e90 --- /dev/null +++ b/lib/puppet/faces/configurer.rb @@ -0,0 +1,12 @@ +require 'puppet/string' + +Puppet::String.define(:configurer, '0.0.1') do + action(:synchronize) do + when_invoked do |certname, options| + 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/faces/faces_collection.rb b/lib/puppet/faces/faces_collection.rb new file mode 100644 index 000000000..ecd99359d --- /dev/null +++ b/lib/puppet/faces/faces_collection.rb @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- +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.validate_version(version) + !!(SEMVER_VERSION =~ version.to_s) + end + + def self.cmp_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) + @strings[underscorize(name)][version] if string?(name, version) + end + + def self.string?(name, version) + name = underscorize(name) + return true if @strings[name].has_key?(version) + + # We always load the current version file; the common case is that we have + # the expected version and any compatibility versions in the same file, + # the default. Which means that this is almost always the case. + # + # We use require to avoid executing the code multiple times, like any + # other Ruby library that we might want to use. --daniel 2011-04-06 + begin + require "puppet/string/#{name}" + + # If we wanted :current, we need to index to find that; direct version + # requests just work™ as they go. --daniel 2011-04-06 + if version == :current then + # We need to find current out of this. This is the largest version + # number that doesn't have a dedicated on-disk file present; those + # represent "experimental" versions of strings, which we don't fully + # support yet. + # + # We walk the versions from highest to lowest and take the first version + # that is not defined in an explicitly versioned file on disk as the + # current version. + # + # This constrains us to only ship experimental versions with *one* + # version in the file, not multiple, but given you can't reliably load + # them except by side-effect when you ignore that rule this seems safe + # enough... + # + # Given those constraints, and that we are not going to ship a versioned + # interface that is not :current in this release, we are going to leave + # these thoughts in place, and just punt on the actual versioning. + # + # When we upgrade the core to support multiple versions we can solve the + # problems then; as lazy as possible. + # + # We do support multiple versions in the same file, though, so we sort + # versions here and return the last item in that set. + # + # --daniel 2011-04-06 + latest_ver = @strings[name].keys.sort {|a, b| cmp_versions(a, b) }.last + @strings[name][:current] = @strings[name][latest_ver] + end + rescue LoadError => e + raise unless e.message =~ %r{-- puppet/string/#{name}$} + # ...guess we didn't find the file; return a much better problem. + end + + # Now, either we have the version in our set of strings, or we didn't find + # the version they were looking for. In the future we will support + # loading versioned stuff from some look-aside part of the Ruby load path, + # but we don't need that right now. + # + # So, this comment is a place-holder for that. --daniel 2011-04-06 + return !! @strings[name].has_key?(version) + 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/faces/facts.rb b/lib/puppet/faces/facts.rb new file mode 100644 index 000000000..6bd9904b0 --- /dev/null +++ b/lib/puppet/faces/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 + when_invoked do |options| + 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/faces/file.rb b/lib/puppet/faces/file.rb new file mode 100644 index 000000000..cc5737f28 --- /dev/null +++ b/lib/puppet/faces/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/faces/indirector.rb b/lib/puppet/faces/indirector.rb new file mode 100644 index 000000000..0c7d043bb --- /dev/null +++ b/lib/puppet/faces/indirector.rb @@ -0,0 +1,94 @@ +require 'puppet' +require 'puppet/string' + +class Puppet::String::Indirector < Puppet::String + option "--terminus TERMINUS" do + desc "REVISIT: You can select a terminus, which has some bigger effect +that we should describe in this file somehow." + end + + 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 + + def call_indirection_method(method, *args) + options = args.pop + options.has_key?(:terminus) and set_terminus(options[:terminus]) + + begin + result = indirection.__send__(method, *args) + rescue => detail + puts detail.backtrace if Puppet[:trace] + raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" + end + + indirection.reset_terminus_class + return result + end + + action :destroy do + when_invoked { |*args| call_indirection_method(:destroy, *args) } + end + + action :find do + when_invoked { |*args| call_indirection_method(:find, *args) } + end + + action :save do + when_invoked { |*args| call_indirection_method(:save, *args) } + end + + action :search do + when_invoked { |*args| call_indirection_method(:search, *args) } + end + + # Print the configuration for the current terminus class + action :info do + when_invoked do |*args| + options = args.pop + options.has_key?(:terminus) and set_terminus(options[:terminus]) + + 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 + + indirection.reset_terminus_class + 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 + @indirection = Puppet::Indirector::Indirection.instance(indirection_name) + @indirection or raise "Could not find terminus for #{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 #{self.class.terminus_classes(indirection.name).join(", ") }" + end + end +end diff --git a/lib/puppet/faces/key.rb b/lib/puppet/faces/key.rb new file mode 100644 index 000000000..95aceade5 --- /dev/null +++ b/lib/puppet/faces/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/faces/node.rb b/lib/puppet/faces/node.rb new file mode 100644 index 000000000..bc31a2cf3 --- /dev/null +++ b/lib/puppet/faces/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/faces/option.rb b/lib/puppet/faces/option.rb new file mode 100644 index 000000000..352f7e5ef --- /dev/null +++ b/lib/puppet/faces/option.rb @@ -0,0 +1,82 @@ +require 'puppet/string' + +class Puppet::String::Option + attr_reader :parent + attr_reader :name + attr_reader :aliases + attr_reader :optparse + attr_accessor :desc + + def takes_argument? + !!@argument + end + def optional_argument? + !!@optional_argument + end + + def initialize(parent, *declaration, &block) + @parent = parent + @optparse = [] + + # Collect and sort the arguments in the declaration. + dups = {} + declaration.each do |item| + if item.is_a? String and item.to_s =~ /^-/ then + unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then + raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" + end + @optparse << item + + # Duplicate checking... + name = optparse_to_name(item) + if dup = dups[name] then + raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" + else + dups[name] = item + end + else + raise ArgumentError, "#{item.inspect} is not valid for an option argument" + end + end + + if @optparse.empty? then + raise ArgumentError, "No option declarations found while building" + end + + # Now, infer the name from the options; we prefer the first long option as + # the name, rather than just the first option. + @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) + @aliases = @optparse.map { |o| optparse_to_name(o) } + + # Do we take an argument? If so, are we consistent about it, because + # incoherence here makes our life super-difficult, and we can more easily + # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 + @argument = @optparse.any? { |o| o =~ /[ =]/ } + if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then + raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" + end + + # Is our argument optional? The rules about consistency apply here, also, + # just like they do to taking arguments at all. --daniel 2011-03-30 + @optional_argument = @optparse.any? { |o| o.include? "[" } + if @optional_argument and not @optparse.all? { |o| o.include? "[" } then + raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" + end + end + + # to_s and optparse_to_name are roughly mirrored, because they are used to + # transform strings to name symbols, and vice-versa. This isn't a full + # bidirectional transformation though. + def to_s + @name.to_s.tr('_', '-') + end + + def optparse_to_name(declaration) + unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then + raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" + end + name = found.captures.first.tr('-', '_') + raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ + name.to_sym + end +end diff --git a/lib/puppet/faces/option_builder.rb b/lib/puppet/faces/option_builder.rb new file mode 100644 index 000000000..da0d213fb --- /dev/null +++ b/lib/puppet/faces/option_builder.rb @@ -0,0 +1,25 @@ +require 'puppet/string/option' + +class Puppet::String::OptionBuilder + attr_reader :option + + def self.build(string, *declaration, &block) + new(string, *declaration, &block).option + end + + private + def initialize(string, *declaration, &block) + @string = string + @option = Puppet::String::Option.new(string, *declaration) + block and instance_eval(&block) + @option + end + + # Metaprogram the simple DSL from the option class. + Puppet::String::Option.instance_methods.grep(/=$/).each do |setter| + next if setter =~ /^=/ # special case, darn it... + + dsl = setter.sub(/=$/, '') + define_method(dsl) do |value| @option.send(setter, value) end + end +end diff --git a/lib/puppet/faces/option_manager.rb b/lib/puppet/faces/option_manager.rb new file mode 100644 index 000000000..f952ad4f0 --- /dev/null +++ b/lib/puppet/faces/option_manager.rb @@ -0,0 +1,56 @@ +require 'puppet/string/option_builder' + +module Puppet::String::OptionManager + # Declare that this app can take a specific option, and provide + # the code to do so. + def option(*declaration, &block) + add_option Puppet::String::OptionBuilder.build(self, *declaration, &block) + end + + def add_option(option) + option.aliases.each do |name| + if conflict = get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" + end + + actions.each do |action| + action = get_action(action) + if conflict = action.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{action}" + end + end + end + + option.aliases.each { |name| @options[name] = option } + option + end + + def options + @options ||= {} + result = @options.keys + + if self.is_a?(Class) and superclass.respond_to?(:options) + result += superclass.options + elsif self.class.respond_to?(:options) + result += self.class.options + end + result.sort + end + + def get_option(name) + @options ||= {} + result = @options[name.to_sym] + unless result then + if self.is_a?(Class) and superclass.respond_to?(:get_option) + result = superclass.get_option(name) + elsif self.class.respond_to?(:get_option) + result = self.class.get_option(name) + end + end + return result + end + + def option?(name) + options.include? name.to_sym + end +end diff --git a/lib/puppet/faces/report.rb b/lib/puppet/faces/report.rb new file mode 100644 index 000000000..da3ca8504 --- /dev/null +++ b/lib/puppet/faces/report.rb @@ -0,0 +1,15 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:report, '0.0.1') do + action(:submit) do + when_invoked do |report, options| + 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/faces/resource.rb b/lib/puppet/faces/resource.rb new file mode 100644 index 000000000..9838be0fa --- /dev/null +++ b/lib/puppet/faces/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/faces/resource_type.rb b/lib/puppet/faces/resource_type.rb new file mode 100644 index 000000000..8ca31ea6c --- /dev/null +++ b/lib/puppet/faces/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/faces/status.rb b/lib/puppet/faces/status.rb new file mode 100644 index 000000000..41de2bb99 --- /dev/null +++ b/lib/puppet/faces/status.rb @@ -0,0 +1,4 @@ +require 'puppet/string/indirector' + +Puppet::String::Indirector.define(:status, '0.0.1') do +end diff --git a/lib/puppet/string.rb b/lib/puppet/string.rb deleted file mode 100644 index 517cf4506..000000000 --- a/lib/puppet/string.rb +++ /dev/null @@ -1,104 +0,0 @@ -require 'puppet' -require 'puppet/util/autoload' - -class Puppet::String - require 'puppet/string/string_collection' - - require 'puppet/string/action_manager' - include Puppet::String::ActionManager - extend Puppet::String::ActionManager - - require 'puppet/string/option_manager' - include Puppet::String::OptionManager - extend Puppet::String::OptionManager - - include Puppet::Util - - class << self - # This is just so we can search for actions. We only use its - # list of directories to search. - # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb - def autoloader - @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/string") - end - - def strings - Puppet::String::StringCollection.strings - end - - def string?(name, version) - Puppet::String::StringCollection.string?(name, version) - end - - def register(instance) - Puppet::String::StringCollection.register(instance) - end - - def define(name, version, &block) - if string?(name, version) - string = Puppet::String::StringCollection[name, version] - else - string = self.new(name, version) - Puppet::String::StringCollection.register(string) - string.load_actions - end - - string.instance_eval(&block) if block_given? - - return string - end - - alias :[] :define - end - - attr_accessor :default_format - - def set_default_format(format) - self.default_format = format.to_sym - end - - attr_accessor :type, :verb, :version, :arguments - attr_reader :name - - def initialize(name, version, &block) - unless Puppet::String::StringCollection.validate_version(version) - raise ArgumentError, "Cannot create string #{name.inspect} with invalid version number '#{version}'!" - end - - @name = Puppet::String::StringCollection.underscorize(name) - @version = version - @default_format = :pson - - instance_eval(&block) if block_given? - end - - # Try to find actions defined in other files. - def load_actions - path = "puppet/string/#{name}" - - loaded = [] - [path, "#{name}@#{version}/#{path}"].each do |path| - Puppet::String.autoloader.search_directories.each do |dir| - fdir = ::File.join(dir, path) - next unless FileTest.directory?(fdir) - - Dir.chdir(fdir) do - Dir.glob("*.rb").each do |file| - aname = file.sub(/\.rb/, '') - if loaded.include?(aname) - Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - next - end - loaded << aname - Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - require "#{Dir.pwd}/#{aname}" - end - end - end - end - end - - def to_s - "Puppet::String[#{name.inspect}, #{version.inspect}]" - end -end diff --git a/lib/puppet/string/action.rb b/lib/puppet/string/action.rb deleted file mode 100644 index 0f5032ffb..000000000 --- a/lib/puppet/string/action.rb +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: utf-8 -*- -require 'puppet/string' -require 'puppet/string/option' - -class Puppet::String::Action - attr_reader :name - - def to_s - "#{@string}##{@name}" - end - - def initialize(string, name, attrs = {}) - raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ - @string = string - @name = name.to_sym - @options = {} - attrs.each do |k, v| send("#{k}=", v) end - end - - # Initially, this was defined to allow the @action.invoke pattern, which is - # a very natural way to invoke behaviour given our introspection - # capabilities. Heck, our initial plan was to have the string delegate to - # the action object for invocation and all. - # - # It turns out that we have a binding problem to solve: @string was bound to - # the parent class, not the subclass instance, and we don't pass the - # appropriate context or change the binding enough to make this work. - # - # We could hack around it, by either mandating that you pass the context in - # to invoke, or try to get the binding right, but that has probably got - # subtleties that we don't instantly think of – especially around threads. - # - # So, we are pulling this method for now, and will return it to life when we - # have the time to resolve the problem. For now, you should replace... - # - # @action = @string.get_action(name) - # @action.invoke(arg1, arg2, arg3) - # - # ...with... - # - # @action = @string.get_action(name) - # @string.send(@action.name, arg1, arg2, arg3) - # - # I understand that is somewhat cumbersome, but it functions as desired. - # --daniel 2011-03-31 - # - # PS: This code is left present, but commented, to support this chunk of - # documentation, for the benefit of the reader. - # - # def invoke(*args, &block) - # @string.send(name, *args, &block) - # end - - def when_invoked=(block) - # We need to build an instance method as a wrapper, using normal code, to - # be able to expose argument defaulting between the caller and definer in - # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. - # - # In future this also gives us a place to hook in additional behaviour - # such as calling out to the action instance to validate and coerce - # parameters, which avoids any exciting context switching and all. - # - # Hopefully we can improve this when we finally shuffle off the last of - # Ruby 1.8 support, but that looks to be a few "enterprise" release eras - # away, so we are pretty stuck with this for now. - # - # Patches to make this work more nicely with Ruby 1.9 using runtime - # version checking and all are welcome, but they can't actually help if - # the results are not totally hidden away in here. - # - # Incidentally, we though about vendoring evil-ruby and actually adjusting - # the internal C structure implementation details under the hood to make - # this stuff work, because it would have been cleaner. Which gives you an - # idea how motivated we were to make this cleaner. Sorry. --daniel 2011-03-31 - - internal_name = "#{@name} implementation, required on Ruby 1.8".to_sym - file = __FILE__ + "+eval" - line = __LINE__ + 1 - wrapper = "def #{@name}(*args, &block) - args << {} unless args.last.is_a? Hash - args << block if block_given? - self.__send__(#{internal_name.inspect}, *args) - end" - - if @string.is_a?(Class) - @string.class_eval do eval wrapper, nil, file, line end - @string.define_method(internal_name, &block) - else - @string.instance_eval do eval wrapper, nil, file, line end - @string.meta_def(internal_name, &block) - end - end - - def add_option(option) - option.aliases.each do |name| - if conflict = get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - elsif conflict = @string.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@string}" - end - end - - option.aliases.each do |name| - @options[name] = option - end - - option - end - - def option?(name) - @options.include? name.to_sym - end - - def options - (@options.keys + @string.options).sort - end - - def get_option(name) - @options[name.to_sym] || @string.get_option(name) - end -end diff --git a/lib/puppet/string/action_builder.rb b/lib/puppet/string/action_builder.rb deleted file mode 100644 index e7c03273b..000000000 --- a/lib/puppet/string/action_builder.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'puppet/string' -require 'puppet/string/action' - -class Puppet::String::ActionBuilder - attr_reader :action - - def self.build(string, name, &block) - raise "Action #{name.inspect} must specify a block" unless block - new(string, name, &block).action - end - - private - 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 when_invoked(&block) - raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action - @action.when_invoked = block - end - - def option(*declaration, &block) - option = Puppet::String::OptionBuilder.build(@action, *declaration, &block) - @action.add_option(option) - end -end diff --git a/lib/puppet/string/action_manager.rb b/lib/puppet/string/action_manager.rb deleted file mode 100644 index 9f0aa7582..000000000 --- a/lib/puppet/string/action_manager.rb +++ /dev/null @@ -1,49 +0,0 @@ -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 ||= {} - raise "Action #{name} already defined for #{self}" if action?(name) - action = Puppet::String::ActionBuilder.build(self, name, &block) - @actions[action.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 ||= {} - raise "Action #{name} already defined for #{self}" if action?(name) - @actions[name] = Puppet::String::Action.new(self, name, :when_invoked => 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 ||= {} - result = @actions[name.to_sym] - if result.nil? - if self.is_a?(Class) and superclass.respond_to?(:get_action) - result = superclass.get_action(name) - elsif self.class.respond_to?(:get_action) - result = self.class.get_action(name) - end - end - return result - end - - def action?(name) - actions.include?(name.to_sym) - end -end diff --git a/lib/puppet/string/catalog.rb b/lib/puppet/string/catalog.rb deleted file mode 100644 index 441c7ee7d..000000000 --- a/lib/puppet/string/catalog.rb +++ /dev/null @@ -1,40 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:catalog, '0.0.1') do - action(:apply) do - when_invoked do |catalog, options| - 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 - when_invoked do |certname, facts, options| - 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/catalog/select.rb b/lib/puppet/string/catalog/select.rb deleted file mode 100644 index 11670e2e7..000000000 --- a/lib/puppet/string/catalog/select.rb +++ /dev/null @@ -1,10 +0,0 @@ -# Select and show a list of resources of a given type. -Puppet::String.define(:catalog, '0.0.1') do - action :select do - when_invoked do |host, type, options| - 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/certificate.rb b/lib/puppet/string/certificate.rb deleted file mode 100644 index e8773ae2e..000000000 --- a/lib/puppet/string/certificate.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'puppet/string/indirector' -require 'puppet/ssl/host' - -Puppet::String::Indirector.define(:certificate, '0.0.1') do - # REVISIT: This should use a pre-invoke hook to run the common code that - # needs to happen before we invoke any action; that would be much nicer than - # the "please repeat yourself" stuff found in here right now. - # - # option "--ca-location LOCATION" do - # type [:whatever, :location, :symbols] - # hook :before do |value| - # Puppet::SSL::Host.ca_location = value - # end - # end - # - # ...but should I pass the arguments as well? - # --daniel 2011-04-05 - option "--ca-location LOCATION" - - action :generate do - when_invoked do |name, options| - Puppet::SSL::Host.ca_location = options[:ca_location].to_sym - host = Puppet::SSL::Host.new(name) - host.generate_certificate_request - host.certificate_request.class.indirection.save(host.certificate_request) - end - end - - action :list do - when_invoked do |options| - Puppet::SSL::Host.ca_location = options[:ca_location].to_sym - Puppet::SSL::Host.indirection.search("*", { - :for => :certificate_request, - }).map { |h| h.inspect } - end - end - - action :sign do - when_invoked do |name, options| - Puppet::SSL::Host.ca_location = options[:ca_location].to_sym - host = Puppet::SSL::Host.new(name) - host.desired_state = 'signed' - Puppet::SSL::Host.indirection.save(host) - end - end -end diff --git a/lib/puppet/string/certificate_request.rb b/lib/puppet/string/certificate_request.rb deleted file mode 100644 index 218b40b98..000000000 --- a/lib/puppet/string/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:certificate_request, '0.0.1') do -end diff --git a/lib/puppet/string/certificate_revocation_list.rb b/lib/puppet/string/certificate_revocation_list.rb deleted file mode 100644 index 9731b4f2d..000000000 --- a/lib/puppet/string/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:certificate_revocation_list, '0.0.1') do -end diff --git a/lib/puppet/string/config.rb b/lib/puppet/string/config.rb deleted file mode 100644 index 8a9417148..000000000 --- a/lib/puppet/string/config.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/string' - -Puppet::String.define(:config, '0.0.1') do - action(:print) do - when_invoked do |*args| - options = args.pop - Puppet.settings[:configprint] = args.join(",") - Puppet.settings.print_config_options - nil - end - end -end diff --git a/lib/puppet/string/configurer.rb b/lib/puppet/string/configurer.rb deleted file mode 100644 index 257f97e90..000000000 --- a/lib/puppet/string/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/string' - -Puppet::String.define(:configurer, '0.0.1') do - action(:synchronize) do - when_invoked do |certname, options| - 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/facts.rb b/lib/puppet/string/facts.rb deleted file mode 100644 index 6bd9904b0..000000000 --- a/lib/puppet/string/facts.rb +++ /dev/null @@ -1,18 +0,0 @@ -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 - when_invoked do |options| - 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/file.rb b/lib/puppet/string/file.rb deleted file mode 100644 index cc5737f28..000000000 --- a/lib/puppet/string/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -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/indirector.rb b/lib/puppet/string/indirector.rb deleted file mode 100644 index 0c7d043bb..000000000 --- a/lib/puppet/string/indirector.rb +++ /dev/null @@ -1,94 +0,0 @@ -require 'puppet' -require 'puppet/string' - -class Puppet::String::Indirector < Puppet::String - option "--terminus TERMINUS" do - desc "REVISIT: You can select a terminus, which has some bigger effect -that we should describe in this file somehow." - end - - 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 - - def call_indirection_method(method, *args) - options = args.pop - options.has_key?(:terminus) and set_terminus(options[:terminus]) - - begin - result = indirection.__send__(method, *args) - rescue => detail - puts detail.backtrace if Puppet[:trace] - raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" - end - - indirection.reset_terminus_class - return result - end - - action :destroy do - when_invoked { |*args| call_indirection_method(:destroy, *args) } - end - - action :find do - when_invoked { |*args| call_indirection_method(:find, *args) } - end - - action :save do - when_invoked { |*args| call_indirection_method(:save, *args) } - end - - action :search do - when_invoked { |*args| call_indirection_method(:search, *args) } - end - - # Print the configuration for the current terminus class - action :info do - when_invoked do |*args| - options = args.pop - options.has_key?(:terminus) and set_terminus(options[:terminus]) - - 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 - - indirection.reset_terminus_class - 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 - @indirection = Puppet::Indirector::Indirection.instance(indirection_name) - @indirection or raise "Could not find terminus for #{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 #{self.class.terminus_classes(indirection.name).join(", ") }" - end - end -end diff --git a/lib/puppet/string/key.rb b/lib/puppet/string/key.rb deleted file mode 100644 index 95aceade5..000000000 --- a/lib/puppet/string/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:key, '0.0.1') do -end diff --git a/lib/puppet/string/node.rb b/lib/puppet/string/node.rb deleted file mode 100644 index bc31a2cf3..000000000 --- a/lib/puppet/string/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:node, '0.0.1') do - set_default_format :yaml -end diff --git a/lib/puppet/string/option.rb b/lib/puppet/string/option.rb deleted file mode 100644 index 352f7e5ef..000000000 --- a/lib/puppet/string/option.rb +++ /dev/null @@ -1,82 +0,0 @@ -require 'puppet/string' - -class Puppet::String::Option - attr_reader :parent - attr_reader :name - attr_reader :aliases - attr_reader :optparse - attr_accessor :desc - - def takes_argument? - !!@argument - end - def optional_argument? - !!@optional_argument - end - - def initialize(parent, *declaration, &block) - @parent = parent - @optparse = [] - - # Collect and sort the arguments in the declaration. - dups = {} - declaration.each do |item| - if item.is_a? String and item.to_s =~ /^-/ then - unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then - raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" - end - @optparse << item - - # Duplicate checking... - name = optparse_to_name(item) - if dup = dups[name] then - raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" - else - dups[name] = item - end - else - raise ArgumentError, "#{item.inspect} is not valid for an option argument" - end - end - - if @optparse.empty? then - raise ArgumentError, "No option declarations found while building" - end - - # Now, infer the name from the options; we prefer the first long option as - # the name, rather than just the first option. - @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) - @aliases = @optparse.map { |o| optparse_to_name(o) } - - # Do we take an argument? If so, are we consistent about it, because - # incoherence here makes our life super-difficult, and we can more easily - # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 - @argument = @optparse.any? { |o| o =~ /[ =]/ } - if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then - raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" - end - - # Is our argument optional? The rules about consistency apply here, also, - # just like they do to taking arguments at all. --daniel 2011-03-30 - @optional_argument = @optparse.any? { |o| o.include? "[" } - if @optional_argument and not @optparse.all? { |o| o.include? "[" } then - raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" - end - end - - # to_s and optparse_to_name are roughly mirrored, because they are used to - # transform strings to name symbols, and vice-versa. This isn't a full - # bidirectional transformation though. - def to_s - @name.to_s.tr('_', '-') - end - - def optparse_to_name(declaration) - unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then - raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" - end - name = found.captures.first.tr('-', '_') - raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ - name.to_sym - end -end diff --git a/lib/puppet/string/option_builder.rb b/lib/puppet/string/option_builder.rb deleted file mode 100644 index da0d213fb..000000000 --- a/lib/puppet/string/option_builder.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'puppet/string/option' - -class Puppet::String::OptionBuilder - attr_reader :option - - def self.build(string, *declaration, &block) - new(string, *declaration, &block).option - end - - private - def initialize(string, *declaration, &block) - @string = string - @option = Puppet::String::Option.new(string, *declaration) - block and instance_eval(&block) - @option - end - - # Metaprogram the simple DSL from the option class. - Puppet::String::Option.instance_methods.grep(/=$/).each do |setter| - next if setter =~ /^=/ # special case, darn it... - - dsl = setter.sub(/=$/, '') - define_method(dsl) do |value| @option.send(setter, value) end - end -end diff --git a/lib/puppet/string/option_manager.rb b/lib/puppet/string/option_manager.rb deleted file mode 100644 index f952ad4f0..000000000 --- a/lib/puppet/string/option_manager.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'puppet/string/option_builder' - -module Puppet::String::OptionManager - # Declare that this app can take a specific option, and provide - # the code to do so. - def option(*declaration, &block) - add_option Puppet::String::OptionBuilder.build(self, *declaration, &block) - end - - def add_option(option) - option.aliases.each do |name| - if conflict = get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - end - - actions.each do |action| - action = get_action(action) - if conflict = action.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{action}" - end - end - end - - option.aliases.each { |name| @options[name] = option } - option - end - - def options - @options ||= {} - result = @options.keys - - if self.is_a?(Class) and superclass.respond_to?(:options) - result += superclass.options - elsif self.class.respond_to?(:options) - result += self.class.options - end - result.sort - end - - def get_option(name) - @options ||= {} - result = @options[name.to_sym] - unless result then - if self.is_a?(Class) and superclass.respond_to?(:get_option) - result = superclass.get_option(name) - elsif self.class.respond_to?(:get_option) - result = self.class.get_option(name) - end - end - return result - end - - def option?(name) - options.include? name.to_sym - end -end diff --git a/lib/puppet/string/report.rb b/lib/puppet/string/report.rb deleted file mode 100644 index da3ca8504..000000000 --- a/lib/puppet/string/report.rb +++ /dev/null @@ -1,15 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:report, '0.0.1') do - action(:submit) do - when_invoked do |report, options| - 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/resource.rb b/lib/puppet/string/resource.rb deleted file mode 100644 index 9838be0fa..000000000 --- a/lib/puppet/string/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:resource, '0.0.1') do -end diff --git a/lib/puppet/string/resource_type.rb b/lib/puppet/string/resource_type.rb deleted file mode 100644 index 8ca31ea6c..000000000 --- a/lib/puppet/string/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:resource_type, '0.0.1') do -end diff --git a/lib/puppet/string/status.rb b/lib/puppet/string/status.rb deleted file mode 100644 index 41de2bb99..000000000 --- a/lib/puppet/string/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/string/indirector' - -Puppet::String::Indirector.define(:status, '0.0.1') do -end diff --git a/lib/puppet/string/string_collection.rb b/lib/puppet/string/string_collection.rb deleted file mode 100644 index ecd99359d..000000000 --- a/lib/puppet/string/string_collection.rb +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- -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.validate_version(version) - !!(SEMVER_VERSION =~ version.to_s) - end - - def self.cmp_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) - @strings[underscorize(name)][version] if string?(name, version) - end - - def self.string?(name, version) - name = underscorize(name) - return true if @strings[name].has_key?(version) - - # We always load the current version file; the common case is that we have - # the expected version and any compatibility versions in the same file, - # the default. Which means that this is almost always the case. - # - # We use require to avoid executing the code multiple times, like any - # other Ruby library that we might want to use. --daniel 2011-04-06 - begin - require "puppet/string/#{name}" - - # If we wanted :current, we need to index to find that; direct version - # requests just work™ as they go. --daniel 2011-04-06 - if version == :current then - # We need to find current out of this. This is the largest version - # number that doesn't have a dedicated on-disk file present; those - # represent "experimental" versions of strings, which we don't fully - # support yet. - # - # We walk the versions from highest to lowest and take the first version - # that is not defined in an explicitly versioned file on disk as the - # current version. - # - # This constrains us to only ship experimental versions with *one* - # version in the file, not multiple, but given you can't reliably load - # them except by side-effect when you ignore that rule this seems safe - # enough... - # - # Given those constraints, and that we are not going to ship a versioned - # interface that is not :current in this release, we are going to leave - # these thoughts in place, and just punt on the actual versioning. - # - # When we upgrade the core to support multiple versions we can solve the - # problems then; as lazy as possible. - # - # We do support multiple versions in the same file, though, so we sort - # versions here and return the last item in that set. - # - # --daniel 2011-04-06 - latest_ver = @strings[name].keys.sort {|a, b| cmp_versions(a, b) }.last - @strings[name][:current] = @strings[name][latest_ver] - end - rescue LoadError => e - raise unless e.message =~ %r{-- puppet/string/#{name}$} - # ...guess we didn't find the file; return a much better problem. - end - - # Now, either we have the version in our set of strings, or we didn't find - # the version they were looking for. In the future we will support - # loading versioned stuff from some look-aside part of the Ruby load path, - # but we don't need that right now. - # - # So, this comment is a place-holder for that. --daniel 2011-04-06 - return !! @strings[name].has_key?(version) - 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 -- cgit From 8d144d0bf5116c5f04522f2b4cd75699f6480f8e Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 7 Apr 2011 14:20:35 -0700 Subject: (#7012) Update references in code to use face(s) The codebase is now using the new name, faces, uniformly to reference the objects contained. All tests pass. --- lib/puppet/application/config.rb | 4 +- lib/puppet/application/configurer.rb | 6 +- lib/puppet/application/faces.rb | 18 ++-- lib/puppet/application/faces_base.rb | 24 ++--- lib/puppet/application/indirection_base.rb | 4 +- lib/puppet/faces.rb | 56 ++++++----- lib/puppet/faces/action.rb | 50 +++++----- lib/puppet/faces/action_builder.rb | 22 ++--- lib/puppet/faces/action_manager.rb | 8 +- lib/puppet/faces/catalog.rb | 6 +- lib/puppet/faces/catalog/select.rb | 2 +- lib/puppet/faces/certificate.rb | 4 +- lib/puppet/faces/certificate_request.rb | 4 +- lib/puppet/faces/certificate_revocation_list.rb | 4 +- lib/puppet/faces/config.rb | 4 +- lib/puppet/faces/configurer.rb | 10 +- lib/puppet/faces/face_collection.rb | 125 ++++++++++++++++++++++++ lib/puppet/faces/faces_collection.rb | 123 ----------------------- lib/puppet/faces/facts.rb | 4 +- lib/puppet/faces/file.rb | 4 +- lib/puppet/faces/indirector.rb | 10 +- lib/puppet/faces/key.rb | 4 +- lib/puppet/faces/node.rb | 4 +- lib/puppet/faces/option.rb | 8 +- lib/puppet/faces/option_builder.rb | 16 +-- lib/puppet/faces/option_manager.rb | 6 +- lib/puppet/faces/report.rb | 4 +- lib/puppet/faces/resource.rb | 4 +- lib/puppet/faces/resource_type.rb | 4 +- lib/puppet/faces/status.rb | 4 +- 30 files changed, 274 insertions(+), 272 deletions(-) create mode 100644 lib/puppet/faces/face_collection.rb delete mode 100644 lib/puppet/faces/faces_collection.rb (limited to 'lib/puppet') diff --git a/lib/puppet/application/config.rb b/lib/puppet/application/config.rb index f6559277b..41a46c339 100644 --- a/lib/puppet/application/config.rb +++ b/lib/puppet/application/config.rb @@ -1,4 +1,4 @@ -require 'puppet/application/string_base' +require 'puppet/application/faces_base' -class Puppet::Application::Config < Puppet::Application::StringBase +class Puppet::Application::Config < Puppet::Application::FacesBase end diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index be018338f..751e6b4d7 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -1,5 +1,5 @@ require 'puppet/application' -require 'puppet/string' +require 'puppet/faces' class Puppet::Application::Configurer < Puppet::Application should_parse_config @@ -17,7 +17,7 @@ class Puppet::Application::Configurer < Puppet::Application end def run_command - report = Puppet::String[:configurer, '0.0.1'].synchronize(Puppet[:certname]) - Puppet::String[:report, '0.0.1'].submit(report) + report = Puppet::Faces[:configurer, '0.0.1'].synchronize(Puppet[:certname]) + Puppet::Faces[:report, '0.0.1'].submit(report) end end diff --git a/lib/puppet/application/faces.rb b/lib/puppet/application/faces.rb index 0a6a798ce..904a0cccc 100644 --- a/lib/puppet/application/faces.rb +++ b/lib/puppet/application/faces.rb @@ -1,7 +1,7 @@ require 'puppet/application' -require 'puppet/string' +require 'puppet/faces' -class Puppet::Application::String < Puppet::Application +class Puppet::Application::Faces < Puppet::Application should_parse_config run_mode :agent @@ -18,7 +18,7 @@ class Puppet::Application::String < Puppet::Application if arguments.empty? arguments = %w{terminuses actions} end - strings.each do |name| + faces.each do |name| str = "#{name}:\n" if arguments.include?("terminuses") begin @@ -68,12 +68,12 @@ class Puppet::Application::String < Puppet::Application end unless respond_to?(verb) - raise "Command '#{verb}' not found for 'string'" + raise "Command '#{verb}' not found for 'faces'" end end - def strings - Puppet::String.strings + def faces + Puppet::Faces.faces end def terminus_classes(indirection) @@ -81,9 +81,9 @@ class Puppet::Application::String < Puppet::Application end def actions(indirection) - return [] unless string = Puppet::String[indirection, '0.0.1'] - string.load_actions - return string.actions.sort { |a, b| a.to_s <=> b.to_s } + return [] unless faces = Puppet::Faces[indirection, '0.0.1'] + faces.load_actions + return faces.actions.sort { |a, b| a.to_s <=> b.to_s } end def load_applications diff --git a/lib/puppet/application/faces_base.rb b/lib/puppet/application/faces_base.rb index 09d02c079..6d66ee8a1 100644 --- a/lib/puppet/application/faces_base.rb +++ b/lib/puppet/application/faces_base.rb @@ -1,7 +1,7 @@ require 'puppet/application' -require 'puppet/string' +require 'puppet/faces' -class Puppet::Application::StringBase < Puppet::Application +class Puppet::Application::FacesBase < Puppet::Application should_parse_config run_mode :agent @@ -24,7 +24,7 @@ class Puppet::Application::StringBase < Puppet::Application end - attr_accessor :string, :action, :type, :arguments, :format + attr_accessor :face, :action, :type, :arguments, :format attr_writer :exit_code # This allows you to set the exit code if you don't want to just exit @@ -47,7 +47,7 @@ class Puppet::Application::StringBase < Puppet::Application def preinit super trap(:INT) do - $stderr.puts "Cancelling String" + $stderr.puts "Cancelling Face" exit(0) end @@ -57,8 +57,8 @@ class Puppet::Application::StringBase < Puppet::Application # TODO: These should be configurable versions, through a global # '--version' option, but we don't implement that yet... --daniel 2011-03-29 @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - @string = Puppet::String[@type, :current] - @format = @string.default_format + @face = Puppet::Faces[@type, :current] + @format = @face.default_format # Now, walk the command line and identify the action. We skip over # arguments based on introspecting the action and all, and find the first @@ -68,11 +68,11 @@ class Puppet::Application::StringBase < Puppet::Application until @action or (index += 1) >= command_line.args.length do item = command_line.args[index] if item =~ /^-/ then - option = @string.options.find do |name| + option = @face.options.find do |name| item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/ end if option then - option = @string.get_option(option) + option = @face.get_option(option) # If we have an inline argument, just carry on. We don't need to # care about optional vs mandatory in that case because we do a real # parse later, and that will totally take care of raising the error @@ -91,9 +91,9 @@ class Puppet::Application::StringBase < Puppet::Application raise ArgumentError, "Unknown option #{item.sub(/=.*$/, '').inspect}" end else - action = @string.get_action(item.to_sym) + action = @face.get_action(item.to_sym) if action.nil? then - raise ArgumentError, "#{@string} does not have an #{item.inspect} action!" + raise ArgumentError, "#{@face} does not have an #{item.inspect} action!" end @action = action end @@ -129,7 +129,7 @@ class Puppet::Application::StringBase < Puppet::Application # Note: because of our definition of where the action is set, we end up # with it *always* being the first word of the remaining set of command # line arguments. So, strip that off when we construct the arguments to - # pass down to the string action. --daniel 2011-04-04 + # pass down to the face action. --daniel 2011-04-04 @arguments.delete_at(0) # We copy all of the app options to the end of the call; This allows each @@ -142,7 +142,7 @@ class Puppet::Application::StringBase < Puppet::Application def main # Call the method associated with the provided action (e.g., 'find'). - if result = @string.send(@action.name, *arguments) + if result = @face.send(@action.name, *arguments) puts render(result) end exit(exit_code) diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index cfa1ea529..7455ebedf 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -1,4 +1,4 @@ -require 'puppet/application/string_base' +require 'puppet/application/faces_base' -class Puppet::Application::IndirectionBase < Puppet::Application::StringBase +class Puppet::Application::IndirectionBase < Puppet::Application::FacesBase end diff --git a/lib/puppet/faces.rb b/lib/puppet/faces.rb index 517cf4506..07a745480 100644 --- a/lib/puppet/faces.rb +++ b/lib/puppet/faces.rb @@ -1,16 +1,16 @@ require 'puppet' require 'puppet/util/autoload' -class Puppet::String - require 'puppet/string/string_collection' +class Puppet::Faces + require 'puppet/faces/face_collection' - require 'puppet/string/action_manager' - include Puppet::String::ActionManager - extend Puppet::String::ActionManager + require 'puppet/faces/action_manager' + include Puppet::Faces::ActionManager + extend Puppet::Faces::ActionManager - require 'puppet/string/option_manager' - include Puppet::String::OptionManager - extend Puppet::String::OptionManager + require 'puppet/faces/option_manager' + include Puppet::Faces::OptionManager + extend Puppet::Faces::OptionManager include Puppet::Util @@ -19,33 +19,35 @@ class Puppet::String # list of directories to search. # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb def autoloader - @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/string") + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/faces") end - def strings - Puppet::String::StringCollection.strings + def faces + Puppet::Faces::FaceCollection.faces end - def string?(name, version) - Puppet::String::StringCollection.string?(name, version) + def face?(name, version) + Puppet::Faces::FaceCollection.face?(name, version) end def register(instance) - Puppet::String::StringCollection.register(instance) + Puppet::Faces::FaceCollection.register(instance) end def define(name, version, &block) - if string?(name, version) - string = Puppet::String::StringCollection[name, version] + if face?(name, version) + face = Puppet::Faces::FaceCollection[name, version] else - string = self.new(name, version) - Puppet::String::StringCollection.register(string) - string.load_actions + face = self.new(name, version) + Puppet::Faces::FaceCollection.register(face) + # REVISIT: Shouldn't this be delayed until *after* we evaluate the + # current block, not done before? --daniel 2011-04-07 + face.load_actions end - string.instance_eval(&block) if block_given? + face.instance_eval(&block) if block_given? - return string + return face end alias :[] :define @@ -61,11 +63,11 @@ class Puppet::String attr_reader :name def initialize(name, version, &block) - unless Puppet::String::StringCollection.validate_version(version) - raise ArgumentError, "Cannot create string #{name.inspect} with invalid version number '#{version}'!" + unless Puppet::Faces::FaceCollection.validate_version(version) + raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!" end - @name = Puppet::String::StringCollection.underscorize(name) + @name = Puppet::Faces::FaceCollection.underscorize(name) @version = version @default_format = :pson @@ -74,11 +76,11 @@ class Puppet::String # Try to find actions defined in other files. def load_actions - path = "puppet/string/#{name}" + path = "puppet/faces/#{name}" loaded = [] [path, "#{name}@#{version}/#{path}"].each do |path| - Puppet::String.autoloader.search_directories.each do |dir| + Puppet::Faces.autoloader.search_directories.each do |dir| fdir = ::File.join(dir, path) next unless FileTest.directory?(fdir) @@ -99,6 +101,6 @@ class Puppet::String end def to_s - "Puppet::String[#{name.inspect}, #{version.inspect}]" + "Puppet::Faces[#{name.inspect}, #{version.inspect}]" end end diff --git a/lib/puppet/faces/action.rb b/lib/puppet/faces/action.rb index 0f5032ffb..58d2c6003 100644 --- a/lib/puppet/faces/action.rb +++ b/lib/puppet/faces/action.rb @@ -1,28 +1,26 @@ # -*- coding: utf-8 -*- -require 'puppet/string' -require 'puppet/string/option' +require 'puppet/faces' +require 'puppet/faces/option' -class Puppet::String::Action - attr_reader :name - - def to_s - "#{@string}##{@name}" - end - - def initialize(string, name, attrs = {}) +class Puppet::Faces::Action + def initialize(face, name, attrs = {}) raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ - @string = string + @face = face @name = name.to_sym @options = {} attrs.each do |k, v| send("#{k}=", v) end end + attr_reader :name + def to_s() "#{@face}##{@name}" end + + # Initially, this was defined to allow the @action.invoke pattern, which is # a very natural way to invoke behaviour given our introspection - # capabilities. Heck, our initial plan was to have the string delegate to + # capabilities. Heck, our initial plan was to have the faces delegate to # the action object for invocation and all. # - # It turns out that we have a binding problem to solve: @string was bound to + # It turns out that we have a binding problem to solve: @face was bound to # the parent class, not the subclass instance, and we don't pass the # appropriate context or change the binding enough to make this work. # @@ -33,13 +31,13 @@ class Puppet::String::Action # So, we are pulling this method for now, and will return it to life when we # have the time to resolve the problem. For now, you should replace... # - # @action = @string.get_action(name) + # @action = @face.get_action(name) # @action.invoke(arg1, arg2, arg3) # # ...with... # - # @action = @string.get_action(name) - # @string.send(@action.name, arg1, arg2, arg3) + # @action = @face.get_action(name) + # @face.send(@action.name, arg1, arg2, arg3) # # I understand that is somewhat cumbersome, but it functions as desired. # --daniel 2011-03-31 @@ -48,7 +46,7 @@ class Puppet::String::Action # documentation, for the benefit of the reader. # # def invoke(*args, &block) - # @string.send(name, *args, &block) + # @face.send(name, *args, &block) # end def when_invoked=(block) @@ -82,12 +80,12 @@ class Puppet::String::Action self.__send__(#{internal_name.inspect}, *args) end" - if @string.is_a?(Class) - @string.class_eval do eval wrapper, nil, file, line end - @string.define_method(internal_name, &block) + if @face.is_a?(Class) + @face.class_eval do eval wrapper, nil, file, line end + @face.define_method(internal_name, &block) else - @string.instance_eval do eval wrapper, nil, file, line end - @string.meta_def(internal_name, &block) + @face.instance_eval do eval wrapper, nil, file, line end + @face.meta_def(internal_name, &block) end end @@ -95,8 +93,8 @@ class Puppet::String::Action option.aliases.each do |name| if conflict = get_option(name) then raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - elsif conflict = @string.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@string}" + elsif conflict = @face.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@face}" end end @@ -112,10 +110,10 @@ class Puppet::String::Action end def options - (@options.keys + @string.options).sort + (@options.keys + @face.options).sort end def get_option(name) - @options[name.to_sym] || @string.get_option(name) + @options[name.to_sym] || @face.get_option(name) end end diff --git a/lib/puppet/faces/action_builder.rb b/lib/puppet/faces/action_builder.rb index e7c03273b..a67068926 100644 --- a/lib/puppet/faces/action_builder.rb +++ b/lib/puppet/faces/action_builder.rb @@ -1,31 +1,31 @@ -require 'puppet/string' -require 'puppet/string/action' +require 'puppet/faces' +require 'puppet/faces/action' -class Puppet::String::ActionBuilder +class Puppet::Faces::ActionBuilder attr_reader :action - def self.build(string, name, &block) + def self.build(face, name, &block) raise "Action #{name.inspect} must specify a block" unless block - new(string, name, &block).action + new(face, name, &block).action end private - def initialize(string, name, &block) - @string = string - @action = Puppet::String::Action.new(string, name) + def initialize(face, name, &block) + @face = face + @action = Puppet::Faces::Action.new(face, 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 + # method on the face would defer to it, but we can't get scope correct, so + # we stick with this. --daniel 2011-03-24 def when_invoked(&block) raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action @action.when_invoked = block end def option(*declaration, &block) - option = Puppet::String::OptionBuilder.build(@action, *declaration, &block) + option = Puppet::Faces::OptionBuilder.build(@action, *declaration, &block) @action.add_option(option) end end diff --git a/lib/puppet/faces/action_manager.rb b/lib/puppet/faces/action_manager.rb index 9f0aa7582..6c0036bd8 100644 --- a/lib/puppet/faces/action_manager.rb +++ b/lib/puppet/faces/action_manager.rb @@ -1,12 +1,12 @@ -require 'puppet/string/action_builder' +require 'puppet/faces/action_builder' -module Puppet::String::ActionManager +module Puppet::Faces::ActionManager # Declare that this app can take a specific action, and provide # the code to do so. def action(name, &block) @actions ||= {} raise "Action #{name} already defined for #{self}" if action?(name) - action = Puppet::String::ActionBuilder.build(self, name, &block) + action = Puppet::Faces::ActionBuilder.build(self, name, &block) @actions[action.name] = action end @@ -15,7 +15,7 @@ module Puppet::String::ActionManager def script(name, &block) @actions ||= {} raise "Action #{name} already defined for #{self}" if action?(name) - @actions[name] = Puppet::String::Action.new(self, name, :when_invoked => block) + @actions[name] = Puppet::Faces::Action.new(self, name, :when_invoked => block) end def actions diff --git a/lib/puppet/faces/catalog.rb b/lib/puppet/faces/catalog.rb index 441c7ee7d..2e2168ac4 100644 --- a/lib/puppet/faces/catalog.rb +++ b/lib/puppet/faces/catalog.rb @@ -1,6 +1,6 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:catalog, '0.0.1') do +Puppet::Faces::Indirector.define(:catalog, '0.0.1') do action(:apply) do when_invoked do |catalog, options| report = Puppet::Transaction::Report.new("apply") @@ -28,7 +28,7 @@ Puppet::String::Indirector.define(:catalog, '0.0.1') do 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) + catalog = Puppet::Faces[:catalog, '0.0.1'].find(certname, facts_to_upload) end catalog = catalog.to_ral catalog.finalize diff --git a/lib/puppet/faces/catalog/select.rb b/lib/puppet/faces/catalog/select.rb index 11670e2e7..e29d19970 100644 --- a/lib/puppet/faces/catalog/select.rb +++ b/lib/puppet/faces/catalog/select.rb @@ -1,5 +1,5 @@ # Select and show a list of resources of a given type. -Puppet::String.define(:catalog, '0.0.1') do +Puppet::Faces.define(:catalog, '0.0.1') do action :select do when_invoked do |host, type, options| catalog = Puppet::Resource::Catalog.indirection.find(host) diff --git a/lib/puppet/faces/certificate.rb b/lib/puppet/faces/certificate.rb index e8773ae2e..b10bee579 100644 --- a/lib/puppet/faces/certificate.rb +++ b/lib/puppet/faces/certificate.rb @@ -1,7 +1,7 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' require 'puppet/ssl/host' -Puppet::String::Indirector.define(:certificate, '0.0.1') do +Puppet::Faces::Indirector.define(:certificate, '0.0.1') do # REVISIT: This should use a pre-invoke hook to run the common code that # needs to happen before we invoke any action; that would be much nicer than # the "please repeat yourself" stuff found in here right now. diff --git a/lib/puppet/faces/certificate_request.rb b/lib/puppet/faces/certificate_request.rb index 218b40b98..5e91bdb7f 100644 --- a/lib/puppet/faces/certificate_request.rb +++ b/lib/puppet/faces/certificate_request.rb @@ -1,4 +1,4 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:certificate_request, '0.0.1') do +Puppet::Faces::Indirector.define(:certificate_request, '0.0.1') do end diff --git a/lib/puppet/faces/certificate_revocation_list.rb b/lib/puppet/faces/certificate_revocation_list.rb index 9731b4f2d..2f2d72874 100644 --- a/lib/puppet/faces/certificate_revocation_list.rb +++ b/lib/puppet/faces/certificate_revocation_list.rb @@ -1,4 +1,4 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:certificate_revocation_list, '0.0.1') do +Puppet::Faces::Indirector.define(:certificate_revocation_list, '0.0.1') do end diff --git a/lib/puppet/faces/config.rb b/lib/puppet/faces/config.rb index 8a9417148..647bf5052 100644 --- a/lib/puppet/faces/config.rb +++ b/lib/puppet/faces/config.rb @@ -1,6 +1,6 @@ -require 'puppet/string' +require 'puppet/faces' -Puppet::String.define(:config, '0.0.1') do +Puppet::Faces.define(:config, '0.0.1') do action(:print) do when_invoked do |*args| options = args.pop diff --git a/lib/puppet/faces/configurer.rb b/lib/puppet/faces/configurer.rb index 257f97e90..d40987697 100644 --- a/lib/puppet/faces/configurer.rb +++ b/lib/puppet/faces/configurer.rb @@ -1,11 +1,11 @@ -require 'puppet/string' +require 'puppet/faces' -Puppet::String.define(:configurer, '0.0.1') do +Puppet::Faces.define(:configurer, '0.0.1') do action(:synchronize) do when_invoked do |certname, options| - 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) + facts = Puppet::Faces[:facts, '0.0.1'].find(certname) + catalog = Puppet::Faces[:catalog, '0.0.1'].download(certname, facts) + report = Puppet::Faces[:catalog, '0.0.1'].apply(catalog) report end end diff --git a/lib/puppet/faces/face_collection.rb b/lib/puppet/faces/face_collection.rb new file mode 100644 index 000000000..e6ee709d6 --- /dev/null +++ b/lib/puppet/faces/face_collection.rb @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +require 'puppet/faces' + +module Puppet::Faces::FaceCollection + SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ + + @faces = Hash.new { |hash, key| hash[key] = {} } + + def self.faces + unless @loaded + @loaded = true + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + Dir.chdir(dir) do + # REVISIT: This is wrong!!!! We don't name files like that ever, + # so we should no longer match things like this. Damnit!!! --daniel 2011-04-07 + Dir.glob("puppet/faces/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 @faces.keys + end + + def self.validate_version(version) + !!(SEMVER_VERSION =~ version.to_s) + end + + def self.cmp_semver(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) + @faces[underscorize(name)][version] if face?(name, version) + end + + def self.face?(name, version) + name = underscorize(name) + return true if @faces[name].has_key?(version) + + # We always load the current version file; the common case is that we have + # the expected version and any compatibility versions in the same file, + # the default. Which means that this is almost always the case. + # + # We use require to avoid executing the code multiple times, like any + # other Ruby library that we might want to use. --daniel 2011-04-06 + begin + require "puppet/faces/#{name}" + + # If we wanted :current, we need to index to find that; direct version + # requests just work™ as they go. --daniel 2011-04-06 + if version == :current then + # We need to find current out of this. This is the largest version + # number that doesn't have a dedicated on-disk file present; those + # represent "experimental" versions of faces, which we don't fully + # support yet. + # + # We walk the versions from highest to lowest and take the first version + # that is not defined in an explicitly versioned file on disk as the + # current version. + # + # This constrains us to only ship experimental versions with *one* + # version in the file, not multiple, but given you can't reliably load + # them except by side-effect when you ignore that rule this seems safe + # enough... + # + # Given those constraints, and that we are not going to ship a versioned + # interface that is not :current in this release, we are going to leave + # these thoughts in place, and just punt on the actual versioning. + # + # When we upgrade the core to support multiple versions we can solve the + # problems then; as lazy as possible. + # + # We do support multiple versions in the same file, though, so we sort + # versions here and return the last item in that set. + # + # --daniel 2011-04-06 + latest_ver = @faces[name].keys.sort {|a, b| cmp_semver(a, b) }.last + @faces[name][:current] = @faces[name][latest_ver] + end + rescue LoadError => e + raise unless e.message =~ %r{-- puppet/faces/#{name}$} + # ...guess we didn't find the file; return a much better problem. + end + + # Now, either we have the version in our set of faces, or we didn't find + # the version they were looking for. In the future we will support + # loading versioned stuff from some look-aside part of the Ruby load path, + # but we don't need that right now. + # + # So, this comment is a place-holder for that. --daniel 2011-04-06 + return !! @faces[name].has_key?(version) + end + + def self.register(face) + @faces[underscorize(face.name)][face.version] = face + end + + def self.underscorize(name) + unless name.to_s =~ /^[-_a-z]+$/i then + raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid face name" + end + + name.to_s.downcase.split(/[-_]/).join('_').to_sym + end +end diff --git a/lib/puppet/faces/faces_collection.rb b/lib/puppet/faces/faces_collection.rb deleted file mode 100644 index ecd99359d..000000000 --- a/lib/puppet/faces/faces_collection.rb +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- -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.validate_version(version) - !!(SEMVER_VERSION =~ version.to_s) - end - - def self.cmp_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) - @strings[underscorize(name)][version] if string?(name, version) - end - - def self.string?(name, version) - name = underscorize(name) - return true if @strings[name].has_key?(version) - - # We always load the current version file; the common case is that we have - # the expected version and any compatibility versions in the same file, - # the default. Which means that this is almost always the case. - # - # We use require to avoid executing the code multiple times, like any - # other Ruby library that we might want to use. --daniel 2011-04-06 - begin - require "puppet/string/#{name}" - - # If we wanted :current, we need to index to find that; direct version - # requests just work™ as they go. --daniel 2011-04-06 - if version == :current then - # We need to find current out of this. This is the largest version - # number that doesn't have a dedicated on-disk file present; those - # represent "experimental" versions of strings, which we don't fully - # support yet. - # - # We walk the versions from highest to lowest and take the first version - # that is not defined in an explicitly versioned file on disk as the - # current version. - # - # This constrains us to only ship experimental versions with *one* - # version in the file, not multiple, but given you can't reliably load - # them except by side-effect when you ignore that rule this seems safe - # enough... - # - # Given those constraints, and that we are not going to ship a versioned - # interface that is not :current in this release, we are going to leave - # these thoughts in place, and just punt on the actual versioning. - # - # When we upgrade the core to support multiple versions we can solve the - # problems then; as lazy as possible. - # - # We do support multiple versions in the same file, though, so we sort - # versions here and return the last item in that set. - # - # --daniel 2011-04-06 - latest_ver = @strings[name].keys.sort {|a, b| cmp_versions(a, b) }.last - @strings[name][:current] = @strings[name][latest_ver] - end - rescue LoadError => e - raise unless e.message =~ %r{-- puppet/string/#{name}$} - # ...guess we didn't find the file; return a much better problem. - end - - # Now, either we have the version in our set of strings, or we didn't find - # the version they were looking for. In the future we will support - # loading versioned stuff from some look-aside part of the Ruby load path, - # but we don't need that right now. - # - # So, this comment is a place-holder for that. --daniel 2011-04-06 - return !! @strings[name].has_key?(version) - 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/faces/facts.rb b/lib/puppet/faces/facts.rb index 6bd9904b0..33eacef38 100644 --- a/lib/puppet/faces/facts.rb +++ b/lib/puppet/faces/facts.rb @@ -1,7 +1,7 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' require 'puppet/node/facts' -Puppet::String::Indirector.define(:facts, '0.0.1') do +Puppet::Faces::Indirector.define(:facts, '0.0.1') do set_default_format :yaml # Upload our facts to the server diff --git a/lib/puppet/faces/file.rb b/lib/puppet/faces/file.rb index cc5737f28..e8ad18c17 100644 --- a/lib/puppet/faces/file.rb +++ b/lib/puppet/faces/file.rb @@ -1,5 +1,5 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:file, '0.0.1') do +Puppet::Faces::Indirector.define(:file, '0.0.1') do set_indirection_name :file_bucket_file end diff --git a/lib/puppet/faces/indirector.rb b/lib/puppet/faces/indirector.rb index 0c7d043bb..f72260017 100644 --- a/lib/puppet/faces/indirector.rb +++ b/lib/puppet/faces/indirector.rb @@ -1,7 +1,7 @@ require 'puppet' -require 'puppet/string' +require 'puppet/faces' -class Puppet::String::Indirector < Puppet::String +class Puppet::Faces::Indirector < Puppet::Faces option "--terminus TERMINUS" do desc "REVISIT: You can select a terminus, which has some bigger effect that we should describe in this file somehow." @@ -68,13 +68,13 @@ that we should describe in this file somehow." @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. + # Here's your opportunity to override the indirection name. By default it + # will be the same name as the face. def set_indirection_name(name) @indirection_name = name end - # Return an indirection associated with an string, if one exists + # Return an indirection associated with a face, if one exists; # One usually does. def indirection unless @indirection diff --git a/lib/puppet/faces/key.rb b/lib/puppet/faces/key.rb index 95aceade5..7b6ad52ac 100644 --- a/lib/puppet/faces/key.rb +++ b/lib/puppet/faces/key.rb @@ -1,4 +1,4 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:key, '0.0.1') do +Puppet::Faces::Indirector.define(:key, '0.0.1') do end diff --git a/lib/puppet/faces/node.rb b/lib/puppet/faces/node.rb index bc31a2cf3..7eed0df91 100644 --- a/lib/puppet/faces/node.rb +++ b/lib/puppet/faces/node.rb @@ -1,5 +1,5 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:node, '0.0.1') do +Puppet::Faces::Indirector.define(:node, '0.0.1') do set_default_format :yaml end diff --git a/lib/puppet/faces/option.rb b/lib/puppet/faces/option.rb index 352f7e5ef..7d3ed37ca 100644 --- a/lib/puppet/faces/option.rb +++ b/lib/puppet/faces/option.rb @@ -1,6 +1,6 @@ -require 'puppet/string' +require 'puppet/faces' -class Puppet::String::Option +class Puppet::Faces::Option attr_reader :parent attr_reader :name attr_reader :aliases @@ -65,8 +65,8 @@ class Puppet::String::Option end # to_s and optparse_to_name are roughly mirrored, because they are used to - # transform strings to name symbols, and vice-versa. This isn't a full - # bidirectional transformation though. + # transform options to name symbols, and vice-versa. This isn't a full + # bidirectional transformation though. --daniel 2011-04-07 def to_s @name.to_s.tr('_', '-') end diff --git a/lib/puppet/faces/option_builder.rb b/lib/puppet/faces/option_builder.rb index da0d213fb..0b6667546 100644 --- a/lib/puppet/faces/option_builder.rb +++ b/lib/puppet/faces/option_builder.rb @@ -1,22 +1,22 @@ -require 'puppet/string/option' +require 'puppet/faces/option' -class Puppet::String::OptionBuilder +class Puppet::Faces::OptionBuilder attr_reader :option - def self.build(string, *declaration, &block) - new(string, *declaration, &block).option + def self.build(face, *declaration, &block) + new(face, *declaration, &block).option end private - def initialize(string, *declaration, &block) - @string = string - @option = Puppet::String::Option.new(string, *declaration) + def initialize(face, *declaration, &block) + @face = face + @option = Puppet::Faces::Option.new(face, *declaration) block and instance_eval(&block) @option end # Metaprogram the simple DSL from the option class. - Puppet::String::Option.instance_methods.grep(/=$/).each do |setter| + Puppet::Faces::Option.instance_methods.grep(/=$/).each do |setter| next if setter =~ /^=/ # special case, darn it... dsl = setter.sub(/=$/, '') diff --git a/lib/puppet/faces/option_manager.rb b/lib/puppet/faces/option_manager.rb index f952ad4f0..02a73afc3 100644 --- a/lib/puppet/faces/option_manager.rb +++ b/lib/puppet/faces/option_manager.rb @@ -1,10 +1,10 @@ -require 'puppet/string/option_builder' +require 'puppet/faces/option_builder' -module Puppet::String::OptionManager +module Puppet::Faces::OptionManager # Declare that this app can take a specific option, and provide # the code to do so. def option(*declaration, &block) - add_option Puppet::String::OptionBuilder.build(self, *declaration, &block) + add_option Puppet::Faces::OptionBuilder.build(self, *declaration, &block) end def add_option(option) diff --git a/lib/puppet/faces/report.rb b/lib/puppet/faces/report.rb index da3ca8504..23a518981 100644 --- a/lib/puppet/faces/report.rb +++ b/lib/puppet/faces/report.rb @@ -1,6 +1,6 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:report, '0.0.1') do +Puppet::Faces::Indirector.define(:report, '0.0.1') do action(:submit) do when_invoked do |report, options| begin diff --git a/lib/puppet/faces/resource.rb b/lib/puppet/faces/resource.rb index 9838be0fa..60b0d94db 100644 --- a/lib/puppet/faces/resource.rb +++ b/lib/puppet/faces/resource.rb @@ -1,4 +1,4 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:resource, '0.0.1') do +Puppet::Faces::Indirector.define(:resource, '0.0.1') do end diff --git a/lib/puppet/faces/resource_type.rb b/lib/puppet/faces/resource_type.rb index 8ca31ea6c..4321d65e7 100644 --- a/lib/puppet/faces/resource_type.rb +++ b/lib/puppet/faces/resource_type.rb @@ -1,4 +1,4 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:resource_type, '0.0.1') do +Puppet::Faces::Indirector.define(:resource_type, '0.0.1') do end diff --git a/lib/puppet/faces/status.rb b/lib/puppet/faces/status.rb index 41de2bb99..e035f281f 100644 --- a/lib/puppet/faces/status.rb +++ b/lib/puppet/faces/status.rb @@ -1,4 +1,4 @@ -require 'puppet/string/indirector' +require 'puppet/faces/indirector' -Puppet::String::Indirector.define(:status, '0.0.1') do +Puppet::Faces::Indirector.define(:status, '0.0.1') do end -- cgit From 87ed3188e65d3f5f9c2c32a409b271d1b39684b9 Mon Sep 17 00:00:00 2001 From: Daniel Pittman Date: Thu, 7 Apr 2011 15:44:28 -0700 Subject: (#7012) Split plumbing into Puppet::Interface This splits out the plumbing into the Puppet::Interface namespace, and uses Puppet::Faces for all the public-facing code. The fault line is "what you care about if you are using or writing a face", which is public, against "what you care about to enable either of those two", which is the plumbing. --- lib/puppet/faces.rb | 118 +++--------------------------- lib/puppet/faces/action.rb | 119 ------------------------------ lib/puppet/faces/action_builder.rb | 31 -------- lib/puppet/faces/action_manager.rb | 49 ------------- lib/puppet/faces/face_collection.rb | 125 -------------------------------- lib/puppet/faces/option.rb | 82 --------------------- lib/puppet/faces/option_builder.rb | 25 ------- lib/puppet/faces/option_manager.rb | 56 -------------- lib/puppet/interface.rb | 106 +++++++++++++++++++++++++++ lib/puppet/interface/action.rb | 119 ++++++++++++++++++++++++++++++ lib/puppet/interface/action_builder.rb | 31 ++++++++ lib/puppet/interface/action_manager.rb | 49 +++++++++++++ lib/puppet/interface/face_collection.rb | 125 ++++++++++++++++++++++++++++++++ lib/puppet/interface/option.rb | 82 +++++++++++++++++++++ lib/puppet/interface/option_builder.rb | 25 +++++++ lib/puppet/interface/option_manager.rb | 56 ++++++++++++++ 16 files changed, 605 insertions(+), 593 deletions(-) delete mode 100644 lib/puppet/faces/action.rb delete mode 100644 lib/puppet/faces/action_builder.rb delete mode 100644 lib/puppet/faces/action_manager.rb delete mode 100644 lib/puppet/faces/face_collection.rb delete mode 100644 lib/puppet/faces/option.rb delete mode 100644 lib/puppet/faces/option_builder.rb delete mode 100644 lib/puppet/faces/option_manager.rb create mode 100644 lib/puppet/interface.rb create mode 100644 lib/puppet/interface/action.rb create mode 100644 lib/puppet/interface/action_builder.rb create mode 100644 lib/puppet/interface/action_manager.rb create mode 100644 lib/puppet/interface/face_collection.rb create mode 100644 lib/puppet/interface/option.rb create mode 100644 lib/puppet/interface/option_builder.rb create mode 100644 lib/puppet/interface/option_manager.rb (limited to 'lib/puppet') diff --git a/lib/puppet/faces.rb b/lib/puppet/faces.rb index 07a745480..947eecf24 100644 --- a/lib/puppet/faces.rb +++ b/lib/puppet/faces.rb @@ -1,106 +1,12 @@ -require 'puppet' -require 'puppet/util/autoload' - -class Puppet::Faces - require 'puppet/faces/face_collection' - - require 'puppet/faces/action_manager' - include Puppet::Faces::ActionManager - extend Puppet::Faces::ActionManager - - require 'puppet/faces/option_manager' - include Puppet::Faces::OptionManager - extend Puppet::Faces::OptionManager - - include Puppet::Util - - class << self - # This is just so we can search for actions. We only use its - # list of directories to search. - # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb - def autoloader - @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/faces") - end - - def faces - Puppet::Faces::FaceCollection.faces - end - - def face?(name, version) - Puppet::Faces::FaceCollection.face?(name, version) - end - - def register(instance) - Puppet::Faces::FaceCollection.register(instance) - end - - def define(name, version, &block) - if face?(name, version) - face = Puppet::Faces::FaceCollection[name, version] - else - face = self.new(name, version) - Puppet::Faces::FaceCollection.register(face) - # REVISIT: Shouldn't this be delayed until *after* we evaluate the - # current block, not done before? --daniel 2011-04-07 - face.load_actions - end - - face.instance_eval(&block) if block_given? - - return face - end - - alias :[] :define - end - - attr_accessor :default_format - - def set_default_format(format) - self.default_format = format.to_sym - end - - attr_accessor :type, :verb, :version, :arguments - attr_reader :name - - def initialize(name, version, &block) - unless Puppet::Faces::FaceCollection.validate_version(version) - raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!" - end - - @name = Puppet::Faces::FaceCollection.underscorize(name) - @version = version - @default_format = :pson - - instance_eval(&block) if block_given? - end - - # Try to find actions defined in other files. - def load_actions - path = "puppet/faces/#{name}" - - loaded = [] - [path, "#{name}@#{version}/#{path}"].each do |path| - Puppet::Faces.autoloader.search_directories.each do |dir| - fdir = ::File.join(dir, path) - next unless FileTest.directory?(fdir) - - Dir.chdir(fdir) do - Dir.glob("*.rb").each do |file| - aname = file.sub(/\.rb/, '') - if loaded.include?(aname) - Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - next - end - loaded << aname - Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" - require "#{Dir.pwd}/#{aname}" - end - end - end - end - end - - def to_s - "Puppet::Faces[#{name.inspect}, #{version.inspect}]" - end -end +# The public name of this feature is 'faces', but we have hidden all the +# plumbing over in the 'interfaces' namespace to make clear the distinction +# between the two. +# +# This file exists to ensure that the public name is usable without revealing +# the details of the implementation; you really only need go look at anything +# under Interfaces if you are looking to extend the implementation. +# +# It isn't hidden to gratuitously hide things, just to make it easier to +# separate out the interests people will have. --daniel 2011-04-07 +require 'puppet/interface' +Puppet::Faces = Puppet::Interface diff --git a/lib/puppet/faces/action.rb b/lib/puppet/faces/action.rb deleted file mode 100644 index 58d2c6003..000000000 --- a/lib/puppet/faces/action.rb +++ /dev/null @@ -1,119 +0,0 @@ -# -*- coding: utf-8 -*- -require 'puppet/faces' -require 'puppet/faces/option' - -class Puppet::Faces::Action - def initialize(face, name, attrs = {}) - raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ - @face = face - @name = name.to_sym - @options = {} - attrs.each do |k, v| send("#{k}=", v) end - end - - attr_reader :name - def to_s() "#{@face}##{@name}" end - - - # Initially, this was defined to allow the @action.invoke pattern, which is - # a very natural way to invoke behaviour given our introspection - # capabilities. Heck, our initial plan was to have the faces delegate to - # the action object for invocation and all. - # - # It turns out that we have a binding problem to solve: @face was bound to - # the parent class, not the subclass instance, and we don't pass the - # appropriate context or change the binding enough to make this work. - # - # We could hack around it, by either mandating that you pass the context in - # to invoke, or try to get the binding right, but that has probably got - # subtleties that we don't instantly think of – especially around threads. - # - # So, we are pulling this method for now, and will return it to life when we - # have the time to resolve the problem. For now, you should replace... - # - # @action = @face.get_action(name) - # @action.invoke(arg1, arg2, arg3) - # - # ...with... - # - # @action = @face.get_action(name) - # @face.send(@action.name, arg1, arg2, arg3) - # - # I understand that is somewhat cumbersome, but it functions as desired. - # --daniel 2011-03-31 - # - # PS: This code is left present, but commented, to support this chunk of - # documentation, for the benefit of the reader. - # - # def invoke(*args, &block) - # @face.send(name, *args, &block) - # end - - def when_invoked=(block) - # We need to build an instance method as a wrapper, using normal code, to - # be able to expose argument defaulting between the caller and definer in - # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. - # - # In future this also gives us a place to hook in additional behaviour - # such as calling out to the action instance to validate and coerce - # parameters, which avoids any exciting context switching and all. - # - # Hopefully we can improve this when we finally shuffle off the last of - # Ruby 1.8 support, but that looks to be a few "enterprise" release eras - # away, so we are pretty stuck with this for now. - # - # Patches to make this work more nicely with Ruby 1.9 using runtime - # version checking and all are welcome, but they can't actually help if - # the results are not totally hidden away in here. - # - # Incidentally, we though about vendoring evil-ruby and actually adjusting - # the internal C structure implementation details under the hood to make - # this stuff work, because it would have been cleaner. Which gives you an - # idea how motivated we were to make this cleaner. Sorry. --daniel 2011-03-31 - - internal_name = "#{@name} implementation, required on Ruby 1.8".to_sym - file = __FILE__ + "+eval" - line = __LINE__ + 1 - wrapper = "def #{@name}(*args, &block) - args << {} unless args.last.is_a? Hash - args << block if block_given? - self.__send__(#{internal_name.inspect}, *args) - end" - - if @face.is_a?(Class) - @face.class_eval do eval wrapper, nil, file, line end - @face.define_method(internal_name, &block) - else - @face.instance_eval do eval wrapper, nil, file, line end - @face.meta_def(internal_name, &block) - end - end - - def add_option(option) - option.aliases.each do |name| - if conflict = get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - elsif conflict = @face.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@face}" - end - end - - option.aliases.each do |name| - @options[name] = option - end - - option - end - - def option?(name) - @options.include? name.to_sym - end - - def options - (@options.keys + @face.options).sort - end - - def get_option(name) - @options[name.to_sym] || @face.get_option(name) - end -end diff --git a/lib/puppet/faces/action_builder.rb b/lib/puppet/faces/action_builder.rb deleted file mode 100644 index a67068926..000000000 --- a/lib/puppet/faces/action_builder.rb +++ /dev/null @@ -1,31 +0,0 @@ -require 'puppet/faces' -require 'puppet/faces/action' - -class Puppet::Faces::ActionBuilder - attr_reader :action - - def self.build(face, name, &block) - raise "Action #{name.inspect} must specify a block" unless block - new(face, name, &block).action - end - - private - def initialize(face, name, &block) - @face = face - @action = Puppet::Faces::Action.new(face, name) - instance_eval(&block) - end - - # Ideally the method we're defining here would be added to the action, and a - # method on the face would defer to it, but we can't get scope correct, so - # we stick with this. --daniel 2011-03-24 - def when_invoked(&block) - raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action - @action.when_invoked = block - end - - def option(*declaration, &block) - option = Puppet::Faces::OptionBuilder.build(@action, *declaration, &block) - @action.add_option(option) - end -end diff --git a/lib/puppet/faces/action_manager.rb b/lib/puppet/faces/action_manager.rb deleted file mode 100644 index 6c0036bd8..000000000 --- a/lib/puppet/faces/action_manager.rb +++ /dev/null @@ -1,49 +0,0 @@ -require 'puppet/faces/action_builder' - -module Puppet::Faces::ActionManager - # Declare that this app can take a specific action, and provide - # the code to do so. - def action(name, &block) - @actions ||= {} - raise "Action #{name} already defined for #{self}" if action?(name) - action = Puppet::Faces::ActionBuilder.build(self, name, &block) - @actions[action.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 ||= {} - raise "Action #{name} already defined for #{self}" if action?(name) - @actions[name] = Puppet::Faces::Action.new(self, name, :when_invoked => 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 ||= {} - result = @actions[name.to_sym] - if result.nil? - if self.is_a?(Class) and superclass.respond_to?(:get_action) - result = superclass.get_action(name) - elsif self.class.respond_to?(:get_action) - result = self.class.get_action(name) - end - end - return result - end - - def action?(name) - actions.include?(name.to_sym) - end -end diff --git a/lib/puppet/faces/face_collection.rb b/lib/puppet/faces/face_collection.rb deleted file mode 100644 index e6ee709d6..000000000 --- a/lib/puppet/faces/face_collection.rb +++ /dev/null @@ -1,125 +0,0 @@ -# -*- coding: utf-8 -*- -require 'puppet/faces' - -module Puppet::Faces::FaceCollection - SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ - - @faces = Hash.new { |hash, key| hash[key] = {} } - - def self.faces - unless @loaded - @loaded = true - $LOAD_PATH.each do |dir| - next unless FileTest.directory?(dir) - Dir.chdir(dir) do - # REVISIT: This is wrong!!!! We don't name files like that ever, - # so we should no longer match things like this. Damnit!!! --daniel 2011-04-07 - Dir.glob("puppet/faces/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 @faces.keys - end - - def self.validate_version(version) - !!(SEMVER_VERSION =~ version.to_s) - end - - def self.cmp_semver(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) - @faces[underscorize(name)][version] if face?(name, version) - end - - def self.face?(name, version) - name = underscorize(name) - return true if @faces[name].has_key?(version) - - # We always load the current version file; the common case is that we have - # the expected version and any compatibility versions in the same file, - # the default. Which means that this is almost always the case. - # - # We use require to avoid executing the code multiple times, like any - # other Ruby library that we might want to use. --daniel 2011-04-06 - begin - require "puppet/faces/#{name}" - - # If we wanted :current, we need to index to find that; direct version - # requests just work™ as they go. --daniel 2011-04-06 - if version == :current then - # We need to find current out of this. This is the largest version - # number that doesn't have a dedicated on-disk file present; those - # represent "experimental" versions of faces, which we don't fully - # support yet. - # - # We walk the versions from highest to lowest and take the first version - # that is not defined in an explicitly versioned file on disk as the - # current version. - # - # This constrains us to only ship experimental versions with *one* - # version in the file, not multiple, but given you can't reliably load - # them except by side-effect when you ignore that rule this seems safe - # enough... - # - # Given those constraints, and that we are not going to ship a versioned - # interface that is not :current in this release, we are going to leave - # these thoughts in place, and just punt on the actual versioning. - # - # When we upgrade the core to support multiple versions we can solve the - # problems then; as lazy as possible. - # - # We do support multiple versions in the same file, though, so we sort - # versions here and return the last item in that set. - # - # --daniel 2011-04-06 - latest_ver = @faces[name].keys.sort {|a, b| cmp_semver(a, b) }.last - @faces[name][:current] = @faces[name][latest_ver] - end - rescue LoadError => e - raise unless e.message =~ %r{-- puppet/faces/#{name}$} - # ...guess we didn't find the file; return a much better problem. - end - - # Now, either we have the version in our set of faces, or we didn't find - # the version they were looking for. In the future we will support - # loading versioned stuff from some look-aside part of the Ruby load path, - # but we don't need that right now. - # - # So, this comment is a place-holder for that. --daniel 2011-04-06 - return !! @faces[name].has_key?(version) - end - - def self.register(face) - @faces[underscorize(face.name)][face.version] = face - end - - def self.underscorize(name) - unless name.to_s =~ /^[-_a-z]+$/i then - raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid face name" - end - - name.to_s.downcase.split(/[-_]/).join('_').to_sym - end -end diff --git a/lib/puppet/faces/option.rb b/lib/puppet/faces/option.rb deleted file mode 100644 index 7d3ed37ca..000000000 --- a/lib/puppet/faces/option.rb +++ /dev/null @@ -1,82 +0,0 @@ -require 'puppet/faces' - -class Puppet::Faces::Option - attr_reader :parent - attr_reader :name - attr_reader :aliases - attr_reader :optparse - attr_accessor :desc - - def takes_argument? - !!@argument - end - def optional_argument? - !!@optional_argument - end - - def initialize(parent, *declaration, &block) - @parent = parent - @optparse = [] - - # Collect and sort the arguments in the declaration. - dups = {} - declaration.each do |item| - if item.is_a? String and item.to_s =~ /^-/ then - unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then - raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" - end - @optparse << item - - # Duplicate checking... - name = optparse_to_name(item) - if dup = dups[name] then - raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" - else - dups[name] = item - end - else - raise ArgumentError, "#{item.inspect} is not valid for an option argument" - end - end - - if @optparse.empty? then - raise ArgumentError, "No option declarations found while building" - end - - # Now, infer the name from the options; we prefer the first long option as - # the name, rather than just the first option. - @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) - @aliases = @optparse.map { |o| optparse_to_name(o) } - - # Do we take an argument? If so, are we consistent about it, because - # incoherence here makes our life super-difficult, and we can more easily - # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 - @argument = @optparse.any? { |o| o =~ /[ =]/ } - if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then - raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" - end - - # Is our argument optional? The rules about consistency apply here, also, - # just like they do to taking arguments at all. --daniel 2011-03-30 - @optional_argument = @optparse.any? { |o| o.include? "[" } - if @optional_argument and not @optparse.all? { |o| o.include? "[" } then - raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" - end - end - - # to_s and optparse_to_name are roughly mirrored, because they are used to - # transform options to name symbols, and vice-versa. This isn't a full - # bidirectional transformation though. --daniel 2011-04-07 - def to_s - @name.to_s.tr('_', '-') - end - - def optparse_to_name(declaration) - unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then - raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" - end - name = found.captures.first.tr('-', '_') - raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ - name.to_sym - end -end diff --git a/lib/puppet/faces/option_builder.rb b/lib/puppet/faces/option_builder.rb deleted file mode 100644 index 0b6667546..000000000 --- a/lib/puppet/faces/option_builder.rb +++ /dev/null @@ -1,25 +0,0 @@ -require 'puppet/faces/option' - -class Puppet::Faces::OptionBuilder - attr_reader :option - - def self.build(face, *declaration, &block) - new(face, *declaration, &block).option - end - - private - def initialize(face, *declaration, &block) - @face = face - @option = Puppet::Faces::Option.new(face, *declaration) - block and instance_eval(&block) - @option - end - - # Metaprogram the simple DSL from the option class. - Puppet::Faces::Option.instance_methods.grep(/=$/).each do |setter| - next if setter =~ /^=/ # special case, darn it... - - dsl = setter.sub(/=$/, '') - define_method(dsl) do |value| @option.send(setter, value) end - end -end diff --git a/lib/puppet/faces/option_manager.rb b/lib/puppet/faces/option_manager.rb deleted file mode 100644 index 02a73afc3..000000000 --- a/lib/puppet/faces/option_manager.rb +++ /dev/null @@ -1,56 +0,0 @@ -require 'puppet/faces/option_builder' - -module Puppet::Faces::OptionManager - # Declare that this app can take a specific option, and provide - # the code to do so. - def option(*declaration, &block) - add_option Puppet::Faces::OptionBuilder.build(self, *declaration, &block) - end - - def add_option(option) - option.aliases.each do |name| - if conflict = get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" - end - - actions.each do |action| - action = get_action(action) - if conflict = action.get_option(name) then - raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{action}" - end - end - end - - option.aliases.each { |name| @options[name] = option } - option - end - - def options - @options ||= {} - result = @options.keys - - if self.is_a?(Class) and superclass.respond_to?(:options) - result += superclass.options - elsif self.class.respond_to?(:options) - result += self.class.options - end - result.sort - end - - def get_option(name) - @options ||= {} - result = @options[name.to_sym] - unless result then - if self.is_a?(Class) and superclass.respond_to?(:get_option) - result = superclass.get_option(name) - elsif self.class.respond_to?(:get_option) - result = self.class.get_option(name) - end - end - return result - end - - def option?(name) - options.include? name.to_sym - end -end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb new file mode 100644 index 000000000..70484adfc --- /dev/null +++ b/lib/puppet/interface.rb @@ -0,0 +1,106 @@ +require 'puppet' +require 'puppet/util/autoload' + +class Puppet::Interface + require 'puppet/interface/face_collection' + + require 'puppet/interface/action_manager' + include Puppet::Interface::ActionManager + extend Puppet::Interface::ActionManager + + require 'puppet/interface/option_manager' + include Puppet::Interface::OptionManager + extend Puppet::Interface::OptionManager + + include Puppet::Util + + class << self + # This is just so we can search for actions. We only use its + # list of directories to search. + # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb + def autoloader + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/faces") + end + + def faces + Puppet::Interface::FaceCollection.faces + end + + def face?(name, version) + Puppet::Interface::FaceCollection.face?(name, version) + end + + def register(instance) + Puppet::Interface::FaceCollection.register(instance) + end + + def define(name, version, &block) + if face?(name, version) + face = Puppet::Interface::FaceCollection[name, version] + else + face = self.new(name, version) + Puppet::Interface::FaceCollection.register(face) + # REVISIT: Shouldn't this be delayed until *after* we evaluate the + # current block, not done before? --daniel 2011-04-07 + face.load_actions + end + + face.instance_eval(&block) if block_given? + + return face + end + + alias :[] :define + end + + attr_accessor :default_format + + def set_default_format(format) + self.default_format = format.to_sym + end + + attr_accessor :type, :verb, :version, :arguments + attr_reader :name + + def initialize(name, version, &block) + unless Puppet::Interface::FaceCollection.validate_version(version) + raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!" + end + + @name = Puppet::Interface::FaceCollection.underscorize(name) + @version = version + @default_format = :pson + + instance_eval(&block) if block_given? + end + + # Try to find actions defined in other files. + def load_actions + path = "puppet/faces/#{name}" + + loaded = [] + [path, "#{name}@#{version}/#{path}"].each do |path| + Puppet::Interface.autoloader.search_directories.each do |dir| + fdir = ::File.join(dir, path) + next unless FileTest.directory?(fdir) + + Dir.chdir(fdir) do + Dir.glob("*.rb").each do |file| + aname = file.sub(/\.rb/, '') + if loaded.include?(aname) + Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + next + end + loaded << aname + Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" + require "#{Dir.pwd}/#{aname}" + end + end + end + end + end + + def to_s + "Puppet::Faces[#{name.inspect}, #{version.inspect}]" + end +end diff --git a/lib/puppet/interface/action.rb b/lib/puppet/interface/action.rb new file mode 100644 index 000000000..e4a37a1f7 --- /dev/null +++ b/lib/puppet/interface/action.rb @@ -0,0 +1,119 @@ +# -*- coding: utf-8 -*- +require 'puppet/interface' +require 'puppet/interface/option' + +class Puppet::Interface::Action + def initialize(face, name, attrs = {}) + raise "#{name.inspect} is an invalid action name" unless name.to_s =~ /^[a-z]\w*$/ + @face = face + @name = name.to_sym + @options = {} + attrs.each do |k, v| send("#{k}=", v) end + end + + attr_reader :name + def to_s() "#{@face}##{@name}" end + + + # Initially, this was defined to allow the @action.invoke pattern, which is + # a very natural way to invoke behaviour given our introspection + # capabilities. Heck, our initial plan was to have the faces delegate to + # the action object for invocation and all. + # + # It turns out that we have a binding problem to solve: @face was bound to + # the parent class, not the subclass instance, and we don't pass the + # appropriate context or change the binding enough to make this work. + # + # We could hack around it, by either mandating that you pass the context in + # to invoke, or try to get the binding right, but that has probably got + # subtleties that we don't instantly think of – especially around threads. + # + # So, we are pulling this method for now, and will return it to life when we + # have the time to resolve the problem. For now, you should replace... + # + # @action = @face.get_action(name) + # @action.invoke(arg1, arg2, arg3) + # + # ...with... + # + # @action = @face.get_action(name) + # @face.send(@action.name, arg1, arg2, arg3) + # + # I understand that is somewhat cumbersome, but it functions as desired. + # --daniel 2011-03-31 + # + # PS: This code is left present, but commented, to support this chunk of + # documentation, for the benefit of the reader. + # + # def invoke(*args, &block) + # @face.send(name, *args, &block) + # end + + def when_invoked=(block) + # We need to build an instance method as a wrapper, using normal code, to + # be able to expose argument defaulting between the caller and definer in + # the Ruby API. An extra method is, sadly, required for Ruby 1.8 to work. + # + # In future this also gives us a place to hook in additional behaviour + # such as calling out to the action instance to validate and coerce + # parameters, which avoids any exciting context switching and all. + # + # Hopefully we can improve this when we finally shuffle off the last of + # Ruby 1.8 support, but that looks to be a few "enterprise" release eras + # away, so we are pretty stuck with this for now. + # + # Patches to make this work more nicely with Ruby 1.9 using runtime + # version checking and all are welcome, but they can't actually help if + # the results are not totally hidden away in here. + # + # Incidentally, we though about vendoring evil-ruby and actually adjusting + # the internal C structure implementation details under the hood to make + # this stuff work, because it would have been cleaner. Which gives you an + # idea how motivated we were to make this cleaner. Sorry. --daniel 2011-03-31 + + internal_name = "#{@name} implementation, required on Ruby 1.8".to_sym + file = __FILE__ + "+eval" + line = __LINE__ + 1 + wrapper = "def #{@name}(*args, &block) + args << {} unless args.last.is_a? Hash + args << block if block_given? + self.__send__(#{internal_name.inspect}, *args) + end" + + if @face.is_a?(Class) + @face.class_eval do eval wrapper, nil, file, line end + @face.define_method(internal_name, &block) + else + @face.instance_eval do eval wrapper, nil, file, line end + @face.meta_def(internal_name, &block) + end + end + + def add_option(option) + option.aliases.each do |name| + if conflict = get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" + elsif conflict = @face.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{@face}" + end + end + + option.aliases.each do |name| + @options[name] = option + end + + option + end + + def option?(name) + @options.include? name.to_sym + end + + def options + (@options.keys + @face.options).sort + end + + def get_option(name) + @options[name.to_sym] || @face.get_option(name) + end +end diff --git a/lib/puppet/interface/action_builder.rb b/lib/puppet/interface/action_builder.rb new file mode 100644 index 000000000..b08c3d023 --- /dev/null +++ b/lib/puppet/interface/action_builder.rb @@ -0,0 +1,31 @@ +require 'puppet/interface' +require 'puppet/interface/action' + +class Puppet::Interface::ActionBuilder + attr_reader :action + + def self.build(face, name, &block) + raise "Action #{name.inspect} must specify a block" unless block + new(face, name, &block).action + end + + private + def initialize(face, name, &block) + @face = face + @action = Puppet::Interface::Action.new(face, name) + instance_eval(&block) + end + + # Ideally the method we're defining here would be added to the action, and a + # method on the face would defer to it, but we can't get scope correct, so + # we stick with this. --daniel 2011-03-24 + def when_invoked(&block) + raise "when_invoked on an ActionBuilder with no corresponding Action" unless @action + @action.when_invoked = block + end + + def option(*declaration, &block) + option = Puppet::Interface::OptionBuilder.build(@action, *declaration, &block) + @action.add_option(option) + end +end diff --git a/lib/puppet/interface/action_manager.rb b/lib/puppet/interface/action_manager.rb new file mode 100644 index 000000000..bb0e5bf57 --- /dev/null +++ b/lib/puppet/interface/action_manager.rb @@ -0,0 +1,49 @@ +require 'puppet/interface/action_builder' + +module Puppet::Interface::ActionManager + # Declare that this app can take a specific action, and provide + # the code to do so. + def action(name, &block) + @actions ||= {} + raise "Action #{name} already defined for #{self}" if action?(name) + action = Puppet::Interface::ActionBuilder.build(self, name, &block) + @actions[action.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 ||= {} + raise "Action #{name} already defined for #{self}" if action?(name) + @actions[name] = Puppet::Interface::Action.new(self, name, :when_invoked => 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 ||= {} + result = @actions[name.to_sym] + if result.nil? + if self.is_a?(Class) and superclass.respond_to?(:get_action) + result = superclass.get_action(name) + elsif self.class.respond_to?(:get_action) + result = self.class.get_action(name) + end + end + return result + end + + def action?(name) + actions.include?(name.to_sym) + end +end diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb new file mode 100644 index 000000000..9f7a499c2 --- /dev/null +++ b/lib/puppet/interface/face_collection.rb @@ -0,0 +1,125 @@ +# -*- coding: utf-8 -*- +require 'puppet/interface' + +module Puppet::Interface::FaceCollection + SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ + + @faces = Hash.new { |hash, key| hash[key] = {} } + + def self.faces + unless @loaded + @loaded = true + $LOAD_PATH.each do |dir| + next unless FileTest.directory?(dir) + Dir.chdir(dir) do + # REVISIT: This is wrong!!!! We don't name files like that ever, + # so we should no longer match things like this. Damnit!!! --daniel 2011-04-07 + Dir.glob("puppet/faces/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 @faces.keys + end + + def self.validate_version(version) + !!(SEMVER_VERSION =~ version.to_s) + end + + def self.cmp_semver(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) + @faces[underscorize(name)][version] if face?(name, version) + end + + def self.face?(name, version) + name = underscorize(name) + return true if @faces[name].has_key?(version) + + # We always load the current version file; the common case is that we have + # the expected version and any compatibility versions in the same file, + # the default. Which means that this is almost always the case. + # + # We use require to avoid executing the code multiple times, like any + # other Ruby library that we might want to use. --daniel 2011-04-06 + begin + require "puppet/faces/#{name}" + + # If we wanted :current, we need to index to find that; direct version + # requests just work™ as they go. --daniel 2011-04-06 + if version == :current then + # We need to find current out of this. This is the largest version + # number that doesn't have a dedicated on-disk file present; those + # represent "experimental" versions of faces, which we don't fully + # support yet. + # + # We walk the versions from highest to lowest and take the first version + # that is not defined in an explicitly versioned file on disk as the + # current version. + # + # This constrains us to only ship experimental versions with *one* + # version in the file, not multiple, but given you can't reliably load + # them except by side-effect when you ignore that rule this seems safe + # enough... + # + # Given those constraints, and that we are not going to ship a versioned + # interface that is not :current in this release, we are going to leave + # these thoughts in place, and just punt on the actual versioning. + # + # When we upgrade the core to support multiple versions we can solve the + # problems then; as lazy as possible. + # + # We do support multiple versions in the same file, though, so we sort + # versions here and return the last item in that set. + # + # --daniel 2011-04-06 + latest_ver = @faces[name].keys.sort {|a, b| cmp_semver(a, b) }.last + @faces[name][:current] = @faces[name][latest_ver] + end + rescue LoadError => e + raise unless e.message =~ %r{-- puppet/faces/#{name}$} + # ...guess we didn't find the file; return a much better problem. + end + + # Now, either we have the version in our set of faces, or we didn't find + # the version they were looking for. In the future we will support + # loading versioned stuff from some look-aside part of the Ruby load path, + # but we don't need that right now. + # + # So, this comment is a place-holder for that. --daniel 2011-04-06 + return !! @faces[name].has_key?(version) + end + + def self.register(face) + @faces[underscorize(face.name)][face.version] = face + end + + def self.underscorize(name) + unless name.to_s =~ /^[-_a-z]+$/i then + raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid face name" + end + + name.to_s.downcase.split(/[-_]/).join('_').to_sym + end +end diff --git a/lib/puppet/interface/option.rb b/lib/puppet/interface/option.rb new file mode 100644 index 000000000..ccc2fbba7 --- /dev/null +++ b/lib/puppet/interface/option.rb @@ -0,0 +1,82 @@ +require 'puppet/interface' + +class Puppet::Interface::Option + attr_reader :parent + attr_reader :name + attr_reader :aliases + attr_reader :optparse + attr_accessor :desc + + def takes_argument? + !!@argument + end + def optional_argument? + !!@optional_argument + end + + def initialize(parent, *declaration, &block) + @parent = parent + @optparse = [] + + # Collect and sort the arguments in the declaration. + dups = {} + declaration.each do |item| + if item.is_a? String and item.to_s =~ /^-/ then + unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then + raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" + end + @optparse << item + + # Duplicate checking... + name = optparse_to_name(item) + if dup = dups[name] then + raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" + else + dups[name] = item + end + else + raise ArgumentError, "#{item.inspect} is not valid for an option argument" + end + end + + if @optparse.empty? then + raise ArgumentError, "No option declarations found while building" + end + + # Now, infer the name from the options; we prefer the first long option as + # the name, rather than just the first option. + @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) + @aliases = @optparse.map { |o| optparse_to_name(o) } + + # Do we take an argument? If so, are we consistent about it, because + # incoherence here makes our life super-difficult, and we can more easily + # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 + @argument = @optparse.any? { |o| o =~ /[ =]/ } + if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then + raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" + end + + # Is our argument optional? The rules about consistency apply here, also, + # just like they do to taking arguments at all. --daniel 2011-03-30 + @optional_argument = @optparse.any? { |o| o.include? "[" } + if @optional_argument and not @optparse.all? { |o| o.include? "[" } then + raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" + end + end + + # to_s and optparse_to_name are roughly mirrored, because they are used to + # transform options to name symbols, and vice-versa. This isn't a full + # bidirectional transformation though. --daniel 2011-04-07 + def to_s + @name.to_s.tr('_', '-') + end + + def optparse_to_name(declaration) + unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then + raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" + end + name = found.captures.first.tr('-', '_') + raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ + name.to_sym + end +end diff --git a/lib/puppet/interface/option_builder.rb b/lib/puppet/interface/option_builder.rb new file mode 100644 index 000000000..83a1906b0 --- /dev/null +++ b/lib/puppet/interface/option_builder.rb @@ -0,0 +1,25 @@ +require 'puppet/interface/option' + +class Puppet::Interface::OptionBuilder + attr_reader :option + + def self.build(face, *declaration, &block) + new(face, *declaration, &block).option + end + + private + def initialize(face, *declaration, &block) + @face = face + @option = Puppet::Interface::Option.new(face, *declaration) + block and instance_eval(&block) + @option + end + + # Metaprogram the simple DSL from the option class. + Puppet::Interface::Option.instance_methods.grep(/=$/).each do |setter| + next if setter =~ /^=/ # special case, darn it... + + dsl = setter.sub(/=$/, '') + define_method(dsl) do |value| @option.send(setter, value) end + end +end diff --git a/lib/puppet/interface/option_manager.rb b/lib/puppet/interface/option_manager.rb new file mode 100644 index 000000000..56df9760f --- /dev/null +++ b/lib/puppet/interface/option_manager.rb @@ -0,0 +1,56 @@ +require 'puppet/interface/option_builder' + +module Puppet::Interface::OptionManager + # Declare that this app can take a specific option, and provide + # the code to do so. + def option(*declaration, &block) + add_option Puppet::Interface::OptionBuilder.build(self, *declaration, &block) + end + + def add_option(option) + option.aliases.each do |name| + if conflict = get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict}" + end + + actions.each do |action| + action = get_action(action) + if conflict = action.get_option(name) then + raise ArgumentError, "Option #{option} conflicts with existing option #{conflict} on #{action}" + end + end + end + + option.aliases.each { |name| @options[name] = option } + option + end + + def options + @options ||= {} + result = @options.keys + + if self.is_a?(Class) and superclass.respond_to?(:options) + result += superclass.options + elsif self.class.respond_to?(:options) + result += self.class.options + end + result.sort + end + + def get_option(name) + @options ||= {} + result = @options[name.to_sym] + unless result then + if self.is_a?(Class) and superclass.respond_to?(:get_option) + result = superclass.get_option(name) + elsif self.class.respond_to?(:get_option) + result = self.class.get_option(name) + end + end + return result + end + + def option?(name) + options.include? name.to_sym + end +end -- cgit From 292a8b92c74c8d9392348ef6e9718934471a0ac1 Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Wed, 6 Apr 2011 21:14:06 -0400 Subject: (#6985) Allows indirectors to accept a hash as an argument. Many indirectors need to take a hash as the last argument. This was not allowed b/c the last hash argument was assumed to be the options hash. I resolved this by assuming that the hash needed by an indirector would be the same as the options hash. Reviewed-By: Daniel Pittman --- lib/puppet/faces/indirector.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/faces/indirector.rb b/lib/puppet/faces/indirector.rb index f72260017..7e4e0f00f 100644 --- a/lib/puppet/faces/indirector.rb +++ b/lib/puppet/faces/indirector.rb @@ -16,7 +16,7 @@ that we should describe in this file somehow." end def call_indirection_method(method, *args) - options = args.pop + options = args.last options.has_key?(:terminus) and set_terminus(options[:terminus]) begin -- cgit From d9f23c0801d7d40809326face37463aeb67a3cdd Mon Sep 17 00:00:00 2001 From: Dan Bode Date: Thu, 7 Apr 2011 16:18:27 -0700 Subject: (#6969) String failures differentiate between invalid string/version This patch does two things: 1. splits out the string lookup functionality from define into a seperate method [] 2. Tries to both load the specific version of a string as well as the current version so that specific error messages can be returned differentiating between an invalid version/string. Reviewed-By: Daniel Pittman --- lib/puppet/interface.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'lib/puppet') diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 70484adfc..07e27efa8 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -50,7 +50,16 @@ class Puppet::Interface return face end - alias :[] :define + def [](name, version) + unless face = Puppet::Interface::FaceCollection[name, version] + if current = Puppet::Interface::FaceCollection[name, :current] + raise Puppet::Error, "Could not find version #{version} of #{current}" + else + raise Puppet::Error, "Could not find Puppet Face #{name.inspect}" + end + end + face + end end attr_accessor :default_format -- cgit