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 @@ -1,23 +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.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 @@ -1,95 +1,95 @@ 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.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 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 index 7a31ce323..78772833e 100644 --- a/lib/puppet/application/interface_base.rb +++ b/lib/puppet/application/interface_base.rb @@ -1,96 +1,97 @@ 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 - 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. # 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/interface.rb b/lib/puppet/interface.rb index f82d6235c..7f208f56c 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -1,91 +1,93 @@ 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 - @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 def self.autoloader @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/interface") end def self.interfaces 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 return interface end attr_accessor :default_format def set_default_format(format) 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 options.each { |opt, val| send(opt.to_s + "=", val) } instance_eval(&block) if block end # Try to find actions defined in other files. def load_actions path = "puppet/interface/#{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})" + "Puppet::Interface(#{name}, :version => #{version.inspect})" 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/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/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,50 +1,52 @@ require 'puppet/interface' module Puppet::Interface::InterfaceCollection - @interfaces = {} + @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/*.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) + 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) 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 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/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/catalog.rb b/lib/puppet/interface/v1/catalog.rb similarity index 87% rename from lib/puppet/interface/catalog.rb rename to lib/puppet/interface/v1/catalog.rb index defe32127..2ba642039 100644 --- a/lib/puppet/interface/catalog.rb +++ b/lib/puppet/interface/v1/catalog.rb @@ -1,40 +1,40 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:catalog) do +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).find(certname, facts_to_upload) + 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/catalog/select.rb b/lib/puppet/interface/v1/catalog/select.rb similarity index 85% rename from lib/puppet/interface/catalog/select.rb rename to lib/puppet/interface/v1/catalog/select.rb index 32d9b7c45..e37c841b5 100644 --- a/lib/puppet/interface/catalog/select.rb +++ b/lib/puppet/interface/v1/catalog/select.rb @@ -1,10 +1,10 @@ # Select and show a list of resources of a given type. -Puppet::Interface.interface(:catalog) do +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/certificate_revocation_list.rb b/lib/puppet/interface/v1/certificate_revocation_list.rb similarity index 89% rename from lib/puppet/interface/certificate_revocation_list.rb rename to lib/puppet/interface/v1/certificate_revocation_list.rb index 956fb6494..09efd8c7a 100644 --- a/lib/puppet/interface/certificate_revocation_list.rb +++ b/lib/puppet/interface/v1/certificate_revocation_list.rb @@ -1,4 +1,4 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:certificate_revocation_list) do +Puppet::Interface::Indirector.interface(:certificate_revocation_list, 1) do end diff --git a/lib/puppet/interface/config.rb b/lib/puppet/interface/v1/config.rb similarity index 81% rename from lib/puppet/interface/config.rb rename to lib/puppet/interface/v1/config.rb index 79d2ee7c1..a072e703c 100644 --- a/lib/puppet/interface/config.rb +++ b/lib/puppet/interface/v1/config.rb @@ -1,10 +1,10 @@ require 'puppet/interface' -Puppet::Interface.interface(:config) do +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/facts.rb b/lib/puppet/interface/v1/facts.rb similarity index 90% rename from lib/puppet/interface/facts.rb rename to lib/puppet/interface/v1/facts.rb index 97e22714b..0be23b781 100644 --- a/lib/puppet/interface/facts.rb +++ b/lib/puppet/interface/v1/facts.rb @@ -1,18 +1,18 @@ require 'puppet/interface/indirector' require 'puppet/node/facts' -Puppet::Interface::Indirector.interface(:facts) do +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/file.rb b/lib/puppet/interface/v1/file.rb similarity index 61% rename from lib/puppet/interface/file.rb rename to lib/puppet/interface/v1/file.rb index f38af2b92..430413a56 100644 --- a/lib/puppet/interface/file.rb +++ b/lib/puppet/interface/v1/file.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:file) do +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/node.rb b/lib/puppet/interface/v1/node.rb similarity index 56% rename from lib/puppet/interface/node.rb rename to lib/puppet/interface/v1/node.rb index 8940fd7dd..c3e527856 100644 --- a/lib/puppet/interface/node.rb +++ b/lib/puppet/interface/v1/node.rb @@ -1,5 +1,5 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:node) do +Puppet::Interface::Indirector.interface(:node, 1) do set_default_format :yaml end diff --git a/lib/puppet/interface/report.rb b/lib/puppet/interface/v1/report.rb similarity index 85% rename from lib/puppet/interface/report.rb rename to lib/puppet/interface/v1/report.rb index 56a58f6aa..fdc2e2c0f 100644 --- a/lib/puppet/interface/report.rb +++ b/lib/puppet/interface/v1/report.rb @@ -1,15 +1,15 @@ require 'puppet/interface/indirector' -Puppet::Interface::Indirector.interface(:report) do +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 diff --git a/spec/unit/application/interface_base_spec.rb b/spec/unit/application/interface_base_spec.rb index 3e7c04f5c..6aa9558df 100644 --- a/spec/unit/application/interface_base_spec.rb +++ b/spec/unit/application/interface_base_spec.rb @@ -1,62 +1,62 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') require 'puppet/application/interface_base' require 'puppet/application/interface_base' -base_interface = Puppet::Interface.interface(:basetest) +base_interface = Puppet::Interface.interface(:basetest, 1) class Puppet::Application::InterfaceBase::Basetest < Puppet::Application::InterfaceBase end describe Puppet::Application::InterfaceBase do before do @app = Puppet::Application::InterfaceBase::Basetest.new @app.stubs(:interface).returns base_interface @app.stubs(:exit) @app.stubs(:puts) Puppet::Util::Log.stubs(:newdestination) end describe "when calling main" do before do @app.verb = :find @app.arguments = ["myname", "myarg"] @app.interface.stubs(:find) end it "should send the specified verb and name to the interface" do @app.interface.expects(:find).with("myname", "myarg") @app.main end it "should use its render method to render any result" it "should exit with the current exit code" end describe "during setup" do before do @app.command_line.stubs(:args).returns(["find", "myname", "myarg"]) @app.stubs(:validate) end it "should set the verb from the command line arguments" do @app.setup @app.verb.should == "find" end it "should make sure arguments are an array" do @app.command_line.stubs(:args).returns(["find", "myname", "myarg"]) @app.setup @app.arguments.should == ["myname", "myarg"] end it "should set the options on the interface" do @app.options[:foo] = "bar" @app.setup @app.interface.options.should == @app.options end end end diff --git a/spec/unit/interface/action_builder_spec.rb b/spec/unit/interface/action_builder_spec.rb index 39b2386dc..ba6618fa4 100644 --- a/spec/unit/interface/action_builder_spec.rb +++ b/spec/unit/interface/action_builder_spec.rb @@ -1,30 +1,30 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') require 'puppet/interface/action_builder' describe Puppet::Interface::ActionBuilder do describe "::build" do it "should build an action" do action = Puppet::Interface::ActionBuilder.build(nil,:foo) do end action.should be_a(Puppet::Interface::Action) action.name.should == "foo" end it "should define a method on the interface which invokes the action" do - interface = Puppet::Interface.new(:action_builder_test_interface) + interface = Puppet::Interface.new(:action_builder_test_interface, :version => 1) action = Puppet::Interface::ActionBuilder.build(interface, :foo) do invoke do "invoked the method" end end interface.foo.should == "invoked the method" end it "should require a block" do lambda { Puppet::Interface::ActionBuilder.build(nil,:foo) }.should raise_error("Action 'foo' must specify a block") end end end diff --git a/spec/unit/interface/action_spec.rb b/spec/unit/interface/action_spec.rb index e74fa9fcc..5be6665fb 100644 --- a/spec/unit/interface/action_spec.rb +++ b/spec/unit/interface/action_spec.rb @@ -1,75 +1,75 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') require 'puppet/interface/action' describe Puppet::Interface::Action do describe "when validating the action name" do it "should require a name" do lambda { Puppet::Interface::Action.new(nil,nil) }.should raise_error("'' is an invalid action name") end it "should not allow empty names" do lambda { Puppet::Interface::Action.new(nil,'') }.should raise_error("'' is an invalid action name") end it "should not allow names with whitespace" do lambda { Puppet::Interface::Action.new(nil,'foo bar') }.should raise_error("'foo bar' is an invalid action name") end it "should not allow names beginning with dashes" do lambda { Puppet::Interface::Action.new(nil,'-foobar') }.should raise_error("'-foobar' is an invalid action name") end end describe "when invoking" do it "should be able to call other actions on the same object" do - interface = Puppet::Interface.new(:my_interface) do + interface = Puppet::Interface.new(:my_interface, :version => 1) do action(:foo) do invoke { 25 } end action(:bar) do invoke { "the value of foo is '#{foo}'" } end end interface.foo.should == 25 interface.bar.should == "the value of foo is '25'" end # bar is a class action calling a class action # quux is a class action calling an instance action # baz is an instance action calling a class action # qux is an instance action calling an instance action it "should be able to call other actions on the same object when defined on a class" do class Puppet::Interface::MyInterfaceBaseClass < Puppet::Interface action(:foo) do invoke { 25 } end action(:bar) do invoke { "the value of foo is '#{foo}'" } end action(:quux) do invoke { "qux told me #{qux}" } end end - interface = Puppet::Interface::MyInterfaceBaseClass.new(:my_inherited_interface) do + interface = Puppet::Interface::MyInterfaceBaseClass.new(:my_inherited_interface, :version => 1) do action(:baz) do invoke { "the value of foo in baz is '#{foo}'" } end action(:qux) do invoke { baz } end end interface.foo.should == 25 interface.bar.should == "the value of foo is '25'" interface.quux.should == "qux told me the value of foo in baz is '25'" interface.baz.should == "the value of foo in baz is '25'" interface.qux.should == "the value of foo in baz is '25'" end end end diff --git a/spec/unit/interface/catalog_spec.rb b/spec/unit/interface/catalog_spec.rb index 78d62110f..a59f9c952 100644 --- a/spec/unit/interface/catalog_spec.rb +++ b/spec/unit/interface/catalog_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/catalog' -describe Puppet::Interface::Indirector.interface(:catalog) do +describe Puppet::Interface.interface(:catalog, 1) do end diff --git a/spec/unit/interface/certificate_request_spec.rb b/spec/unit/interface/certificate_request_spec.rb index a6ab8d17e..e818c301b 100644 --- a/spec/unit/interface/certificate_request_spec.rb +++ b/spec/unit/interface/certificate_request_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/certificate_request' -describe Puppet::Interface::Indirector.interface(:certificate_request) do +describe Puppet::Interface.interface(:certificate_request, 1) do end diff --git a/spec/unit/interface/certificate_revocation_list_spec.rb b/spec/unit/interface/certificate_revocation_list_spec.rb index a98b48d90..0979eda1f 100644 --- a/spec/unit/interface/certificate_revocation_list_spec.rb +++ b/spec/unit/interface/certificate_revocation_list_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/certificate_revocation_list' -describe Puppet::Interface::Indirector.interface(:certificate_revocation_list) do +describe Puppet::Interface.interface(:certificate_revocation_list, 1) do end diff --git a/spec/unit/interface/certificate_spec.rb b/spec/unit/interface/certificate_spec.rb index 6a325343f..51b79e6b0 100644 --- a/spec/unit/interface/certificate_spec.rb +++ b/spec/unit/interface/certificate_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/certificate' -describe Puppet::Interface::Indirector.interface(:certificate) do +describe Puppet::Interface.interface(:certificate, 1) do end diff --git a/spec/unit/interface/config_spec.rb b/spec/unit/interface/config_spec.rb index e8aafd4a3..e1238b925 100644 --- a/spec/unit/interface/config_spec.rb +++ b/spec/unit/interface/config_spec.rb @@ -1,19 +1,18 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/config' -describe Puppet::Interface.interface(:config) do +describe Puppet::Interface.interface(:config, 1) do it "should use Settings#print_config_options when asked to print" do Puppet.settings.stubs(:puts) Puppet.settings.expects(:print_config_options) subject.print end it "should set 'configprint' to all desired values and call print_config_options when a specific value is provided" do Puppet.settings.stubs(:puts) Puppet.settings.expects(:print_config_options) subject.print("libdir", "ssldir") Puppet.settings[:configprint].should == "libdir,ssldir" end end diff --git a/spec/unit/interface/configurer_spec.rb b/spec/unit/interface/configurer_spec.rb index 4b3532c1b..b592a85bb 100644 --- a/spec/unit/interface/configurer_spec.rb +++ b/spec/unit/interface/configurer_spec.rb @@ -1,25 +1,24 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/configurer' require 'puppet/indirector/catalog/rest' require 'tempfile' -describe Puppet::Interface.interface(:configurer) do +describe Puppet::Interface.interface(:configurer, 1) do describe "#synchronize" do it "should retrieve and apply a catalog and return a report" do dirname = Dir.mktmpdir("puppetdir") Puppet[:vardir] = dirname Puppet[:confdir] = dirname @catalog = Puppet::Resource::Catalog.new @file = Puppet::Resource.new(:file, File.join(dirname, "tmp_dir_resource"), :parameters => {:ensure => :present}) @catalog.add_resource(@file) Puppet::Resource::Catalog::Rest.any_instance.stubs(:find).returns(@catalog) - report = Puppet::Interface.interface(:configurer).synchronize("foo") + report = subject.synchronize("foo") report.kind.should == "apply" report.status.should == "changed" end end end diff --git a/spec/unit/interface/facts_spec.rb b/spec/unit/interface/facts_spec.rb index d0f87d3a0..2b5731de5 100644 --- a/spec/unit/interface/facts_spec.rb +++ b/spec/unit/interface/facts_spec.rb @@ -1,22 +1,21 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/facts' -describe Puppet::Interface::Indirector.interface(:facts) do +describe Puppet::Interface.interface(:facts, 1) do it "should define an 'upload' fact" do subject.should be_action(:upload) end it "should set its default format to :yaml" do subject.default_format.should == :yaml end describe "when uploading" do it "should set the terminus_class to :facter" it "should set the cach_eclass to :rest" it "should find the current certname" end end diff --git a/spec/unit/interface/file_spec.rb b/spec/unit/interface/file_spec.rb index 54427a267..754b22875 100644 --- a/spec/unit/interface/file_spec.rb +++ b/spec/unit/interface/file_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/file' -describe Puppet::Interface::Indirector.interface(:file) do +describe Puppet::Interface.interface(:file, 1) do end diff --git a/spec/unit/interface/indirector_spec.rb b/spec/unit/interface/indirector_spec.rb index 0eb7a9a4f..abbff150b 100644 --- a/spec/unit/interface/indirector_spec.rb +++ b/spec/unit/interface/indirector_spec.rb @@ -1,55 +1,55 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') require 'puppet/interface/indirector' describe Puppet::Interface::Indirector do before do - @instance = Puppet::Interface::Indirector.new(:test) + @instance = Puppet::Interface::Indirector.new(:test, :version => 1) @indirection = stub 'indirection', :name => :stub_indirection @instance.stubs(:indirection).returns @indirection end it "should be able to return a list of indirections" do Puppet::Interface::Indirector.indirections.should be_include("catalog") end it "should be able to return a list of terminuses for a given indirection" do Puppet::Interface::Indirector.terminus_classes(:catalog).should be_include("compiler") end describe "as an instance" do it "should be able to determine its indirection" do # Loading actions here an get, um, complicated Puppet::Interface.stubs(:load_actions) - Puppet::Interface::Indirector.new(:catalog).indirection.should equal(Puppet::Resource::Catalog.indirection) + Puppet::Interface::Indirector.new(:catalog, :version => 1).indirection.should equal(Puppet::Resource::Catalog.indirection) end end [:find, :search, :save, :destroy].each do |method| it "should define a '#{method}' action" do Puppet::Interface::Indirector.should be_action(method) end it "should just call the indirection method when the '#{method}' action is invoked" do @instance.indirection.expects(method).with(:test, "myargs") @instance.send(method, :test, "myargs") end end it "should be able to override its indirection name" do @instance.set_indirection_name :foo @instance.indirection_name.should == :foo end it "should be able to set its terminus class" do @instance.indirection.expects(:terminus_class=).with(:myterm) @instance.set_terminus(:myterm) end it "should define a class-level 'info' action" do Puppet::Interface::Indirector.should be_action(:info) end end diff --git a/spec/unit/interface/interface_collection_spec.rb b/spec/unit/interface/interface_collection_spec.rb index 536e694fd..ae684ca75 100644 --- a/spec/unit/interface/interface_collection_spec.rb +++ b/spec/unit/interface/interface_collection_spec.rb @@ -1,97 +1,101 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') +#!/usr/bin/env ruby -require 'puppet/interface/interface_collection' +require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') describe Puppet::Interface::InterfaceCollection do + before :all do + @interfaces = subject.instance_variable_get("@interfaces").dup + end + before :each do - subject.instance_variable_set("@interfaces", {}) + subject.instance_variable_get("@interfaces").clear end after :all do - subject.instance_variable_set("@interfaces", {}) + subject.instance_variable_set("@interfaces", @interfaces) end describe "::interfaces" do end describe "::[]" do before :each do - subject.instance_variable_set("@interfaces", {:foo => 10}) + subject.instance_variable_get("@interfaces")[:foo][1] = 10 end it "should return the interface with the given name" do - subject["foo"].should == 10 + subject["foo", 1].should == 10 end it "should attempt to load the interface if it isn't found" do - subject.expects(:require).with('puppet/interface/bar') - subject["bar"] + subject.expects(:require).with('puppet/interface/v1/bar') + subject["bar", 1] end end describe "::interface?" do before :each do - subject.instance_variable_set("@interfaces", {:foo => 10}) + subject.instance_variable_get("@interfaces")[:foo][1] = 10 end it "should return true if the interface specified is registered" do - subject.interface?("foo").should == true + subject.interface?("foo", 1).should == true end it "should attempt to require the interface if it is not registered" do - subject.expects(:require).with('puppet/interface/bar') - subject.interface?("bar") + subject.expects(:require).with('puppet/interface/v1/bar') + subject.interface?("bar", 1) end it "should return true if requiring the interface registered it" do subject.stubs(:require).with do - subject.instance_variable_set("@interfaces", {:bar => 20}) + subject.instance_variable_get("@interfaces")[:bar][1] = 20 end - subject.interface?("bar").should == true + subject.interface?("bar", 1).should == true end it "should return false if the interface is not registered" do subject.stubs(:require).returns(true) - subject.interface?("bar").should == false + subject.interface?("bar", 1).should == false end it "should return false if there is a LoadError requiring the interface" do subject.stubs(:require).raises(LoadError) - subject.interface?("bar").should == false + subject.interface?("bar", 1).should == false end end describe "::register" do it "should store the interface by name" do - interface = Puppet::Interface.new(:my_interface) + interface = Puppet::Interface.new(:my_interface, :version => 1) subject.register(interface) - subject.instance_variable_get("@interfaces").should == {:my_interface => interface} + subject.instance_variable_get("@interfaces").should == {:my_interface => {1 => interface}} end end describe "::underscorize" do faulty = [1, "#foo", "$bar", "sturm und drang", :"sturm und drang"] valid = { "Foo" => :foo, :Foo => :foo, "foo_bar" => :foo_bar, :foo_bar => :foo_bar, "foo-bar" => :foo_bar, :"foo-bar" => :foo_bar, } valid.each do |input, expect| it "should map #{input.inspect} to #{expect.inspect}" do result = subject.underscorize(input) result.should == expect end end faulty.each do |input| it "should fail when presented with #{input.inspect} (#{input.class})" do expect { subject.underscorize(input) }. should raise_error ArgumentError, /not a valid interface name/ end end end end diff --git a/spec/unit/interface/key_spec.rb b/spec/unit/interface/key_spec.rb index 4b331d169..395fbef4d 100644 --- a/spec/unit/interface/key_spec.rb +++ b/spec/unit/interface/key_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/key' -describe Puppet::Interface::Indirector.interface(:key) do +describe Puppet::Interface.interface(:key, 1) do end diff --git a/spec/unit/interface/node_spec.rb b/spec/unit/interface/node_spec.rb index b1b4ad421..bd4bc9fea 100644 --- a/spec/unit/interface/node_spec.rb +++ b/spec/unit/interface/node_spec.rb @@ -1,10 +1,9 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/node' -describe Puppet::Interface::Indirector.interface(:node) do +describe Puppet::Interface.interface(:node, 1) do it "should set its default format to :yaml" do subject.default_format.should == :yaml end end diff --git a/spec/unit/interface/report_spec.rb b/spec/unit/interface/report_spec.rb index c424880a9..0dd3cacf1 100644 --- a/spec/unit/interface/report_spec.rb +++ b/spec/unit/interface/report_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/report' -describe Puppet::Interface::Indirector.interface(:report) do +describe Puppet::Interface.interface(:report, 1) do end diff --git a/spec/unit/interface/resource_spec.rb b/spec/unit/interface/resource_spec.rb index aab2753b1..5101ddbd6 100644 --- a/spec/unit/interface/resource_spec.rb +++ b/spec/unit/interface/resource_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/resource' -describe Puppet::Interface::Indirector.interface(:resource) do +describe Puppet::Interface.interface(:resource, 1) do end diff --git a/spec/unit/interface/resource_type_spec.rb b/spec/unit/interface/resource_type_spec.rb index 6e973c98b..84afa30d4 100644 --- a/spec/unit/interface/resource_type_spec.rb +++ b/spec/unit/interface/resource_type_spec.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper.rb') -require 'puppet/interface/resource_type' -describe Puppet::Interface::Indirector.interface(:resource_type) do +describe Puppet::Interface.interface(:resource_type, 1) do end diff --git a/spec/unit/interface_spec.rb b/spec/unit/interface_spec.rb index e35da6b95..b78a9f8c8 100755 --- a/spec/unit/interface_spec.rb +++ b/spec/unit/interface_spec.rb @@ -1,62 +1,83 @@ #!/usr/bin/env ruby require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb') -require 'puppet/interface' describe Puppet::Interface do + before :all do + @interfaces = Puppet::Interface::InterfaceCollection.instance_variable_get("@interfaces").dup + end + + before :each do + Puppet::Interface::InterfaceCollection.instance_variable_get("@interfaces").clear + end + + after :all do + Puppet::Interface::InterfaceCollection.instance_variable_set("@interfaces", @interfaces) + end + describe "#interface" do it "should register the interface" do - interface = Puppet::Interface.interface(:interface_test_register) - interface.should == Puppet::Interface.interface(:interface_test_register) + interface = Puppet::Interface.interface(:interface_test_register, 1) + interface.should == Puppet::Interface.interface(:interface_test_register, 1) end it "should load actions" do Puppet::Interface.any_instance.expects(:load_actions) - Puppet::Interface.interface(:interface_test_load_actions) + Puppet::Interface.interface(:interface_test_load_actions, 1) + end + + it "should require a version number" do + proc { Puppet::Interface.interface(:no_version) }.should raise_error(ArgumentError) + end + end + + describe "#initialize" do + it "should require a version number" do + proc { Puppet::Interface.new(:no_version) }.should raise_error(/declared without version/) end it "should instance-eval any provided block" do - face = Puppet::Interface.new(:interface_test_block) do + face = Puppet::Interface.new(:interface_test_block, :version => 1) do action(:something) do invoke { "foo" } end end face.something.should == "foo" end end it "should have a name" do - Puppet::Interface.new(:me).name.should == :me + Puppet::Interface.new(:me, :version => 1).name.should == :me end it "should stringify with its own name" do - Puppet::Interface.new(:me).to_s.should =~ /\bme\b/ + Puppet::Interface.new(:me, :version => 1).to_s.should =~ /\bme\b/ end it "should allow overriding of the default format" do - face = Puppet::Interface.new(:me) + face = Puppet::Interface.new(:me, :version => 1) face.set_default_format :foo face.default_format.should == :foo end it "should default to :pson for its format" do - Puppet::Interface.new(:me).default_format.should == :pson + Puppet::Interface.new(:me, :version => 1).default_format.should == :pson end # Why? it "should create a class-level autoloader" do Puppet::Interface.autoloader.should be_instance_of(Puppet::Util::Autoload) end it "should set any provided options" do - Puppet::Interface.new(:me, :verb => "foo").verb.should == "foo" + Puppet::Interface.new(:me, :version => 1, :verb => "foo").verb.should == "foo" end it "should try to require interfaces that are not known" do - Puppet::Interface::InterfaceCollection.expects(:require).with "puppet/interface/foo" - Puppet::Interface.interface(:foo) + Puppet::Interface::InterfaceCollection.expects(:require).with "puppet/interface/v1/foo" + Puppet::Interface.interface(:foo, 1) end it "should be able to load all actions in all search paths" end