diff --git a/lib/puppet/application.rb b/lib/puppet/application.rb index 7b404a906..49a146ffe 100644 --- a/lib/puppet/application.rb +++ b/lib/puppet/application.rb @@ -1,402 +1,370 @@ require 'puppet' require 'optparse' # This class handles all the aspects of a Puppet application/executable # * setting up options # * setting up logs # * choosing what to run # * representing execution status # # === Usage -# The application is a Puppet::Application object that register itself in the list -# of available application. Each application needs a +name+ and a getopt +options+ -# description array. +# An application is a subclass of Puppet::Application. # -# The executable uses the application object like this: +# For legacy compatibility, # Puppet::Application[:example].run +# is equivalent to +# Puppet::Application::Example.new.run # # -# Puppet::Application.new(:example) do +# class Puppet::Application::Example << Puppet::Application # -# preinit do +# def preinit # # perform some pre initialization # @all = false # end # -# # dispatch is called to know to what command to call -# dispatch do -# Puppet::Util::CommandLine.args.shift +# # run_command is called to actually run the specified command +# def run_command +# send Puppet::Util::CommandLine.args.shift # end # +# # option uses metaprogramming to create a method +# # and also tells the option parser how to invoke that method # option("--arg ARGUMENT") do |v| # @args << v # end # # option("--debug", "-d") do |v| # @debug = v # end # # option("--all", "-a:) do |v| # @all = v # end # -# unknown do |opt,arg| +# def handle_unknown(opt,arg) # # last chance to manage an option # ... # # let's say to the framework we finally handle this option # true # end # -# command(:read) do +# def read # # read action # end # -# command(:write) do +# def write # # writeaction # end # # end # # === Preinit # The preinit block is the first code to be called in your application, before option parsing, # setup or command execution. # # === Options # Puppet::Application uses +OptionParser+ to manage the application options. # Options are defined with the +option+ method to which are passed various # arguments, including the long option, the short option, a description... # Refer to +OptionParser+ documentation for the exact format. # * If the option method is given a block, this one will be called whenever # the option is encountered in the command-line argument. # * If the option method has no block, a default functionnality will be used, that # stores the argument (or true/false if the option doesn't require an argument) in # the global (to the application) options array. # * If a given option was not defined by a the +option+ method, but it exists as a Puppet settings: # * if +unknown+ was used with a block, it will be called with the option name and argument # * if +unknown+ wasn't used, then the option/argument is handed to Puppet.settings.handlearg for # a default behavior # # --help is managed directly by the Puppet::Application class, but can be overriden. # # === Setup # Applications can use the setup block to perform any initialization. # The defaul +setup+ behaviour is to: read Puppet configuration and manage log level and destination # # === What and how to run # If the +dispatch+ block is defined it is called. This block should return the name of the registered command # to be run. # If it doesn't exist, it defaults to execute the +main+ command if defined. # # === Execution state # The class attributes/methods of Puppet::Application serve as a global place to set and query the execution # status of the application: stopping, restarting, etc. The setting of the application status does not directly # aftect its running status; it's assumed that the various components within the application will consult these # settings appropriately and affect their own processing accordingly. Control operations (signal handlers and # the like) should set the status appropriately to indicate to the overall system that it's the process of # stopping or restarting (or just running as usual). # # So, if something in your application needs to stop the process, for some reason, you might consider: # # def stop_me! # # indicate that we're stopping # Puppet::Application.stop! # # ...do stuff... # end # # And, if you have some component that involves a long-running process, you might want to consider: # # def my_long_process(giant_list_to_munge) # giant_list_to_munge.collect do |member| # # bail if we're stopping # return if Puppet::Application.stop_requested? # process_member(member) # end # end class Puppet::Application include Puppet::Util BINDIRS = %w{sbin bin}.map{|dir| File.expand_path(File.dirname(__FILE__)) + "/../../#{dir}/*"}.join(" ") - @@applications = {} - def self.applications; @@applications end - class << self include Puppet::Util attr_accessor :run_status def clear! self.run_status = nil end def stop! self.run_status = :stop_requested end def restart! self.run_status = :restart_requested end # Indicates that Puppet::Application.restart! has been invoked and components should # do what is necessary to facilitate a restart. def restart_requested? :restart_requested == run_status end # Indicates that Puppet::Application.stop! has been invoked and components should do what is necessary # for a clean stop. def stop_requested? :stop_requested == run_status end # Indicates that one of stop! or start! was invoked on Puppet::Application, and some kind of process # shutdown/short-circuit may be necessary. def interrupted? [:restart_requested, :stop_requested].include? run_status end # Indicates that Puppet::Application believes that it's in usual running mode (no stop/restart request # currently active). def clear? run_status.nil? end # Only executes the given block if the run status of Puppet::Application is clear (no restarts, stops, # etc. requested). # Upon block execution, checks the run status again; if a restart has been requested during the block's # execution, then controlled_run will send a new HUP signal to the current process. # Thus, long-running background processes can potentially finish their work before a restart. def controlled_run(&block) return unless clear? result = block.call Process.kill(:HUP, $$) if restart_requested? result end - end - attr_reader :options, :opt_parser + def should_parse_config + @parse_config = true + end - def self.[](name) - name = symbolize(name) - @@applications[name] - end + def should_not_parse_config + @parse_config = false + end - def should_parse_config - @parse_config = true - end + def should_parse_config? + if ! defined? @parse_config + @parse_config = true + end + return @parse_config + end - def should_not_parse_config - @parse_config = false - end + # used to declare code that handle an option + def option(*options, &block) + long = options.find { |opt| opt =~ /^--/ }.gsub(/^--(?:\[no-\])?([^ =]+).*$/, '\1' ).gsub('-','_') + fname = symbolize("handle_#{long}") + if (block_given?) + define_method(fname, &block) + else + define_method(fname) do |value| + self.options["#{long}".to_sym] = value + end + end + @opt_parser_commands ||= [] + @opt_parser_commands << [options, fname] + end - def should_parse_config? - unless @parse_config.nil? - return @parse_config + def banner(banner = nil) + @banner = banner unless banner.nil? end - @parse_config = true - end - # used to declare a new command - def command(name, &block) - meta_def(symbolize(name), &block) - end + def new_option_parser( target ) + @banner ||= nil - # used as a catch-all for unknown option - def unknown(&block) - meta_def(:handle_unknown, &block) - end + opt_parser = OptionParser.new(@banner) - # used to declare code that handle an option - def option(*options, &block) - long = options.find { |opt| opt =~ /^--/ }.gsub(/^--(?:\[no-\])?([^ =]+).*$/, '\1' ).gsub('-','_') - fname = "handle_#{long}" - if (block_given?) - meta_def(symbolize(fname), &block) - else - meta_def(symbolize(fname)) do |value| - self.options["#{long}".to_sym] = value + @opt_parser_commands ||= [] + @opt_parser_commands.each do |options, fname| + opt_parser.on(*options) do |value| + target.send(fname, value) + end end + opt_parser end - @opt_parser.on(*options) do |value| - self.send(symbolize(fname), value) + + def find(name) + self.const_get(name.to_s.capitalize) end - end - # used to declare accessor in a more natural way in the - # various applications - def attr_accessor(*args) - args.each do |arg| - meta_def(arg) do - instance_variable_get("@#{arg}".to_sym) - end - meta_def("#{arg}=") do |value| - instance_variable_set("@#{arg}".to_sym, value) - end + def [](name) + find(name).new end end - # used to declare code run instead the default setup - def setup(&block) - meta_def(:run_setup, &block) - end + attr_reader :options, :opt_parser - # used to declare code to choose which command to run - def dispatch(&block) - meta_def(:get_command, &block) + # Every app responds to --version + option("--version", "-V") do |arg| + puts "%s" % Puppet.version + exit end - # used to execute code before running anything else - def preinit(&block) - meta_def(:run_preinit, &block) + # Every app responds to --help + option("--help", "-h") do |v| + help end - def initialize(name, banner = nil, &block) - @opt_parser = OptionParser.new(banner) - - @name = symbolize(name) - - init_default - - @options = {} - - instance_eval(&block) if block_given? - - @@applications[@name] = self + def should_parse_config? + self.class.should_parse_config? end - # initialize default application behaviour - def init_default - setup do - default_setup - end - - dispatch do - :main - end - - # empty by default - preinit do - end + # override to execute code before running anything else + def preinit + end - option("--version", "-V") do |arg| - puts "%s" % Puppet.version - exit - end + def initialize + @opt_parser = self.class.new_option_parser( self ) - option("--help", "-h") do |v| - help - end + @options = {} end # This is the main application entry point def run - exit_on_fail("initialize") { run_preinit } + exit_on_fail("initialize") { preinit } exit_on_fail("parse options") { parse_options } exit_on_fail("parse configuration file") { Puppet.settings.parse } if should_parse_config? - exit_on_fail("prepare for execution") { run_setup } + exit_on_fail("prepare for execution") { setup } exit_on_fail("run") { run_command } end def main raise NotImplementedError, "No valid command or main" end def run_command - if command = get_command() and respond_to?(command) - send(command) - else - main - end + main end - def default_setup + def setup # Handle the logging settings if options[:debug] or options[:verbose] Puppet::Util::Log.newdestination(:console) if options[:debug] Puppet::Util::Log.level = :debug else Puppet::Util::Log.level = :info end end unless options[:setdest] Puppet::Util::Log.newdestination(:syslog) end end def parse_options # get all puppet options optparse_opt = [] optparse_opt = Puppet.settings.optparse_addargs(optparse_opt) # convert them to OptionParser format optparse_opt.each do |option| @opt_parser.on(*option) do |arg| handlearg(option[0], arg) end end # scan command line argument begin @opt_parser.parse! rescue OptionParser::ParseError => detail $stderr.puts detail $stderr.puts "Try '#{$0} --help'" exit(1) end end def handlearg(opt, arg) # rewrite --[no-]option to --no-option if that's what was given if opt =~ /\[no-\]/ and !arg opt = opt.gsub(/\[no-\]/,'no-') end # otherwise remove the [no-] prefix to not confuse everybody opt = opt.gsub(/\[no-\]/, '') unless respond_to?(:handle_unknown) and send(:handle_unknown, opt, arg) # Puppet.settings.handlearg doesn't handle direct true/false :-) if arg.is_a?(FalseClass) arg = "false" elsif arg.is_a?(TrueClass) arg = "true" end Puppet.settings.handlearg(opt, arg) end end # this is used for testing def self.exit(code) exit(code) end + def name + self.class.to_s.sub(/.*::/,"").downcase.to_sym + end + def help if Puppet.features.usage? # RH:FIXME: My goodness, this is ugly. - ::RDoc.const_set("PuppetSourceFile", @name) + ::RDoc.const_set("PuppetSourceFile", name) def (::RDoc).caller docfile = `grep -l 'Puppet::Application\\[:#{::RDoc::PuppetSourceFile}\\]' #{BINDIRS}`.chomp super << "#{docfile}:0" end ::RDoc::usage && exit else puts "No help available unless you have RDoc::usage installed" exit end rescue Errno::ENOENT - puts "No help available for puppet #@name" + puts "No help available for puppet #{name}" exit end private def exit_on_fail(message, code = 1) begin yield rescue RuntimeError, NotImplementedError => detail puts detail.backtrace if Puppet[:trace] $stderr.puts "Could not %s: %s" % [message, detail] exit(code) end end end diff --git a/lib/puppet/application/agent.rb b/lib/puppet/application/agent.rb index 985d87dd0..093e5b94d 100644 --- a/lib/puppet/application/agent.rb +++ b/lib/puppet/application/agent.rb @@ -1,286 +1,286 @@ require 'puppet' require 'puppet/application' require 'puppet/agent' require 'puppet/daemon' require 'puppet/configurer' require 'puppet/network/client' -Puppet::Application.new(:agent) do +class Puppet::Application::Agent < Puppet::Application should_parse_config attr_accessor :explicit_waitforcert, :args, :agent, :daemon, :host - preinit do + def preinit # Do an initial trap, so that cancels don't get a stack trace. trap(:INT) do $stderr.puts "Cancelling startup" exit(0) end { :waitforcert => 120, # Default to checking for certs every 5 minutes :onetime => false, :detailed_exitcodes => false, :verbose => false, :debug => false, :centrallogs => false, :setdest => false, :enable => false, :disable => false, :client => true, :fqdn => nil, :serve => [], :digest => :MD5, :fingerprint => false, }.each do |opt,val| options[opt] = val end @explicit_waitforcert = false @args = {} @daemon = Puppet::Daemon.new @daemon.argv = ARGV.dup end option("--centrallogging") option("--disable") option("--enable") option("--debug","-d") option("--fqdn FQDN","-f") option("--test","-t") option("--verbose","-v") option("--fingerprint") option("--digest DIGEST") option("--serve HANDLER", "-s") do |arg| if Puppet::Network::Handler.handler(arg) options[:serve] << arg.to_sym else raise "Could not find handler for %s" % arg end end option("--no-client") do |arg| options[:client] = false end option("--onetime", "-o") do |arg| options[:onetime] = true options[:waitforcert] = 0 unless @explicit_waitforcert end option("--detailed-exitcodes") do |arg| options[:detailed_exitcodes] = true end option("--logdest DEST", "-l DEST") do |arg| begin Puppet::Util::Log.newdestination(arg) options[:setdest] = true rescue => detail if Puppet[:debug] puts detail.backtrace end $stderr.puts detail.to_s end end option("--waitforcert WAITFORCERT", "-w") do |arg| options[:waitforcert] = arg.to_i @explicit_waitforcert = true end option("--port PORT","-p") do |arg| @args[:Port] = arg end - dispatch do - return :fingerprint if options[:fingerprint] - return :onetime if options[:onetime] - return :main + def run_command + return fingerprint if options[:fingerprint] + return onetime if options[:onetime] + return main end - command(:fingerprint) do + def fingerprint unless cert = host.certificate || host.certificate_request $stderr.puts "Fingerprint asked but no certificate nor certificate request have yet been issued" exit(1) return end unless fingerprint = cert.fingerprint(options[:digest]) raise ArgumentError, "Could not get fingerprint for digest '#{options[:digest]}'" end Puppet.notice fingerprint end - command(:onetime) do + def onetime unless options[:client] $stderr.puts "onetime is specified but there is no client" exit(43) return end @daemon.set_signal_traps begin report = @agent.run rescue => detail if Puppet[:trace] puts detail.backtrace end Puppet.err detail.to_s end if not report exit(1) elsif not Puppet[:noop] and options[:detailed_exitcodes] then exit(report.exit_status) else exit(0) end end - command(:main) do + def main Puppet.notice "Starting Puppet client version %s" % [Puppet.version] @daemon.start end # Enable all of the most common test options. def setup_test Puppet.settings.handlearg("--ignorecache") Puppet.settings.handlearg("--no-usecacheonfailure") Puppet.settings.handlearg("--no-splay") Puppet.settings.handlearg("--show_diff") Puppet.settings.handlearg("--no-daemonize") options[:verbose] = true options[:onetime] = true options[:detailed_exitcodes] = true options[:waitforcert] = 0 unless @explicit_waitforcert end # Handle the logging settings. def setup_logs if options[:debug] or options[:verbose] Puppet::Util::Log.newdestination(:console) if options[:debug] Puppet::Util::Log.level = :debug else Puppet::Util::Log.level = :info end end unless options[:setdest] Puppet::Util::Log.newdestination(:syslog) end end def enable_disable_client(agent) if options[:enable] agent.enable elsif options[:disable] agent.disable end exit(0) end def setup_listen unless FileTest.exists?(Puppet[:authconfig]) Puppet.err "Will not start without authorization file %s" % Puppet[:authconfig] exit(14) end handlers = nil if options[:serve].empty? handlers = [:Runner] else handlers = options[:serve] end require 'puppet/network/server' # No REST handlers yet. server = Puppet::Network::Server.new(:xmlrpc_handlers => handlers, :port => Puppet[:puppetport]) @daemon.server = server end - setup do + def setup setup_test if options[:test] setup_logs if Puppet.settings.print_configs? exit(Puppet.settings.print_configs ? 0 : 1) end # If noop is set, then also enable diffs if Puppet[:noop] Puppet[:show_diff] = true end args[:Server] = Puppet[:server] if options[:fqdn] args[:FQDN] = options[:fqdn] Puppet[:certname] = options[:fqdn] end if options[:centrallogs] logdest = args[:Server] if args.include?(:Port) logdest += ":" + args[:Port] end Puppet::Util::Log.newdestination(logdest) end Puppet.settings.use :main, :puppetd, :ssl # We need to specify a ca location for all of the SSL-related i # indirected classes to work; in fingerprint mode we just need # access to the local files and we don't need a ca. Puppet::SSL::Host.ca_location = options[:fingerprint] ? :none : :remote Puppet::Transaction::Report.terminus_class = :rest # Override the default; puppetd needs this, usually. # You can still override this on the command-line with, e.g., :compiler. Puppet[:catalog_terminus] = :rest Puppet::Resource::Catalog.cache_class = :yaml Puppet::Node::Facts.terminus_class = :facter # We need tomake the client either way, we just don't start it # if --no-client is set. @agent = Puppet::Agent.new(Puppet::Configurer) enable_disable_client(@agent) if options[:enable] or options[:disable] @daemon.agent = agent if options[:client] # It'd be nice to daemonize later, but we have to daemonize before the # waitforcert happens. if Puppet[:daemonize] @daemon.daemonize end @host = Puppet::SSL::Host.new unless options[:fingerprint] cert = @host.wait_for_cert(options[:waitforcert]) end @objects = [] # This has to go after the certs are dealt with. if Puppet[:listen] unless options[:onetime] setup_listen else Puppet.notice "Ignoring --listen on onetime run" end end end end diff --git a/lib/puppet/application/apply.rb b/lib/puppet/application/apply.rb index d977cf1d0..88385f0a0 100644 --- a/lib/puppet/application/apply.rb +++ b/lib/puppet/application/apply.rb @@ -1,183 +1,183 @@ require 'puppet' require 'puppet/application' require 'puppet/configurer' require 'puppet/network/handler' require 'puppet/network/client' -Puppet::Application.new(:apply) do +class Puppet::Application::Apply < Puppet::Application should_parse_config option("--debug","-d") option("--execute EXECUTE","-e") do |arg| options[:code] = arg end option("--loadclasses","-L") option("--verbose","-v") option("--use-nodes") option("--detailed-exitcodes") option("--apply catalog", "-a catalog") do |arg| options[:catalog] = arg end option("--logdest LOGDEST", "-l") do |arg| begin Puppet::Util::Log.newdestination(arg) options[:logset] = true rescue => detail $stderr.puts detail.to_s end end - dispatch do + def run_command if options[:catalog] - :apply + apply elsif Puppet[:parseonly] - :parseonly + parseonly else - :main + main end end - command(:apply) do + def apply require 'puppet/configurer' if options[:catalog] == "-" text = $stdin.read else text = File.read(options[:catalog]) end begin catalog = Puppet::Resource::Catalog.convert_from(Puppet::Resource::Catalog.default_format,text) unless catalog.is_a?(Puppet::Resource::Catalog) catalog = Puppet::Resource::Catalog.pson_create(catalog) end rescue => detail raise Puppet::Error, "Could not deserialize catalog from pson: %s" % detail end catalog = catalog.to_ral configurer = Puppet::Configurer.new configurer.run :catalog => catalog end - command(:parseonly) do + def parseonly # Set our code or file to use. if options[:code] or Puppet::Util::CommandLine.args.length == 0 Puppet[:code] = options[:code] || STDIN.read else Puppet[:manifest] = Puppet::Util::CommandLine.args.shift end begin Puppet::Resource::TypeCollection.new(Puppet[:environment]).perform_initial_import rescue => detail Puppet.err detail exit 1 end exit 0 end - command(:main) do + def main # Set our code or file to use. if options[:code] or Puppet::Util::CommandLine.args.length == 0 Puppet[:code] = options[:code] || STDIN.read else Puppet[:manifest] = Puppet::Util::CommandLine.args.shift end # Collect our facts. unless facts = Puppet::Node::Facts.find(Puppet[:certname]) raise "Could not find facts for %s" % Puppet[:certname] end # Find our Node unless node = Puppet::Node.find(Puppet[:certname]) raise "Could not find node %s" % Puppet[:certname] end # Merge in the facts. node.merge(facts.values) # Allow users to load the classes that puppetd creates. if options[:loadclasses] file = Puppet[:classfile] if FileTest.exists?(file) unless FileTest.readable?(file) $stderr.puts "%s is not readable" % file exit(63) end node.classes = File.read(file).split(/[\s\n]+/) end end begin # Compile our catalog starttime = Time.now catalog = Puppet::Resource::Catalog.find(node.name, :use_node => node) # Translate it to a RAL catalog catalog = catalog.to_ral catalog.host_config = true if Puppet[:graph] or Puppet[:report] catalog.finalize catalog.retrieval_duration = Time.now - starttime configurer = Puppet::Configurer.new configurer.execute_prerun_command # And apply it transaction = catalog.apply configurer.execute_postrun_command status = 0 if not Puppet[:noop] and options[:detailed_exitcodes] then transaction.generate_report exit(transaction.report.exit_status) else exit(0) end rescue => detail puts detail.backtrace if Puppet[:trace] if detail.is_a?(XMLRPC::FaultException) $stderr.puts detail.message else $stderr.puts detail end exit(1) end end - setup do + def setup if Puppet.settings.print_configs? exit(Puppet.settings.print_configs ? 0 : 1) end # If noop is set, then also enable diffs if Puppet[:noop] Puppet[:show_diff] = true end unless options[:logset] Puppet::Util::Log.newdestination(:console) end client = nil server = nil trap(:INT) do $stderr.puts "Exiting" exit(1) end if options[:debug] Puppet::Util::Log.level = :debug elsif options[:verbose] Puppet::Util::Log.level = :info end end end diff --git a/lib/puppet/application/cert.rb b/lib/puppet/application/cert.rb index 7a7784b09..92da03ca7 100644 --- a/lib/puppet/application/cert.rb +++ b/lib/puppet/application/cert.rb @@ -1,76 +1,76 @@ require 'puppet' require 'puppet/application' require 'puppet/ssl/certificate_authority' -Puppet::Application.new(:cert) do +class Puppet::Application::Cert < Puppet::Application should_parse_config attr_accessor :mode, :all, :ca, :digest def find_mode(opt) modes = Puppet::SSL::CertificateAuthority::Interface::INTERFACE_METHODS tmp = opt.sub("--", '').to_sym @mode = modes.include?(tmp) ? tmp : nil end option("--clean", "-c") do @mode = :destroy end option("--all", "-a") do @all = true end option("--digest DIGEST") do |arg| @digest = arg end option("--debug", "-d") do |arg| Puppet::Util::Log.level = :debug end Puppet::SSL::CertificateAuthority::Interface::INTERFACE_METHODS.reject {|m| m == :destroy }.each do |method| option("--#{method}", "-%s" % method.to_s[0,1] ) do find_mode("--#{method}") end end option("--verbose", "-v") do Puppet::Util::Log.level = :info end - command(:main) do + def main if @all hosts = :all else hosts = Puppet::Util::CommandLine.args.collect { |h| puts h; h.downcase } end begin @ca.apply(:revoke, :to => hosts) if @mode == :destroy @ca.apply(@mode, :to => hosts, :digest => @digest) rescue => detail puts detail.backtrace if Puppet[:trace] puts detail.to_s exit(24) end end - setup do + def setup if Puppet.settings.print_configs? exit(Puppet.settings.print_configs ? 0 : 1) end Puppet::Util::Log.newdestination :console Puppet::SSL::Host.ca_location = :only begin @ca = Puppet::SSL::CertificateAuthority.new rescue => detail puts detail.backtrace if Puppet[:trace] puts detail.to_s exit(23) end end end diff --git a/lib/puppet/application/describe.rb b/lib/puppet/application/describe.rb index ea4ac162c..45f017a48 100644 --- a/lib/puppet/application/describe.rb +++ b/lib/puppet/application/describe.rb @@ -1,214 +1,215 @@ require 'puppet' require 'puppet/application' class Formatter def initialize(width) @width = width end def wrap(txt, opts) return "" unless txt && !txt.empty? work = (opts[:scrub] ? scrub(txt) : txt) indent = (opts[:indent] ? opts[:indent] : 0) textLen = @width - indent patt = Regexp.new("^(.{0,#{textLen}})[ \n]") prefix = " " * indent res = [] while work.length > textLen if work =~ patt res << $1 work.slice!(0, $&.length) else res << work.slice!(0, textLen) end end res << work if work.length.nonzero? return prefix + res.join("\n" + prefix) end def header(txt, sep = "-") "\n#{txt}\n" + sep * txt.size end private def scrub(text) # For text with no carriage returns, there's nothing to do. if text !~ /\n/ return text end indent = nil # If we can match an indentation, then just remove that same level of # indent from every line. if text =~ /^(\s+)/ indent = $1 return text.gsub(/^#{indent}/,'') else return text end end end class TypeDoc def initialize @format = Formatter.new(76) @types = {} Puppet::Type.loadall Puppet::Type.eachtype { |type| next if type.name == :component @types[type.name] = type } end def list_types puts "These are the types known to puppet:\n" @types.keys.sort { |a, b| a.to_s <=> b.to_s }.each do |name| type = @types[name] s = type.doc.gsub(/\s+/, " ") n = s.index(".") if n.nil? s = ".. no documentation .." elsif n > 45 s = s[0, 45] + " ..." else s = s[0, n] end printf "%-15s - %s\n", name, s end end def format_type(name, opts) name = name.to_sym unless @types.has_key?(name) puts "Unknown type #{name}" return end type = @types[name] puts @format.header(name.to_s, "=") puts @format.wrap(type.doc, :indent => 0, :scrub => true) + "\n\n" puts @format.header("Parameters") if opts[:parameters] format_attrs(type, [:property, :param]) else list_attrs(type, [:property, :param]) end if opts[:meta] puts @format.header("Meta Parameters") if opts[:parameters] format_attrs(type, [:meta]) else list_attrs(type, [:meta]) end end if type.providers.size > 0 puts @format.header("Providers") if opts[:providers] format_providers(type) else list_providers(type) end end end # List details about attributes def format_attrs(type, attrs) docs = {} type.allattrs.each do |name| kind = type.attrtype(name) if attrs.include?(kind) && name != :provider docs[name] = type.attrclass(name).doc end end docs.sort { |a,b| a[0].to_s <=> b[0].to_s }.each { |name, doc| print "\n- **%s**" % name if type.namevar == name and name != :name puts " (*namevar*)" else puts "" end puts @format.wrap(doc, :indent => 4, :scrub => true) } end # List the names of attributes def list_attrs(type, attrs) params = [] type.allattrs.each do |name| kind = type.attrtype(name) if attrs.include?(kind) && name != :provider params << name.to_s end end puts @format.wrap(params.sort.join(", "), :indent => 4) end def format_providers(type) type.providers.sort { |a,b| a.to_s <=> b.to_s }.each { |prov| puts "\n- **%s**" % prov puts @format.wrap(type.provider(prov).doc, :indent => 4, :scrub => true) } end def list_providers(type) list = type.providers.sort { |a,b| a.to_s <=> b.to_s }.join(", ") puts @format.wrap(list, :indent => 4) end end -Puppet::Application.new(:describe,"#{$0} [options] [type]") do +class Puppet::Application::Describe < Puppet::Application + banner "puppet describe [options] [type]" should_not_parse_config option("--short", "-s", "Only list parameters without detail") do |arg| options[:parameters] = false end option("--providers","-p") option("--list", "-l") option("--meta","-m") - preinit do + def preinit options[:parameters] = true end - command(:main) do + def main doc = TypeDoc.new if options[:list] doc.list_types else options[:types].each { |name| doc.format_type(name, options) } end end - setup do + def setup options[:types] = Puppet::Util::CommandLine.args.dup unless options[:list] || options[:types].size > 0 handle_help(nil) end if options[:list] && options[:types].size > 0 $stderr.puts "Warning: ignoring types when listing all types" end end end diff --git a/lib/puppet/application/doc.rb b/lib/puppet/application/doc.rb index 0a11d6045..295cd6771 100644 --- a/lib/puppet/application/doc.rb +++ b/lib/puppet/application/doc.rb @@ -1,224 +1,224 @@ require 'puppet' require 'puppet/application' require 'puppet/util/reference' require 'puppet/network/handler' require 'puppet/util/rdoc' $tab = " " Reference = Puppet::Util::Reference -Puppet::Application.new(:doc) do +class Puppet::Application::Doc < Puppet::Application should_not_parse_config attr_accessor :unknown_args, :manifest - preinit do + def preinit {:references => [], :mode => :text, :format => :to_rest }.each do |name,value| options[name] = value end @unknown_args = [] @manifest = false end option("--all","-a") option("--outputdir OUTPUTDIR","-o") option("--verbose","-v") option("--debug","-d") option("--format FORMAT", "-f") do |arg| method = "to_%s" % arg if Reference.method_defined?(method) options[:format] = method else raise "Invalid output format %s" % arg end end option("--mode MODE", "-m") do |arg| if Reference.modes.include?(arg) or arg.intern==:rdoc options[:mode] = arg.intern else raise "Invalid output mode %s" % arg end end option("--list", "-l") do |arg| puts Reference.references.collect { |r| Reference.reference(r).doc }.join("\n") exit(0) end option("--reference REFERENCE", "-r") do |arg| options[:references] << arg.intern end - unknown do |opt, arg| + def handle_unknown( opt, arg ) @unknown_args << {:opt => opt, :arg => arg } true end - dispatch do - return options[:mode] if [:rdoc, :trac, :markdown].include?(options[:mode]) - return :other + def run_command + return send(options[:mode]) if [:rdoc, :trac, :markdown].include?(options[:mode]) + return other end - command(:rdoc) do + def rdoc exit_code = 0 files = [] unless @manifest env = Puppet::Node::Environment.new files += env.modulepath files << File.dirname(env[:manifest]) end files += Puppet::Util::CommandLine.args Puppet.info "scanning: %s" % files.inspect Puppet.settings.setdefaults("puppetdoc", "document_all" => [false, "Document all resources"] ) Puppet.settings[:document_all] = options[:all] || false begin if @manifest Puppet::Util::RDoc.manifestdoc(files) else options[:outputdir] = "doc" unless options[:outputdir] Puppet::Util::RDoc.rdoc(options[:outputdir], files) end rescue => detail if Puppet[:trace] puts detail.backtrace end $stderr.puts "Could not generate documentation: %s" % detail exit_code = 1 end exit exit_code end - command(:trac) do + def trac options[:references].each do |name| section = Puppet::Util::Reference.reference(name) or raise "Could not find section %s" % name unless options[:mode] == :pdf section.trac end end end - command(:markdown) do + def markdown text = "" with_contents = false exit_code = 0 options[:references].sort { |a,b| a.to_s <=> b.to_s }.each do |name| raise "Could not find reference %s" % name unless section = Puppet::Util::Reference.reference(name) begin # Add the per-section text, but with no ToC text += section.send(options[:format], with_contents) text += Puppet::Util::Reference.footer text.gsub!(/`\w+\s+([^`]+)`:trac:/) { |m| $1 } Puppet::Util::Reference.markdown(name, text) text = "" rescue => detail puts detail.backtrace $stderr.puts "Could not generate reference %s: %s" % [name, detail] exit_code = 1 next end end exit exit_code end - command(:other) do + def other text = "" if options[:references].length > 1 with_contents = false else with_contents = true end exit_code = 0 options[:references].sort { |a,b| a.to_s <=> b.to_s }.each do |name| raise "Could not find reference %s" % name unless section = Puppet::Util::Reference.reference(name) begin # Add the per-section text, but with no ToC text += section.send(options[:format], with_contents) rescue => detail puts detail.backtrace $stderr.puts "Could not generate reference %s: %s" % [name, detail] exit_code = 1 next end end unless with_contents # We've only got one reference text += Puppet::Util::Reference.footer end # Replace the trac links, since they're invalid everywhere else text.gsub!(/`\w+\s+([^`]+)`:trac:/) { |m| $1 } if options[:mode] == :pdf Puppet::Util::Reference.pdf(text) else puts text end exit exit_code end - setup do + def setup # sole manifest documentation if Puppet::Util::CommandLine.args.size > 0 options[:mode] = :rdoc @manifest = true end if options[:mode] == :rdoc setup_rdoc else setup_reference end end def setup_reference if options[:all] # Don't add dynamic references to the "all" list. options[:references] = Reference.references.reject do |ref| Reference.reference(ref).dynamic? end end if options[:references].empty? options[:references] << :type end end def setup_rdoc(dummy_argument=:work_arround_for_ruby_GC_bug) # consume the unknown options # and feed them as settings if @unknown_args.size > 0 @unknown_args.each do |option| # force absolute path for modulepath when passed on commandline if option[:opt]=="--modulepath" or option[:opt] == "--manifestdir" option[:arg] = option[:arg].split(':').collect { |p| File.expand_path(p) }.join(':') end Puppet.settings.handlearg(option[:opt], option[:arg]) end end # hack to get access to puppetmasterd modulepath and manifestdir Puppet[:name] = "puppetmasterd" # Now parse the config Puppet.parse_config # Handle the logging settings. if options[:debug] or options[:verbose] if options[:debug] Puppet::Util::Log.level = :debug else Puppet::Util::Log.level = :info end Puppet::Util::Log.newdestination(:console) end end end diff --git a/lib/puppet/application/filebucket.rb b/lib/puppet/application/filebucket.rb index cd7c854af..ddc46e394 100644 --- a/lib/puppet/application/filebucket.rb +++ b/lib/puppet/application/filebucket.rb @@ -1,92 +1,92 @@ require 'puppet' require 'puppet/application' require 'puppet/file_bucket/dipper' -Puppet::Application.new(:filebucket) do +class Puppet::Application::Filebucket < Puppet::Application should_not_parse_config option("--bucket BUCKET","-b") option("--debug","-d") option("--local","-l") option("--remote","-r") option("--verbose","-v") - class << self - attr :args - end + attr :args - dispatch do + def run_command @args = Puppet::Util::CommandLine.args - args.shift + command = args.shift + return send(command) if %w[get backup restore].include? command + help end - command(:get) do + def get md5 = args.shift out = @client.getfile(md5) print out end - command(:backup) do + def backup args.each do |file| unless FileTest.exists?(file) $stderr.puts "%s: no such file" % file next end unless FileTest.readable?(file) $stderr.puts "%s: cannot read file" % file next end md5 = @client.backup(file) puts "%s: %s" % [file, md5] end end - command(:restore) do + def restore file = args.shift md5 = args.shift @client.restore(file, md5) end - setup do + def setup Puppet::Log.newdestination(:console) @client = nil @server = nil trap(:INT) do $stderr.puts "Cancelling" exit(1) end if options[:debug] Puppet::Log.level = :debug elsif options[:verbose] Puppet::Log.level = :info end # Now parse the config Puppet.parse_config if Puppet.settings.print_configs? exit(Puppet.settings.print_configs ? 0 : 1) end begin if options[:local] or options[:bucket] path = options[:bucket] || Puppet[:bucketdir] @client = Puppet::FileBucket::Dipper.new(:Path => path) else @client = Puppet::FileBucket::Dipper.new(:Server => Puppet[:server]) end rescue => detail $stderr.puts detail if Puppet[:trace] puts detail.backtrace end exit(1) end end end diff --git a/lib/puppet/application/kick.rb b/lib/puppet/application/kick.rb index 7b4993bb4..37d3e533f 100644 --- a/lib/puppet/application/kick.rb +++ b/lib/puppet/application/kick.rb @@ -1,214 +1,213 @@ require 'puppet' require 'puppet/application' Puppet.warning "RubyGems not installed" unless Puppet.features.rubygems? Puppet.warning "Failed to load ruby LDAP library. LDAP functionality will not be available" unless Puppet.features.ldap? -Puppet::Application.new(:kick) do +class Puppet::Application::Kick < Puppet::Application should_not_parse_config attr_accessor :hosts, :tags, :classes option("--all","-a") option("--foreground","-f") option("--debug","-d") option("--ping","-P") option("--test") option("--host HOST") do |arg| @hosts << arg end option("--tag TAG", "-t") do |arg| @tags << arg end option("--class CLASS", "-c") do |arg| @classes << arg end option("--no-fqdn", "-n") do |arg| options[:fqdn] = false end option("--parallel PARALLEL", "-p") do |arg| begin options[:parallel] = Integer(arg) rescue $stderr.puts "Could not convert %s to an integer" % arg.inspect exit(23) end end - - dispatch do - options[:test] ? :test : :main + def run_command + options[:test] ? test : main end - command(:test) do + def test puts "Skipping execution in test mode" exit(0) end - command(:main) do + def main require 'puppet/network/client' require 'puppet/util/ldap/connection' todo = @hosts.dup failures = [] # Now do the actual work go = true while go # If we don't have enough children in process and we still have hosts left to # do, then do the next host. if @children.length < options[:parallel] and ! todo.empty? host = todo.shift pid = fork do run_for_host(host) end @children[pid] = host else # Else, see if we can reap a process. begin pid = Process.wait if host = @children[pid] # Remove our host from the list of children, so the parallelization # continues working. @children.delete(pid) if $?.exitstatus != 0 failures << host end print "%s finished with exit code %s\n" % [host, $?.exitstatus] else $stderr.puts "Could not find host for PID %s with status %s" % [pid, $?.exitstatus] end rescue Errno::ECHILD # There are no children left, so just exit unless there are still # children left to do. next unless todo.empty? if failures.empty? puts "Finished" exit(0) else puts "Failed: %s" % failures.join(", ") exit(3) end end end end end def run_for_host(host) if options[:ping] out = %x{ping -c 1 #{host}} unless $? == 0 $stderr.print "Could not contact %s\n" % host next end end require 'puppet/run' Puppet::Run.indirection.terminus_class = :rest port = Puppet[:puppetport] url = ["https://#{host}:#{port}", "production", "run", host].join('/') print "Triggering %s\n" % host begin run_options = { :tags => @tags, :background => ! options[:foreground], :ignoreschedules => options[:ignoreschedules] } run = Puppet::Run.new( run_options ).save( url ) puts "Getting status" result = run.status puts "status is #{result}" rescue => detail puts detail.backtrace if Puppet[:trace] $stderr.puts "Host %s failed: %s\n" % [host, detail] exit(2) end case result when "success"; exit(0) when "running" $stderr.puts "Host %s is already running" % host exit(3) else $stderr.puts "Host %s returned unknown answer '%s'" % [host, result] exit(12) end end - preinit do + def preinit [:INT, :TERM].each do |signal| trap(signal) do $stderr.puts "Cancelling" exit(1) end end options[:parallel] = 1 options[:verbose] = true options[:fqdn] = true options[:ignoreschedules] = false options[:foreground] = false @hosts = [] @classes = [] @tags = [] end - setup do + def setup if options[:debug] Puppet::Util::Log.level = :debug else Puppet::Util::Log.level = :info end # Now parse the config Puppet.parse_config if Puppet[:node_terminus] == "ldap" and (options[:all] or @classes) if options[:all] @hosts = Puppet::Node.search("whatever", :fqdn => options[:fqdn]).collect { |node| node.name } puts "all: %s" % @hosts.join(", ") else @hosts = [] @classes.each do |klass| list = Puppet::Node.search("whatever", :fqdn => options[:fqdn], :class => klass).collect { |node| node.name } puts "%s: %s" % [klass, list.join(", ")] @hosts += list end end elsif ! @classes.empty? $stderr.puts "You must be using LDAP to specify host classes" exit(24) end @children = {} # If we get a signal, then kill all of our children and get out. [:INT, :TERM].each do |signal| trap(signal) do Puppet.notice "Caught #{signal}; shutting down" @children.each do |pid, host| Process.kill("INT", pid) end waitall exit(1) end end end end diff --git a/lib/puppet/application/master.rb b/lib/puppet/application/master.rb index 8f1c0cd95..2433780c2 100644 --- a/lib/puppet/application/master.rb +++ b/lib/puppet/application/master.rb @@ -1,167 +1,167 @@ require 'puppet' require 'puppet/application' require 'puppet/daemon' require 'puppet/network/server' require 'puppet/network/http/rack' if Puppet.features.rack? -Puppet::Application.new(:master) do +class Puppet::Application::Master < Puppet::Application should_parse_config option("--debug", "-d") option("--verbose", "-v") # internal option, only to be used by ext/rack/config.ru option("--rack") option("--compile host", "-c host") do |arg| options[:node] = arg end option("--logdest DEST", "-l DEST") do |arg| begin Puppet::Util::Log.newdestination(arg) options[:setdest] = true rescue => detail if Puppet[:debug] puts detail.backtrace end $stderr.puts detail.to_s end end - preinit do + def preinit trap(:INT) do $stderr.puts "Cancelling startup" exit(0) end # Create this first-off, so we have ARGV @daemon = Puppet::Daemon.new @daemon.argv = ARGV.dup end - dispatch do + def run_command if options[:node] - :compile + compile elsif Puppet[:parseonly] - :parseonly + parseonly else - :main + main end end - command(:compile) do + def compile Puppet::Util::Log.newdestination :console raise ArgumentError, "Cannot render compiled catalogs without pson support" unless Puppet.features.pson? begin unless catalog = Puppet::Resource::Catalog.find(options[:node]) raise "Could not compile catalog for %s" % options[:node] end $stdout.puts catalog.render(:pson) rescue => detail $stderr.puts detail exit(30) end exit(0) end - command(:parseonly) do + def parseonly begin Puppet::Resource::TypeCollection.new(Puppet[:environment]).perform_initial_import rescue => detail Puppet.err detail exit 1 end exit(0) end - command(:main) do + def main require 'etc' require 'puppet/file_serving/content' require 'puppet/file_serving/metadata' xmlrpc_handlers = [:Status, :FileServer, :Master, :Report, :Filebucket] if Puppet[:ca] xmlrpc_handlers << :CA end # Make sure we've got a localhost ssl cert Puppet::SSL::Host.localhost # And now configure our server to *only* hit the CA for data, because that's # all it will have write access to. if Puppet::SSL::CertificateAuthority.ca? Puppet::SSL::Host.ca_location = :only end if Process.uid == 0 begin Puppet::Util.chuser rescue => detail puts detail.backtrace if Puppet[:trace] $stderr.puts "Could not change user to %s: %s" % [Puppet[:user], detail] exit(39) end end unless options[:rack] @daemon.server = Puppet::Network::Server.new(:xmlrpc_handlers => xmlrpc_handlers) @daemon.daemonize if Puppet[:daemonize] else require 'puppet/network/http/rack' @app = Puppet::Network::HTTP::Rack.new(:xmlrpc_handlers => xmlrpc_handlers, :protocols => [:rest, :xmlrpc]) end Puppet.notice "Starting Puppet master version %s" % [Puppet.version] unless options[:rack] @daemon.start else return @app end end - setup do + def setup # Handle the logging settings. if options[:debug] or options[:verbose] if options[:debug] Puppet::Util::Log.level = :debug else Puppet::Util::Log.level = :info end unless Puppet[:daemonize] or options[:rack] Puppet::Util::Log.newdestination(:console) options[:setdest] = true end end unless options[:setdest] Puppet::Util::Log.newdestination(:syslog) end if Puppet.settings.print_configs? exit(Puppet.settings.print_configs ? 0 : 1) end Puppet.settings.use :main, :puppetmasterd, :ssl # A temporary solution, to at least make the master work for now. Puppet::Node::Facts.terminus_class = :yaml # Cache our nodes in yaml. Currently not configurable. Puppet::Node.cache_class = :yaml # Configure all of the SSL stuff. if Puppet::SSL::CertificateAuthority.ca? Puppet::SSL::Host.ca_location = :local Puppet.settings.use :ca Puppet::SSL::CertificateAuthority.instance else Puppet::SSL::Host.ca_location = :none end end end diff --git a/lib/puppet/application/queue.rb b/lib/puppet/application/queue.rb index 13fb3e107..4b3aa57b5 100644 --- a/lib/puppet/application/queue.rb +++ b/lib/puppet/application/queue.rb @@ -1,96 +1,95 @@ require 'puppet' require 'puppet/daemon' require 'puppet/application' require 'puppet/resource/catalog' require 'puppet/indirector/catalog/queue' require 'puppet/util' -Puppet::Application.new(:queue) do - extend Puppet::Util +class Puppet::Application::Queue < Puppet::Application should_parse_config attr_accessor :daemon - preinit do + def preinit @daemon = Puppet::Daemon.new @daemon.argv = ARGV.dup Puppet::Util::Log.newdestination(:console) # Do an initial trap, so that cancels don't get a stack trace. # This exits with exit code 1 trap(:INT) do $stderr.puts "Caught SIGINT; shutting down" exit(1) end # This is a normal shutdown, so code 0 trap(:TERM) do $stderr.puts "Caught SIGTERM; shutting down" exit(0) end { :verbose => false, :debug => false }.each do |opt,val| options[opt] = val end end option("--debug","-d") option("--verbose","-v") - command(:main) do + def main Puppet.notice "Starting puppetqd %s" % Puppet.version Puppet::Resource::Catalog::Queue.subscribe do |catalog| # Once you have a Puppet::Resource::Catalog instance, calling save() on it should suffice # to put it through to the database via its active_record indirector (which is determined # by the terminus_class = :active_record setting above) - benchmark(:notice, "Processing queued catalog for %s" % catalog.name) do + Puppet::Util.benchmark(:notice, "Processing queued catalog for %s" % catalog.name) do begin catalog.save rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not save queued catalog for %s: %s" % [catalog.name, detail] end end end Thread.list.each { |thread| thread.join } end # Handle the logging settings. def setup_logs if options[:debug] or options[:verbose] Puppet::Util::Log.newdestination(:console) if options[:debug] Puppet::Util::Log.level = :debug else Puppet::Util::Log.level = :info end end end - setup do + def setup unless Puppet.features.stomp? raise ArgumentError, "Could not load the 'stomp' library, which must be present for queueing to work. You must install the required library." end setup_logs if Puppet.settings.print_configs? exit(Puppet.settings.print_configs ? 0 : 1) end Puppet::Resource::Catalog.terminus_class = :active_record daemon.daemonize if Puppet[:daemonize] # We want to make sure that we don't have a cache # class set up, because if storeconfigs is enabled, # we'll get a loop of continually caching the catalog # for storage again. Puppet::Resource::Catalog.cache_class = nil end end diff --git a/lib/puppet/application/resource.rb b/lib/puppet/application/resource.rb index 78aed95c5..52320e7a1 100644 --- a/lib/puppet/application/resource.rb +++ b/lib/puppet/application/resource.rb @@ -1,124 +1,124 @@ require 'puppet' require 'puppet/application' require 'facter' -Puppet::Application.new(:resource) do +class Puppet::Application::Resource < Puppet::Application should_not_parse_config attr_accessor :host, :extra_params - preinit do + def preinit @extra_params = [] @host = nil Facter.loadfacts end option("--debug","-d") option("--verbose","-v") option("--edit","-e") option("--host HOST","-H") do |arg| @host = arg end option("--types", "-t") do |arg| types = [] Puppet::Type.loadall Puppet::Type.eachtype do |t| next if t.name == :component types << t.name.to_s end puts types.sort exit end option("--param PARAM", "-p") do |arg| @extra_params << arg.to_sym end - command(:main) do + def main args = Puppet::Util::CommandLine.args type = args.shift or raise "You must specify the type to display" typeobj = Puppet::Type.type(type) or raise "Could not find type #{type}" name = args.shift params = {} args.each do |setting| if setting =~ /^(\w+)=(.+)$/ params[$1] = $2 else raise "Invalid parameter setting %s" % setting end end if options[:edit] and @host raise "You cannot edit a remote host" end properties = typeobj.properties.collect { |s| s.name } format = proc {|trans| trans.dup.collect do |param, value| if value.nil? or value.to_s.empty? trans.delete(param) elsif value.to_s == "absent" and param.to_s != "ensure" trans.delete(param) end unless properties.include?(param) or @extra_params.include?(param) trans.delete(param) end end trans.to_manifest } if @host Puppet::Resource.indirection.terminus_class = :rest port = Puppet[:puppetport] key = ["https://#{host}:#{port}", "production", "resources", type, name].join('/') else key = [type, name].join('/') end text = if name if params.empty? [ Puppet::Resource.find( key ) ] else [ Puppet::Resource.new( type, name, params ).save( key ) ] end else Puppet::Resource.search( key, {} ) end.map(&format).join("\n") if options[:edit] file = "/tmp/x2puppet-#{Process.pid}.pp" begin File.open(file, "w") do |f| f.puts text end ENV["EDITOR"] ||= "vi" system(ENV["EDITOR"], file) system("puppet -v " + file) ensure #if FileTest.exists? file # File.unlink(file) #end end else puts text end end - setup do + def setup Puppet::Util::Log.newdestination(:console) # Now parse the config Puppet.parse_config if options[:debug] Puppet::Util::Log.level = :debug elsif options[:verbose] Puppet::Util::Log.level = :info end end end diff --git a/spec/unit/application.rb b/spec/unit/application.rb index 87a90099a..c18aa1903 100755 --- a/spec/unit/application.rb +++ b/spec/unit/application.rb @@ -1,547 +1,487 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../spec_helper' require 'puppet/application' require 'puppet' require 'getoptlong' describe Puppet::Application do - before :each do - @app = Puppet::Application.new(:test) + before do + @app = Class.new(Puppet::Application).new end it "should have a run entry-point" do @app.should respond_to(:run) end it "should have a read accessor to options" do @app.should respond_to(:options) end - it "should create a default run_setup method" do - @app.should respond_to(:run_setup) + it "should include a default setup method" do + @app.should respond_to(:setup) end - it "should create a default run_preinit method" do - @app.should respond_to(:run_preinit) + it "should include a default preinit method" do + @app.should respond_to(:preinit) end - it "should create a default get_command method" do - @app.should respond_to(:get_command) + it "should include a default run_command method" do + @app.should respond_to(:run_command) end - it "should return :main as default get_command" do - @app.get_command.should == :main + it "should invoke main as the default" do + @app.expects( :main ) + @app.run_command end describe 'when invoking clear!' do before :each do Puppet::Application.run_status = :stop_requested Puppet::Application.clear! end it 'should have nil run_status' do Puppet::Application.run_status.should be_nil end it 'should return false for restart_requested?' do Puppet::Application.restart_requested?.should be_false end it 'should return false for stop_requested?' do Puppet::Application.stop_requested?.should be_false end it 'should return false for interrupted?' do Puppet::Application.interrupted?.should be_false end it 'should return true for clear?' do Puppet::Application.clear?.should be_true end end describe 'after invoking stop!' do before :each do Puppet::Application.run_status = nil Puppet::Application.stop! end after :each do Puppet::Application.run_status = nil end it 'should have run_status of :stop_requested' do Puppet::Application.run_status.should == :stop_requested end it 'should return true for stop_requested?' do Puppet::Application.stop_requested?.should be_true end it 'should return false for restart_requested?' do Puppet::Application.restart_requested?.should be_false end it 'should return true for interrupted?' do Puppet::Application.interrupted?.should be_true end it 'should return false for clear?' do Puppet::Application.clear?.should be_false end end describe 'when invoking restart!' do before :each do Puppet::Application.run_status = nil Puppet::Application.restart! end after :each do Puppet::Application.run_status = nil end it 'should have run_status of :restart_requested' do Puppet::Application.run_status.should == :restart_requested end it 'should return true for restart_requested?' do Puppet::Application.restart_requested?.should be_true end it 'should return false for stop_requested?' do Puppet::Application.stop_requested?.should be_false end it 'should return true for interrupted?' do Puppet::Application.interrupted?.should be_true end it 'should return false for clear?' do Puppet::Application.clear?.should be_false end end describe 'when performing a controlled_run' do it 'should not execute block if not :clear?' do Puppet::Application.run_status = :stop_requested target = mock 'target' target.expects(:some_method).never Puppet::Application.controlled_run do target.some_method end end it 'should execute block if :clear?' do Puppet::Application.run_status = nil target = mock 'target' target.expects(:some_method).once Puppet::Application.controlled_run do target.some_method end end it 'should signal process with HUP after block if restart requested during block execution' do Puppet::Application.run_status = nil target = mock 'target' target.expects(:some_method).once old_handler = trap('HUP') { target.some_method } begin Puppet::Application.controlled_run do Puppet::Application.run_status = :restart_requested end ensure trap('HUP', old_handler) end end after :each do Puppet::Application.run_status = nil end end describe "when parsing command-line options" do before :each do @argv_bak = ARGV.dup ARGV.clear Puppet.settings.stubs(:optparse_addargs).returns([]) - @app = Puppet::Application.new(:test) end after :each do ARGV.clear ARGV << @argv_bak end it "should get options from Puppet.settings.optparse_addargs" do Puppet.settings.expects(:optparse_addargs).returns([]) @app.parse_options end it "should add Puppet.settings options to OptionParser" do Puppet.settings.stubs(:optparse_addargs).returns( [["--option","-o", "Funny Option"]]) @app.opt_parser.expects(:on).with { |*arg| arg == ["--option","-o", "Funny Option"] } @app.parse_options end it "should ask OptionParser to parse the command-line argument" do @app.opt_parser.expects(:parse!) @app.parse_options end describe "when using --help" do confine "rdoc" => Puppet.features.usage? it "should call RDoc::usage and exit" do @app.expects(:exit) RDoc.expects(:usage).returns(true) @app.handle_help(nil) end end describe "when using --version" do it "should declare a version option" do @app.should respond_to(:handle_version) end it "should exit after printing the version" do @app.stubs(:puts) lambda { @app.handle_version(nil) }.should raise_error(SystemExit) end end describe "when dealing with an argument not declared directly by the application" do it "should pass it to handle_unknown if this method exists" do Puppet.settings.stubs(:optparse_addargs).returns([["--not-handled"]]) @app.opt_parser.stubs(:on).yields("value") @app.expects(:handle_unknown).with("--not-handled", "value").returns(true) @app.parse_options end it "should pass it to Puppet.settings if handle_unknown says so" do Puppet.settings.stubs(:optparse_addargs).returns([["--topuppet"]]) @app.opt_parser.stubs(:on).yields("value") @app.stubs(:handle_unknown).with("--topuppet", "value").returns(false) Puppet.settings.expects(:handlearg).with("--topuppet", "value") @app.parse_options end it "should pass it to Puppet.settings if there is no handle_unknown method" do Puppet.settings.stubs(:optparse_addargs).returns([["--topuppet"]]) @app.opt_parser.stubs(:on).yields("value") @app.stubs(:respond_to?).returns(false) Puppet.settings.expects(:handlearg).with("--topuppet", "value") @app.parse_options end it "should transform boolean false value to string for Puppet.settings" do Puppet.settings.expects(:handlearg).with("--option", "false") @app.handlearg("--option", false) end it "should transform boolean true value to string for Puppet.settings" do Puppet.settings.expects(:handlearg).with("--option", "true") @app.handlearg("--option", true) end it "should transform boolean option to normal form for Puppet.settings" do Puppet.settings.expects(:handlearg).with("--option", "true") @app.handlearg("--[no-]option", true) end it "should transform boolean option to no- form for Puppet.settings" do Puppet.settings.expects(:handlearg).with("--no-option", "false") @app.handlearg("--[no-]option", false) end end it "should exit if OptionParser raises an error" do $stderr.stubs(:puts) @app.opt_parser.stubs(:parse!).raises(OptionParser::ParseError.new("blah blah")) @app.expects(:exit) lambda { @app.parse_options }.should_not raise_error end end describe "when calling default setup" do before :each do - @app = Puppet::Application.new(:test) @app.stubs(:should_parse_config?).returns(false) @app.options.stubs(:[]) end [ :debug, :verbose ].each do |level| it "should honor option #{level}" do @app.options.stubs(:[]).with(level).returns(true) Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.expects(:level=).with(level == :verbose ? :info : :debug) - @app.run_setup + @app.setup end end it "should honor setdest option" do @app.options.stubs(:[]).with(:setdest).returns(false) Puppet::Util::Log.expects(:newdestination).with(:syslog) - @app.run_setup + @app.setup end end describe "when running" do before :each do - @app = Puppet::Application.new(:test) - @app.stubs(:run_preinit) - @app.stubs(:run_setup) + @app.stubs(:preinit) + @app.stubs(:setup) @app.stubs(:parse_options) end - it "should call run_preinit" do + it "should call preinit" do @app.stubs(:run_command) - @app.expects(:run_preinit) + @app.expects(:preinit) @app.run end it "should call parse_options" do @app.stubs(:run_command) @app.expects(:parse_options) @app.run end it "should call run_command" do @app.expects(:run_command) @app.run end it "should parse Puppet configuration if should_parse_config is called" do @app.stubs(:run_command) - @app.should_parse_config + @app.class.should_parse_config Puppet.settings.expects(:parse) @app.run end it "should not parse_option if should_not_parse_config is called" do @app.stubs(:run_command) - @app.should_not_parse_config + @app.class.should_not_parse_config Puppet.settings.expects(:parse).never @app.run end it "should parse Puppet configuration if needed" do @app.stubs(:run_command) @app.stubs(:should_parse_config?).returns(true) Puppet.settings.expects(:parse) @app.run end - it "should call the action matching what returned command" do - @app.stubs(:get_command).returns(:backup) - @app.stubs(:respond_to?).with(:backup).returns(true) - - @app.expects(:backup) + it "should call run_command" do + @app.expects(:run_command) @app.run end it "should call main as the default command" do @app.expects(:main) @app.run end it "should warn and exit if no command can be called" do $stderr.expects(:puts) @app.expects(:exit).with(1) @app.run end it "should raise an error if dispatch returns no command" do @app.stubs(:get_command).returns(nil) $stderr.expects(:puts) @app.expects(:exit).with(1) @app.run end it "should raise an error if dispatch returns an invalid command" do @app.stubs(:get_command).returns(:this_function_doesnt_exist) $stderr.expects(:puts) @app.expects(:exit).with(1) @app.run end end describe "when metaprogramming" do - before :each do - @app = Puppet::Application.new(:test) - end - - it "should create a new method with command" do - @app.command(:test) do - end - - @app.should respond_to(:test) - end - - describe "when calling attr_accessor" do - it "should create a reader method" do - @app.attr_accessor(:attribute) - - @app.should respond_to(:attribute) - end - - it "should create a reader that delegates to instance_variable_get" do - @app.attr_accessor(:attribute) - - @app.expects(:instance_variable_get).with(:@attribute) - @app.attribute - end - - it "should create a writer method" do - @app.attr_accessor(:attribute) - - @app.should respond_to(:attribute=) - end - - it "should create a writer that delegates to instance_variable_set" do - @app.attr_accessor(:attribute) - - @app.expects(:instance_variable_set).with(:@attribute, 1234) - @app.attribute=1234 - end - end - describe "when calling option" do it "should create a new method named after the option" do - @app.option("--test1","-t") do + @app.class.option("--test1","-t") do end @app.should respond_to(:handle_test1) end it "should transpose in option name any '-' into '_'" do - @app.option("--test-dashes-again","-t") do + @app.class.option("--test-dashes-again","-t") do end @app.should respond_to(:handle_test_dashes_again) end it "should create a new method called handle_test2 with option(\"--[no-]test2\")" do - @app.option("--[no-]test2","-t") do + @app.class.option("--[no-]test2","-t") do end @app.should respond_to(:handle_test2) end describe "when a block is passed" do it "should create a new method with it" do - @app.option("--[no-]test2","-t") do + @app.class.option("--[no-]test2","-t") do raise "I can't believe it, it works!" end lambda { @app.handle_test2 }.should raise_error end it "should declare the option to OptionParser" do - @app.opt_parser.expects(:on).with { |*arg| arg[0] == "--[no-]test3" } + OptionParser.any_instance.stubs(:on) + OptionParser.any_instance.expects(:on).with { |*arg| arg[0] == "--[no-]test3" } - @app.option("--[no-]test3","-t") do + @app.class.option("--[no-]test3","-t") do end + + @app.class.new_option_parser( @app ) end it "should pass a block that calls our defined method" do - @app.opt_parser.stubs(:on).yields(nil) + OptionParser.any_instance.stubs(:on) + OptionParser.any_instance.stubs(:on).with('--test4','-t').yields(nil) @app.expects(:send).with(:handle_test4, nil) - @app.option("--test4","-t") do + @app.class.option("--test4","-t") do end + + @app.class.new_option_parser( @app ) end end describe "when no block is given" do it "should declare the option to OptionParser" do - @app.opt_parser.expects(:on).with("--test4","-t") + OptionParser.any_instance.stubs(:on) + OptionParser.any_instance.expects(:on).with("--test4","-t") - @app.option("--test4","-t") + @app.class.option("--test4","-t") + + @app.class.new_option_parser( @app ) end it "should give to OptionParser a block that adds the the value to the options array" do - @app.opt_parser.stubs(:on).with("--test4","-t").yields(nil) + OptionParser.any_instance.stubs(:on) + OptionParser.any_instance.stubs(:on).with("--test4","-t").yields(nil) @app.options.expects(:[]=).with(:test4,nil) - @app.option("--test4","-t") - end - end - end - - it "should create a method called run_setup with setup" do - @app.setup do - end - - @app.should respond_to(:run_setup) - end + @app.class.option("--test4","-t") - it "should create a method called run_preinit with preinit" do - @app.preinit do - end - - @app.should respond_to(:run_preinit) - end - - it "should create a method called handle_unknown with unknown" do - @app.unknown do + @app.class.new_option_parser( @app ) + end end - - @app.should respond_to(:handle_unknown) end - - it "should create a method called get_command with dispatch" do - @app.dispatch do - end - - @app.should respond_to(:get_command) - end end end diff --git a/spec/unit/application/agent.rb b/spec/unit/application/agent.rb index 9c8aa11c1..fbcc61be3 100755 --- a/spec/unit/application/agent.rb +++ b/spec/unit/application/agent.rb @@ -1,600 +1,603 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/agent' require 'puppet/network/server' -describe Puppet::Application[:agent] do +describe Puppet::Application::Agent do before :each do @puppetd = Puppet::Application[:agent] @puppetd.stubs(:puts) @daemon = stub_everything 'daemon' Puppet::Daemon.stubs(:new).returns(@daemon) @agent = stub_everything 'agent' Puppet::Agent.stubs(:new).returns(@agent) - @puppetd.run_preinit + @puppetd.preinit Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) Puppet::Node.stubs(:terminus_class=) Puppet::Node.stubs(:cache_class=) Puppet::Node::Facts.stubs(:terminus_class=) end it "should ask Puppet::Application to parse Puppet configuration file" do @puppetd.should_parse_config?.should be_true end it "should declare a main command" do @puppetd.should respond_to(:main) end it "should declare a onetime command" do @puppetd.should respond_to(:onetime) end it "should declare a fingerprint command" do @puppetd.should respond_to(:fingerprint) end it "should declare a preinit block" do - @puppetd.should respond_to(:run_preinit) + @puppetd.should respond_to(:preinit) end describe "in preinit" do before :each do @puppetd.stubs(:trap) end it "should catch INT" do @puppetd.expects(:trap).with { |arg,block| arg == :INT } - @puppetd.run_preinit + @puppetd.preinit end it "should set waitforcert to 120" do - @puppetd.run_preinit + @puppetd.preinit @puppetd.options[:waitforcert].should == 120 end it "should init client to true" do - @puppetd.run_preinit + @puppetd.preinit @puppetd.options[:client].should be_true end it "should init fqdn to nil" do - @puppetd.run_preinit + @puppetd.preinit @puppetd.options[:fqdn].should be_nil end it "should init serve to []" do - @puppetd.run_preinit + @puppetd.preinit @puppetd.options[:serve].should == [] end it "should use MD5 as default digest algorithm" do - @puppetd.run_preinit + @puppetd.preinit @puppetd.options[:digest].should == :MD5 end it "should not fingerprint by default" do - @puppetd.run_preinit + @puppetd.preinit @puppetd.options[:fingerprint].should be_false end end describe "when handling options" do before do @old_argv = ARGV.dup ARGV.clear end after do ARGV.clear @old_argv.each { |a| ARGV << a } end [:centrallogging, :disable, :enable, :debug, :fqdn, :test, :verbose, :digest].each do |option| it "should declare handle_#{option} method" do @puppetd.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @puppetd.options.expects(:[]=).with(option, 'arg') @puppetd.send("handle_#{option}".to_sym, 'arg') end end it "should set an existing handler on server" do Puppet::Network::Handler.stubs(:handler).with("handler").returns(true) @puppetd.handle_serve("handler") @puppetd.options[:serve].should == [ :handler ] end it "should set client to false with --no-client" do @puppetd.handle_no_client(nil) @puppetd.options[:client].should be_false end it "should set onetime to ture with --onetime" do @puppetd.handle_onetime(nil) @puppetd.options[:onetime].should be_true end it "should set waitforcert to 0 with --onetime and if --waitforcert wasn't given" do @puppetd.explicit_waitforcert = false @puppetd.handle_onetime(nil) @puppetd.options[:waitforcert].should == 0 end it "should not reset waitforcert with --onetime when --waitforcert is used" do @puppetd.explicit_waitforcert = true @puppetd.handle_onetime(nil) @puppetd.options[:waitforcert].should_not == 0 end it "should set the log destination with --logdest" do @puppetd.options.stubs(:[]=).with { |opt,val| opt == :setdest } Puppet::Log.expects(:newdestination).with("console") @puppetd.handle_logdest("console") end it "should put the setdest options to true" do @puppetd.options.expects(:[]=).with(:setdest,true) @puppetd.handle_logdest("console") end it "should parse the log destination from ARGV" do ARGV << "--logdest" << "/my/file" Puppet::Util::Log.expects(:newdestination).with("/my/file") @puppetd.parse_options end it "should store the waitforcert options with --waitforcert" do @puppetd.options.expects(:[]=).with(:waitforcert,42) @puppetd.handle_waitforcert("42") end it "should mark explicit_waitforcert to true with --waitforcert" do @puppetd.options.stubs(:[]=) @puppetd.handle_waitforcert("42") @puppetd.explicit_waitforcert.should be_true end it "should set args[:Port] with --port" do @puppetd.handle_port("42") @puppetd.args[:Port].should == "42" end end describe "during setup" do before :each do @puppetd.options.stubs(:[]) Puppet.stubs(:info) FileTest.stubs(:exists?).returns(true) Puppet.stubs(:[]) Puppet.stubs(:[]).with(:libdir).returns("/dev/null/lib") Puppet.settings.stubs(:print_config?) Puppet.settings.stubs(:print_config) Puppet::SSL::Host.stubs(:ca_location=) Puppet::Transaction::Report.stubs(:terminus_class=) Puppet::Resource::Catalog.stubs(:terminus_class=) Puppet::Resource::Catalog.stubs(:cache_class=) Puppet::Node::Facts.stubs(:terminus_class=) @host = stub_everything 'host' Puppet::SSL::Host.stubs(:new).returns(@host) Puppet.stubs(:settraps) end describe "with --test" do before :each do Puppet.settings.stubs(:handlearg) @puppetd.options.stubs(:[]=) end it "should call setup_test" do @puppetd.options.stubs(:[]).with(:test).returns(true) @puppetd.expects(:setup_test) - @puppetd.run_setup + @puppetd.setup end it "should set options[:verbose] to true" do @puppetd.options.expects(:[]=).with(:verbose,true) @puppetd.setup_test end it "should set options[:onetime] to true" do @puppetd.options.expects(:[]=).with(:onetime,true) @puppetd.setup_test end it "should set options[:detailed_exitcodes] to true" do @puppetd.options.expects(:[]=).with(:detailed_exitcodes,true) @puppetd.setup_test end it "should set waitforcert to 0" do @puppetd.options.expects(:[]=).with(:waitforcert,0) @puppetd.setup_test end end it "should call setup_logs" do @puppetd.expects(:setup_logs) - @puppetd.run_setup + @puppetd.setup end describe "when setting up logs" do before :each do Puppet::Util::Log.stubs(:newdestination) end it "should set log level to debug if --debug was passed" do @puppetd.options.stubs(:[]).with(:debug).returns(true) Puppet::Util::Log.expects(:level=).with(:debug) @puppetd.setup_logs end it "should set log level to info if --verbose was passed" do @puppetd.options.stubs(:[]).with(:verbose).returns(true) Puppet::Util::Log.expects(:level=).with(:info) @puppetd.setup_logs end [:verbose, :debug].each do |level| it "should set console as the log destination with level #{level}" do @puppetd.options.stubs(:[]).with(level).returns(true) Puppet::Util::Log.expects(:newdestination).with(:console) @puppetd.setup_logs end end it "should set syslog as the log destination if no --logdest" do @puppetd.options.stubs(:[]).with(:setdest).returns(false) Puppet::Util::Log.expects(:newdestination).with(:syslog) @puppetd.setup_logs end end it "should print puppet config if asked to in Puppet config" do @puppetd.stubs(:exit) Puppet.settings.stubs(:print_configs?).returns(true) Puppet.settings.expects(:print_configs) - @puppetd.run_setup + @puppetd.setup end it "should exit after printing puppet config if asked to in Puppet config" do Puppet.settings.stubs(:print_configs?).returns(true) - lambda { @puppetd.run_setup }.should raise_error(SystemExit) + lambda { @puppetd.setup }.should raise_error(SystemExit) end it "should set a central log destination with --centrallogs" do @puppetd.options.stubs(:[]).with(:centrallogs).returns(true) Puppet.stubs(:[]).with(:server).returns("puppet.reductivelabs.com") Puppet::Util::Log.stubs(:newdestination).with(:syslog) Puppet::Util::Log.expects(:newdestination).with("puppet.reductivelabs.com") - @puppetd.run_setup + @puppetd.setup end it "should use :main, :puppetd, and :ssl" do Puppet.settings.expects(:use).with(:main, :puppetd, :ssl) - @puppetd.run_setup + @puppetd.setup end it "should install a remote ca location" do Puppet::SSL::Host.expects(:ca_location=).with(:remote) - @puppetd.run_setup + @puppetd.setup end it "should install a none ca location in fingerprint mode" do @puppetd.options.stubs(:[]).with(:fingerprint).returns(true) Puppet::SSL::Host.expects(:ca_location=).with(:none) - @puppetd.run_setup + @puppetd.setup end it "should tell the report handler to use REST" do Puppet::Transaction::Report.expects(:terminus_class=).with(:rest) - @puppetd.run_setup + @puppetd.setup end it "should change the catalog_terminus setting to 'rest'" do Puppet.expects(:[]=).with(:catalog_terminus, :rest) - @puppetd.run_setup + @puppetd.setup end it "should tell the catalog handler to use cache" do Puppet::Resource::Catalog.expects(:cache_class=).with(:yaml) - @puppetd.run_setup + @puppetd.setup end it "should tell the facts to use facter" do Puppet::Node::Facts.expects(:terminus_class=).with(:facter) - @puppetd.run_setup + @puppetd.setup end it "should create an agent" do Puppet::Agent.stubs(:new).with(Puppet::Configurer) - @puppetd.run_setup + @puppetd.setup end [:enable, :disable].each do |action| it "should delegate to enable_disable_client if we #{action} the agent" do @puppetd.options.stubs(:[]).with(action).returns(true) @puppetd.expects(:enable_disable_client).with(@agent) - @puppetd.run_setup + @puppetd.setup end end describe "when enabling or disabling agent" do [:enable, :disable].each do |action| it "should call client.#{action}" do @puppetd.stubs(:exit) @puppetd.options.stubs(:[]).with(action).returns(true) @agent.expects(action) @puppetd.enable_disable_client(@agent) end end it "should finally exit" do lambda { @puppetd.enable_disable_client(@agent) }.should raise_error(SystemExit) end end it "should inform the daemon about our agent if :client is set to 'true'" do @puppetd.options.expects(:[]).with(:client).returns true @daemon.expects(:agent=).with(@agent) - @puppetd.run_setup + @puppetd.setup end it "should not inform the daemon about our agent if :client is set to 'false'" do @puppetd.options[:client] = false @daemon.expects(:agent=).never - @puppetd.run_setup + @puppetd.setup end it "should daemonize if needed" do Puppet.stubs(:[]).with(:daemonize).returns(true) @daemon.expects(:daemonize) - @puppetd.run_setup + @puppetd.setup end it "should wait for a certificate" do @puppetd.options.stubs(:[]).with(:waitforcert).returns(123) @host.expects(:wait_for_cert).with(123) - @puppetd.run_setup + @puppetd.setup end it "should not wait for a certificate in fingerprint mode" do @puppetd.options.stubs(:[]).with(:fingerprint).returns(true) @puppetd.options.stubs(:[]).with(:waitforcert).returns(123) @host.expects(:wait_for_cert).never - @puppetd.run_setup + @puppetd.setup end it "should setup listen if told to and not onetime" do Puppet.stubs(:[]).with(:listen).returns(true) @puppetd.options.stubs(:[]).with(:onetime).returns(false) @puppetd.expects(:setup_listen) - @puppetd.run_setup + @puppetd.setup end describe "when setting up listen" do before :each do Puppet.stubs(:[]).with(:authconfig).returns('auth') FileTest.stubs(:exists?).with('auth').returns(true) File.stubs(:exist?).returns(true) @puppetd.options.stubs(:[]).with(:serve).returns([]) @puppetd.stubs(:exit) @server = stub_everything 'server' Puppet::Network::Server.stubs(:new).returns(@server) end it "should exit if no authorization file" do Puppet.stubs(:err) FileTest.stubs(:exists?).with('auth').returns(false) @puppetd.expects(:exit) @puppetd.setup_listen end it "should create a server to listen on at least the Runner handler" do Puppet::Network::Server.expects(:new).with { |args| args[:xmlrpc_handlers] == [:Runner] } @puppetd.setup_listen end it "should create a server to listen for specific handlers" do @puppetd.options.stubs(:[]).with(:serve).returns([:handler]) Puppet::Network::Server.expects(:new).with { |args| args[:xmlrpc_handlers] == [:handler] } @puppetd.setup_listen end it "should use puppet default port" do Puppet.stubs(:[]).with(:puppetport).returns(:port) Puppet::Network::Server.expects(:new).with { |args| args[:port] == :port } @puppetd.setup_listen end end end describe "when running" do before :each do @puppetd.agent = @agent @puppetd.daemon = @daemon @puppetd.options.stubs(:[]).with(:fingerprint).returns(false) end it "should dispatch to fingerprint if --fingerprint is used" do @puppetd.options.stubs(:[]).with(:fingerprint).returns(true) - @puppetd.get_command.should == :fingerprint + @puppetd.stubs(:fingerprint) + @puppetd.run_command end it "should dispatch to onetime if --onetime is used" do @puppetd.options.stubs(:[]).with(:onetime).returns(true) - @puppetd.get_command.should == :onetime + @puppetd.stubs(:onetime) + @puppetd.run_command end it "should dispatch to main if --onetime and --fingerprint are not used" do @puppetd.options.stubs(:[]).with(:onetime).returns(false) - @puppetd.get_command.should == :main + @puppetd.stubs(:main) + @puppetd.run_command end describe "with --onetime" do before :each do @agent.stubs(:run).returns(:report) @puppetd.options.stubs(:[]).with(:client).returns(:client) @puppetd.options.stubs(:[]).with(:detailed_exitcodes).returns(false) @puppetd.stubs(:exit).with(0) Puppet.stubs(:newservice) end it "should exit if no defined --client" do $stderr.stubs(:puts) @puppetd.options.stubs(:[]).with(:client).returns(nil) @puppetd.expects(:exit).with(43) @puppetd.onetime end it "should setup traps" do @daemon.expects(:set_signal_traps) @puppetd.onetime end it "should let the agent run" do @agent.expects(:run).returns(:report) @puppetd.onetime end it "should finish by exiting with 0 error code" do @puppetd.expects(:exit).with(0) @puppetd.onetime end describe "and --detailed-exitcodes" do before :each do @puppetd.options.stubs(:[]).with(:detailed_exitcodes).returns(true) end it "should exit with report's computed exit status" do Puppet.stubs(:[]).with(:noop).returns(false) report = stub 'report', :exit_status => 666 @agent.stubs(:run).returns(report) @puppetd.expects(:exit).with(666) @puppetd.onetime end it "should always exit with 0 if --noop" do Puppet.stubs(:[]).with(:noop).returns(true) report = stub 'report', :exit_status => 666 @agent.stubs(:run).returns(report) @puppetd.expects(:exit).with(0) @puppetd.onetime end end end describe "with --fingerprint" do before :each do @cert = stub_everything 'cert' @puppetd.options.stubs(:[]).with(:fingerprint).returns(true) @puppetd.options.stubs(:[]).with(:digest).returns(:MD5) @host = stub_everything 'host' @puppetd.stubs(:host).returns(@host) end it "should fingerprint the certificate if it exists" do @host.expects(:certificate).returns(@cert) @cert.expects(:fingerprint).with(:MD5).returns "fingerprint" @puppetd.fingerprint end it "should fingerprint the certificate request if no certificate have been signed" do @host.expects(:certificate).returns(nil) @host.expects(:certificate_request).returns(@cert) @cert.expects(:fingerprint).with(:MD5).returns "fingerprint" @puppetd.fingerprint end it "should display the fingerprint" do @host.stubs(:certificate).returns(@cert) @cert.stubs(:fingerprint).with(:MD5).returns("DIGEST") Puppet.expects(:notice).with("DIGEST") @puppetd.fingerprint end end describe "without --onetime and --fingerprint" do before :each do Puppet.stubs(:notice) @puppetd.options.stubs(:[]).with(:client) end it "should start our daemon" do @daemon.expects(:start) @puppetd.main end end end end diff --git a/spec/unit/application/apply.rb b/spec/unit/application/apply.rb index 6fdeebfcb..10202e196 100755 --- a/spec/unit/application/apply.rb +++ b/spec/unit/application/apply.rb @@ -1,384 +1,387 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/apply' -describe "Puppet" do +describe Puppet::Application::Apply do before :each do @apply = Puppet::Application[:apply] Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) end [:debug,:loadclasses,:verbose,:use_nodes,:detailed_exitcodes].each do |option| it "should declare handle_#{option} method" do @apply.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @apply.options.expects(:[]=).with(option, 'arg') @apply.send("handle_#{option}".to_sym, 'arg') end end it "should set the code to the provided code when :execute is used" do @apply.options.expects(:[]=).with(:code, 'arg') @apply.send("handle_execute".to_sym, 'arg') end it "should ask Puppet::Application to parse Puppet configuration file" do @apply.should_parse_config?.should be_true end describe "when applying options" do it "should set the log destination with --logdest" do Puppet::Log.expects(:newdestination).with("console") @apply.handle_logdest("console") end it "should put the logset options to true" do @apply.options.expects(:[]=).with(:logset,true) @apply.handle_logdest("console") end end describe "during setup" do before :each do Puppet::Log.stubs(:newdestination) Puppet.stubs(:trap) Puppet::Log.stubs(:level=) Puppet.stubs(:parse_config) require 'lib/puppet/file_bucket/dipper' Puppet::FileBucket::Dipper.stubs(:new) STDIN.stubs(:read) @apply.options.stubs(:[]).with(any_parameters) end it "should set show_diff on --noop" do Puppet.stubs(:[]=) Puppet.stubs(:[]).with(:config) Puppet.stubs(:[]).with(:noop).returns(true) Puppet.expects(:[]=).with(:show_diff, true) - @apply.run_setup + @apply.setup end it "should set console as the log destination if logdest option wasn't provided" do Puppet::Log.expects(:newdestination).with(:console) - @apply.run_setup + @apply.setup end it "should set INT trap" do @apply.expects(:trap).with(:INT) - @apply.run_setup + @apply.setup end it "should set log level to debug if --debug was passed" do @apply.options.stubs(:[]).with(:debug).returns(true) Puppet::Log.expects(:level=).with(:debug) - @apply.run_setup + @apply.setup end it "should set log level to info if --verbose was passed" do @apply.options.stubs(:[]).with(:verbose).returns(true) Puppet::Log.expects(:level=).with(:info) - @apply.run_setup + @apply.setup end it "should print puppet config if asked to in Puppet config" do @apply.stubs(:exit) Puppet.settings.stubs(:print_configs?).returns(true) Puppet.settings.expects(:print_configs) - @apply.run_setup + @apply.setup end it "should exit after printing puppet config if asked to in Puppet config" do Puppet.settings.stubs(:print_configs?).returns(true) - lambda { @apply.run_setup }.should raise_error(SystemExit) + lambda { @apply.setup }.should raise_error(SystemExit) end end describe "when executing" do it "should dispatch to parseonly if parseonly is set" do @apply.stubs(:options).returns({}) Puppet.stubs(:[]).with(:parseonly).returns(true) - @apply.get_command.should == :parseonly + @apply.expects(:parseonly) + @apply.run_command end it "should dispatch to 'apply' if it was called with 'apply'" do @apply.options[:catalog] = "foo" - @apply.get_command.should == :apply + @apply.expects(:apply) + @apply.run_command end it "should dispatch to main if parseonly is not set" do @apply.stubs(:options).returns({}) Puppet.stubs(:[]).with(:parseonly).returns(false) - @apply.get_command.should == :main + @apply.expects(:main) + @apply.run_command end describe "the parseonly command" do before :each do Puppet.stubs(:[]).with(:environment) Puppet.stubs(:[]).with(:manifest).returns("site.pp") Puppet.stubs(:err) @apply.stubs(:exit) @apply.options.stubs(:[]).with(:code).returns "some code" @collection = stub_everything Puppet::Resource::TypeCollection.stubs(:new).returns(@collection) end it "should use a Puppet Resource Type Collection to parse the file" do @collection.expects(:perform_initial_import) @apply.parseonly end it "should exit with exit code 0 if no error" do @apply.expects(:exit).with(0) @apply.parseonly end it "should exit with exit code 1 if error" do @collection.stubs(:perform_initial_import).raises(Puppet::ParseError) @apply.expects(:exit).with(1) @apply.parseonly end end describe "the main command" do before :each do Puppet.stubs(:[]) Puppet.settings.stubs(:use) Puppet.stubs(:[]).with(:prerun_command).returns "" Puppet.stubs(:[]).with(:postrun_command).returns "" Puppet.stubs(:[]).with(:trace).returns(true) @apply.options.stubs(:[]) @facts = stub_everything 'facts' Puppet::Node::Facts.stubs(:find).returns(@facts) @node = stub_everything 'node' Puppet::Node.stubs(:find).returns(@node) @catalog = stub_everything 'catalog' @catalog.stubs(:to_ral).returns(@catalog) Puppet::Resource::Catalog.stubs(:find).returns(@catalog) STDIN.stubs(:read) @transaction = stub_everything 'transaction' @catalog.stubs(:apply).returns(@transaction) @apply.stubs(:exit) end it "should set the code to run from --code" do @apply.options.stubs(:[]).with(:code).returns("code to run") Puppet.expects(:[]=).with(:code,"code to run") @apply.main end it "should set the code to run from STDIN if no arguments" do Puppet::Util::CommandLine.stubs(:args).returns([]) STDIN.stubs(:read).returns("code to run") Puppet.expects(:[]=).with(:code,"code to run") @apply.main end it "should set the manifest if some files are passed on command line" do Puppet::Util::CommandLine.stubs(:args).returns(['site.pp']) Puppet.expects(:[]=).with(:manifest,"site.pp") @apply.main end it "should collect the node facts" do Puppet::Node::Facts.expects(:find).returns(@facts) @apply.main end it "should raise an error if we can't find the node" do Puppet::Node::Facts.expects(:find).returns(nil) lambda { @apply.main }.should raise_error end it "should find the node" do Puppet::Node.expects(:find).returns(@node) @apply.main end it "should raise an error if we can't find the node" do Puppet::Node.expects(:find).returns(nil) lambda { @apply.main }.should raise_error end it "should merge in our node the loaded facts" do @facts.stubs(:values).returns("values") @node.expects(:merge).with("values") @apply.main end it "should load custom classes if loadclasses" do @apply.options.stubs(:[]).with(:loadclasses).returns(true) Puppet.stubs(:[]).with(:classfile).returns("/etc/puppet/classes.txt") FileTest.stubs(:exists?).with("/etc/puppet/classes.txt").returns(true) FileTest.stubs(:readable?).with("/etc/puppet/classes.txt").returns(true) File.stubs(:read).with("/etc/puppet/classes.txt").returns("class") @node.expects(:classes=) @apply.main end it "should compile the catalog" do Puppet::Resource::Catalog.expects(:find).returns(@catalog) @apply.main end it "should transform the catalog to ral" do @catalog.expects(:to_ral).returns(@catalog) @apply.main end it "should finalize the catalog" do @catalog.expects(:finalize) @apply.main end it "should call the prerun and postrun commands on a Configurer instance" do configurer = stub 'configurer' Puppet::Configurer.expects(:new).returns configurer configurer.expects(:execute_prerun_command) configurer.expects(:execute_postrun_command) @apply.main end it "should apply the catalog" do @catalog.expects(:apply) @apply.main end describe "with detailed_exitcodes" do it "should exit with report's computed exit status" do Puppet.stubs(:[]).with(:noop).returns(false) @apply.options.stubs(:[]).with(:detailed_exitcodes).returns(true) report = stub 'report', :exit_status => 666 @transaction.stubs(:report).returns(report) @apply.expects(:exit).with(666) @apply.main end it "should always exit with 0 if option is disabled" do Puppet.stubs(:[]).with(:noop).returns(false) @apply.options.stubs(:[]).with(:detailed_exitcodes).returns(false) report = stub 'report', :exit_status => 666 @transaction.stubs(:report).returns(report) @apply.expects(:exit).with(0) @apply.main end it "should always exit with 0 if --noop" do Puppet.stubs(:[]).with(:noop).returns(true) @apply.options.stubs(:[]).with(:detailed_exitcodes).returns(true) report = stub 'report', :exit_status => 666 @transaction.stubs(:report).returns(report) @apply.expects(:exit).with(0) @apply.main end end end describe "the 'apply' command" do it "should read the catalog in from disk if a file name is provided" do @apply.options[:catalog] = "/my/catalog.pson" File.expects(:read).with("/my/catalog.pson").returns "something" Puppet::Resource::Catalog.stubs(:convert_from).with(:pson,'something').returns Puppet::Resource::Catalog.new @apply.apply end it "should read the catalog in from stdin if '-' is provided" do @apply.options[:catalog] = "-" $stdin.expects(:read).returns "something" Puppet::Resource::Catalog.stubs(:convert_from).with(:pson,'something').returns Puppet::Resource::Catalog.new @apply.apply end it "should deserialize the catalog from the default format" do @apply.options[:catalog] = "/my/catalog.pson" File.stubs(:read).with("/my/catalog.pson").returns "something" Puppet::Resource::Catalog.stubs(:default_format).returns :rot13_piglatin Puppet::Resource::Catalog.stubs(:convert_from).with(:rot13_piglatin,'something').returns Puppet::Resource::Catalog.new @apply.apply end it "should fail helpfully if deserializing fails" do @apply.options[:catalog] = "/my/catalog.pson" File.stubs(:read).with("/my/catalog.pson").returns "something syntacically invalid" lambda { @apply.apply }.should raise_error(Puppet::Error) end it "should convert plain data structures into a catalog if deserialization does not do so" do @apply.options[:catalog] = "/my/catalog.pson" File.stubs(:read).with("/my/catalog.pson").returns "something" Puppet::Resource::Catalog.stubs(:convert_from).with(:pson,"something").returns({:foo => "bar"}) Puppet::Resource::Catalog.expects(:pson_create).with({:foo => "bar"}).returns(Puppet::Resource::Catalog.new) @apply.apply end it "should convert the catalog to a RAL catalog and use a Configurer instance to apply it" do @apply.options[:catalog] = "/my/catalog.pson" File.stubs(:read).with("/my/catalog.pson").returns "something" catalog = Puppet::Resource::Catalog.new Puppet::Resource::Catalog.stubs(:convert_from).with(:pson,'something').returns catalog catalog.expects(:to_ral).returns "mycatalog" configurer = stub 'configurer' Puppet::Configurer.expects(:new).returns configurer configurer.expects(:run).with(:catalog => "mycatalog") @apply.apply end end end end diff --git a/spec/unit/application/cert.rb b/spec/unit/application/cert.rb index 8757cf36c..3fb2f1ed4 100644 --- a/spec/unit/application/cert.rb +++ b/spec/unit/application/cert.rb @@ -1,167 +1,167 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/cert' -describe "PuppetCA" do +describe Puppet::Application::Cert do before :each do @cert_app = Puppet::Application[:cert] Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) end it "should ask Puppet::Application to parse Puppet configuration file" do @cert_app.should_parse_config?.should be_true end it "should declare a main command" do @cert_app.should respond_to(:main) end Puppet::SSL::CertificateAuthority::Interface::INTERFACE_METHODS.reject{ |m| m == :destroy }.each do |method| it "should declare option --#{method}" do @cert_app.should respond_to("handle_#{method}".to_sym) end end it "should set log level to info with the --verbose option" do Puppet::Log.expects(:level=).with(:info) @cert_app.handle_verbose(0) end it "should set log level to debug with the --debug option" do Puppet::Log.expects(:level=).with(:debug) @cert_app.handle_debug(0) end it "should set the fingerprint digest with the --digest option" do @cert_app.handle_digest(:digest) @cert_app.digest.should == :digest end it "should set mode to :destroy for --clean" do @cert_app.handle_clean(0) @cert_app.mode.should == :destroy end it "should set all to true for --all" do @cert_app.handle_all(0) @cert_app.all.should be_true end Puppet::SSL::CertificateAuthority::Interface::INTERFACE_METHODS.reject { |m| m == :destroy }.each do |method| it "should set mode to #{method} with option --#{method}" do @cert_app.send("handle_#{method}".to_sym, nil) @cert_app.mode.should == method end end describe "during setup" do before :each do Puppet::Log.stubs(:newdestination) Puppet::SSL::Host.stubs(:ca_location=) Puppet::SSL::CertificateAuthority.stubs(:new) end it "should set console as the log destination" do Puppet::Log.expects(:newdestination).with(:console) - @cert_app.run_setup + @cert_app.setup end it "should print puppet config if asked to in Puppet config" do @cert_app.stubs(:exit) Puppet.settings.stubs(:print_configs?).returns(true) Puppet.settings.expects(:print_configs) - @cert_app.run_setup + @cert_app.setup end it "should exit after printing puppet config if asked to in Puppet config" do Puppet.settings.stubs(:print_configs?).returns(true) - lambda { @cert_app.run_setup }.should raise_error(SystemExit) + lambda { @cert_app.setup }.should raise_error(SystemExit) end it "should set the CA location to 'only'" do Puppet::SSL::Host.expects(:ca_location=).with(:only) - @cert_app.run_setup + @cert_app.setup end it "should create a new certificate authority" do Puppet::SSL::CertificateAuthority.expects(:new) - @cert_app.run_setup + @cert_app.setup end end describe "when running" do before :each do @cert_app.all = false @ca = stub_everything 'ca' @cert_app.ca = @ca Puppet::Util::CommandLine.stubs(:args).returns([]) end it "should delegate to the CertificateAuthority" do @ca.expects(:apply) @cert_app.main end it "should delegate with :all if option --all was given" do @cert_app.handle_all(0) @ca.expects(:apply).with { |mode,to| to[:to] == :all } @cert_app.main end it "should delegate to ca.apply with the hosts given on command line" do Puppet::Util::CommandLine.stubs(:args).returns(["host"]) @ca.expects(:apply).with { |mode,to| to[:to] == ["host"]} @cert_app.main end it "should send the currently set digest" do Puppet::Util::CommandLine.stubs(:args).returns(["host"]) @cert_app.handle_digest(:digest) @ca.expects(:apply).with { |mode,to| to[:digest] == :digest} @cert_app.main end it "should delegate to ca.apply with current set mode" do @cert_app.mode = "currentmode" Puppet::Util::CommandLine.stubs(:args).returns(["host"]) @ca.expects(:apply).with { |mode,to| mode == "currentmode" } @cert_app.main end it "should revoke cert if mode is clean" do @cert_app.mode = :destroy Puppet::Util::CommandLine.stubs(:args).returns(["host"]) @ca.expects(:apply).with { |mode,to| mode == :revoke } @ca.expects(:apply).with { |mode,to| mode == :destroy } @cert_app.main end end end diff --git a/spec/unit/application/describe.rb b/spec/unit/application/describe.rb index fd0c5e002..002cdb763 100755 --- a/spec/unit/application/describe.rb +++ b/spec/unit/application/describe.rb @@ -1,84 +1,84 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/describe' -describe Puppet::Application[:describe] do +describe Puppet::Application::Describe do before :each do @describe = Puppet::Application[:describe] end it "should ask Puppet::Application to not parse Puppet configuration file" do @describe.should_parse_config?.should be_false end it "should declare a main command" do @describe.should respond_to(:main) end it "should declare a preinit block" do - @describe.should respond_to(:run_preinit) + @describe.should respond_to(:preinit) end [:providers,:list,:meta].each do |option| it "should declare handle_#{option} method" do @describe.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @describe.options.expects(:[]=).with("#{option}".to_sym, 'arg') @describe.send("handle_#{option}".to_sym, 'arg') end end describe "in preinit" do it "should set options[:parameteers] to true" do - @describe.run_preinit + @describe.preinit @describe.options[:parameters].should be_true end end describe "when handling parameters" do it "should set options[:parameters] to false" do @describe.handle_short(nil) @describe.options[:parameters].should be_false end end describe "during setup" do it "should collect arguments in options[:types]" do - Puppet::Util::CommandLine.stubs(:args).returns(['1','2']) - @describe.run_setup + @describe.command_line.stubs(:args).returns(['1','2']) + @describe.setup @describe.options[:types].should == ['1','2'] end end describe "when running" do before :each do @typedoc = stub 'type_doc' TypeDoc.stubs(:new).returns(@typedoc) end it "should call list_types if options list is set" do @describe.options[:list] = true @typedoc.expects(:list_types) @describe.run_command end it "should call format_type for each given types" do @describe.options[:list] = false @describe.options[:types] = ['type'] @typedoc.expects(:format_type).with('type', @describe.options) @describe.run_command end end end diff --git a/spec/unit/application/doc.rb b/spec/unit/application/doc.rb index 185612873..3bda25f2f 100755 --- a/spec/unit/application/doc.rb +++ b/spec/unit/application/doc.rb @@ -1,359 +1,359 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/doc' -describe "doc" do +describe Puppet::Application::Doc do before :each do @doc = Puppet::Application[:doc] @doc.stubs(:puts) - @doc.run_preinit + @doc.preinit Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) end it "should ask Puppet::Application to not parse Puppet configuration file" do @doc.should_parse_config?.should be_false end it "should declare a other command" do @doc.should respond_to(:other) end it "should declare a rdoc command" do @doc.should respond_to(:rdoc) end it "should declare a trac command" do @doc.should respond_to(:trac) end it "should declare a fallback for unknown options" do @doc.should respond_to(:handle_unknown) end it "should declare a preinit block" do - @doc.should respond_to(:run_preinit) + @doc.should respond_to(:preinit) end describe "in preinit" do it "should set references to []" do - @doc.run_preinit + @doc.preinit @doc.options[:references].should == [] end it "should init mode to text" do - @doc.run_preinit + @doc.preinit @doc.options[:mode].should == :text end it "should init format to to_rest" do - @doc.run_preinit + @doc.preinit @doc.options[:format].should == :to_rest end end describe "when handling options" do [:all, :outputdir, :verbose, :debug].each do |option| it "should declare handle_#{option} method" do @doc.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @doc.options.expects(:[]=).with(option, 'arg') @doc.send("handle_#{option}".to_sym, 'arg') end end it "should store the format if valid" do Puppet::Util::Reference.stubs(:method_defined?).with('to_format').returns(true) @doc.options.expects(:[]=).with(:format, 'to_format') @doc.handle_format('format') end it "should raise an error if the format is not valid" do Puppet::Util::Reference.stubs(:method_defined?).with('to_format').returns(false) lambda { @doc.handle_format('format') } end it "should store the mode if valid" do Puppet::Util::Reference.stubs(:modes).returns(stub('mode', :include? => true)) @doc.options.expects(:[]=).with(:mode, :mode) @doc.handle_mode('mode') end it "should store the mode if :rdoc" do Puppet::Util::Reference.modes.stubs(:include?).with('rdoc').returns(false) @doc.options.expects(:[]=).with(:mode, :rdoc) @doc.handle_mode('rdoc') end it "should raise an error if the mode is not valid" do Puppet::Util::Reference.modes.stubs(:include?).with('unknown').returns(false) lambda { @doc.handle_mode('unknown') } end it "should list all references on list and exit" do reference = stubs 'reference' ref = stubs 'ref' Puppet::Util::Reference.stubs(:references).returns([reference]) Puppet::Util::Reference.expects(:reference).with(reference).returns(ref) ref.expects(:doc) @doc.expects(:exit) @doc.handle_list(nil) end it "should add reference to references list with --reference" do @doc.options[:references] = [:ref1] @doc.handle_reference('ref2') @doc.options[:references].should == [:ref1,:ref2] end end describe "during setup" do before :each do Puppet::Log.stubs(:newdestination) Puppet::Util::CommandLine.stubs(:args).returns([]) end it "should default to rdoc mode if there are command line arguments" do Puppet::Util::CommandLine.stubs(:args).returns(["1"]) @doc.stubs(:setup_rdoc) @doc.options.expects(:[]=).with(:mode,:rdoc) - @doc.run_setup + @doc.setup end it "should call setup_rdoc in rdoc mode" do @doc.options.stubs(:[]).with(:mode).returns(:rdoc) @doc.expects(:setup_rdoc) - @doc.run_setup + @doc.setup end it "should call setup_reference if not rdoc" do @doc.options.stubs(:[]).with(:mode).returns(:test) @doc.expects(:setup_reference) - @doc.run_setup + @doc.setup end describe "in non-rdoc mode" do it "should get all non-dynamic reference if --all" do @doc.options.stubs(:[]).with(:all).returns(true) @doc.options.stubs(:[]).with(:references).returns([]) static = stub 'static', :dynamic? => false dynamic = stub 'dynamic', :dynamic? => true Reference.stubs(:reference).with(:static).returns(static) Reference.stubs(:reference).with(:dynamic).returns(dynamic) Reference.stubs(:references).returns([:static,:dynamic]) @doc.options.stubs(:[]=).with(:references, [:static]) @doc.setup_reference end it "should default to :type if no references" do @doc.options.stubs(:[]).with(:all).returns(false) array = stub 'array', :empty? => true @doc.options.stubs(:[]).with(:references).returns(array) array.expects(:<<).with(:type) @doc.setup_reference end end describe "in rdoc mode" do before :each do @doc.options.stubs(:[]).returns(false) Puppet.stubs(:[]=).with(:name, "puppetmasterd") Puppet.stubs(:parse_config) Puppet::Util::Log.stubs(:level=) Puppet::Util::Log.stubs(:newdestination) end describe "when there are unknown args" do it "should expand --modulepath if any" do @doc.unknown_args = [ { :opt => "--modulepath", :arg => "path" } ] Puppet.settings.stubs(:handlearg) File.expects(:expand_path).with("path") @doc.setup_rdoc end it "should expand --manifestdir if any" do @doc.unknown_args = [ { :opt => "--manifestdir", :arg => "path" } ] Puppet.settings.stubs(:handlearg) File.expects(:expand_path).with("path") @doc.setup_rdoc end it "should give them to Puppet.settings" do @doc.unknown_args = [ { :opt => :option, :arg => :argument } ] Puppet.settings.expects(:handlearg).with(:option,:argument) @doc.setup_rdoc end end it "should pretend to be puppetmasterd" do Puppet.expects(:[]=).with(:name, "puppetmasterd") @doc.setup_rdoc end it "should parse puppet configuration" do Puppet.expects(:parse_config) @doc.setup_rdoc end it "should set log level to debug if --debug" do @doc.options.stubs(:[]).with(:debug).returns(true) Puppet::Util::Log.expects(:level=).with(:debug) @doc.setup_rdoc end it "should set log level to info if --verbose" do @doc.options.stubs(:[]).with(:verbose).returns(true) Puppet::Util::Log.expects(:level=).with(:info) @doc.setup_rdoc end it "should set log destination to console if --verbose" do @doc.options.stubs(:[]).with(:verbose).returns(true) Puppet::Util::Log.expects(:newdestination).with(:console) @doc.setup_rdoc end it "should set log destination to console if --debug" do @doc.options.stubs(:[]).with(:debug).returns(true) Puppet::Util::Log.expects(:newdestination).with(:console) @doc.setup_rdoc end end end describe "when running" do before :each do end describe "in trac mode" do it "should call trac for each reference" do ref = stub 'ref' Puppet::Util::Reference.stubs(:reference).with(:ref).returns(ref) @doc.options.stubs(:[]).with(:references).returns([:ref]) @doc.options.stubs(:[]).with(:mode).returns(:trac) ref.expects(:trac) @doc.trac end end describe "in rdoc mode" do before :each do @doc.manifest = false Puppet.stubs(:info) Puppet.stubs(:[]).with(:trace).returns(false) @env = stub 'env' Puppet::Node::Environment.stubs(:new).returns(@env) @env.stubs(:modulepath).returns(['modules']) @env.stubs(:[]).with(:manifest).returns('manifests/site.pp') Puppet.stubs(:[]).with(:modulepath).returns('modules') Puppet.stubs(:[]).with(:manifestdir).returns('manifests') @doc.options.stubs(:[]).with(:all).returns(false) @doc.options.stubs(:[]).with(:outputdir).returns('doc') Puppet.settings.stubs(:[]=).with(:document_all, false) Puppet.settings.stubs(:setdefaults) Puppet::Util::RDoc.stubs(:rdoc) @doc.stubs(:exit) File.stubs(:expand_path).with('modules').returns('modules') File.stubs(:expand_path).with('manifests').returns('manifests') Puppet::Util::CommandLine.stubs(:args).returns([]) end it "should set document_all on --all" do @doc.options.expects(:[]).with(:all).returns(true) Puppet.settings.expects(:[]=).with(:document_all, true) @doc.rdoc end it "should call Puppet::Util::RDoc.rdoc in full mode" do Puppet::Util::RDoc.expects(:rdoc).with('doc', ['modules','manifests']) @doc.rdoc end it "should call Puppet::Util::RDoc.rdoc in full mode with outputdir set to doc if no --outputdir" do @doc.options.expects(:[]).with(:outputdir).returns(false) Puppet::Util::RDoc.expects(:rdoc).with('doc', ['modules','manifests']) @doc.rdoc end it "should call Puppet::Util::RDoc.manifestdoc in manifest mode" do @doc.manifest = true Puppet::Util::RDoc.expects(:manifestdoc) @doc.rdoc end it "should get modulepath and manifestdir values from the environment" do @env.expects(:modulepath).returns(['envmodules1','envmodules2']) @env.expects(:[]).with(:manifest).returns('envmanifests/site.pp') Puppet::Util::RDoc.expects(:rdoc).with('doc', ['envmodules1','envmodules2','envmanifests']) @doc.rdoc end end describe "in the other modes" do it "should get reference in given format" do reference = stub 'reference' @doc.options.stubs(:[]).with(:mode).returns(:none) @doc.options.stubs(:[]).with(:references).returns([:ref]) Puppet::Util::Reference.expects(:reference).with(:ref).returns(reference) @doc.options.stubs(:[]).with(:format).returns(:format) @doc.stubs(:exit) reference.expects(:send).with { |format,contents| format == :format }.returns('doc') @doc.other end end end end diff --git a/spec/unit/application/filebucket.rb b/spec/unit/application/filebucket.rb index 37cc93997..68af45c40 100644 --- a/spec/unit/application/filebucket.rb +++ b/spec/unit/application/filebucket.rb @@ -1,220 +1,223 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/filebucket' -describe Puppet::Application[:filebucket] do +describe Puppet::Application::Filebucket do before :each do @filebucket = Puppet::Application[:filebucket] end it "should ask Puppet::Application to not parse Puppet configuration file" do @filebucket.should_parse_config?.should be_false end it "should declare a get command" do @filebucket.should respond_to(:get) end it "should declare a backup command" do @filebucket.should respond_to(:backup) end it "should declare a restore command" do @filebucket.should respond_to(:restore) end [:bucket, :debug, :local, :remote, :verbose].each do |option| it "should declare handle_#{option} method" do @filebucket.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @filebucket.options.expects(:[]=).with("#{option}".to_sym, 'arg') @filebucket.send("handle_#{option}".to_sym, 'arg') end end describe "during setup" do before :each do Puppet::Log.stubs(:newdestination) Puppet.stubs(:settraps) Puppet::Log.stubs(:level=) Puppet.stubs(:parse_config) Puppet::FileBucket::Dipper.stubs(:new) @filebucket.options.stubs(:[]).with(any_parameters) end it "should set console as the log destination" do Puppet::Log.expects(:newdestination).with(:console) - @filebucket.run_setup + @filebucket.setup end it "should trap INT" do @filebucket.expects(:trap).with(:INT) - @filebucket.run_setup + @filebucket.setup end it "should set log level to debug if --debug was passed" do @filebucket.options.stubs(:[]).with(:debug).returns(true) Puppet::Log.expects(:level=).with(:debug) - @filebucket.run_setup + @filebucket.setup end it "should set log level to info if --verbose was passed" do @filebucket.options.stubs(:[]).with(:verbose).returns(true) Puppet::Log.expects(:level=).with(:info) - @filebucket.run_setup + @filebucket.setup end it "should Parse puppet config" do Puppet.expects(:parse_config) - @filebucket.run_setup + @filebucket.setup end it "should print puppet config if asked to in Puppet config" do @filebucket.stubs(:exit) Puppet.settings.stubs(:print_configs?).returns(true) Puppet.settings.expects(:print_configs) - @filebucket.run_setup + @filebucket.setup end it "should exit after printing puppet config if asked to in Puppet config" do Puppet.settings.stubs(:print_configs?).returns(true) - lambda { @filebucket.run_setup }.should raise_error(SystemExit) + lambda { @filebucket.setup }.should raise_error(SystemExit) end describe "with local bucket" do before :each do @filebucket.options.stubs(:[]).with(:local).returns(true) end it "should create a client with the default bucket if none passed" do Puppet.stubs(:[]).with(:bucketdir).returns("path") Puppet::FileBucket::Dipper.expects(:new).with { |h| h[:Path] == "path" } - @filebucket.run_setup + @filebucket.setup end it "should create a local Dipper with the given bucket" do @filebucket.options.stubs(:[]).with(:bucket).returns("path") Puppet::FileBucket::Dipper.expects(:new).with { |h| h[:Path] == "path" } - @filebucket.run_setup + @filebucket.setup end end describe "with remote bucket" do it "should create a remote Client to the configured server" do Puppet.stubs(:[]).with(:server).returns("puppet.reductivelabs.com") Puppet::FileBucket::Dipper.expects(:new).with { |h| h[:Server] == "puppet.reductivelabs.com" } - @filebucket.run_setup + @filebucket.setup end end end describe "when running" do before :each do Puppet::Log.stubs(:newdestination) Puppet.stubs(:settraps) Puppet::Log.stubs(:level=) Puppet.stubs(:parse_config) Puppet::FileBucket::Dipper.stubs(:new) @filebucket.options.stubs(:[]).with(any_parameters) @client = stub 'client' Puppet::FileBucket::Dipper.stubs(:new).returns(@client) - @filebucket.run_setup + @filebucket.setup end it "should use the first non-option parameter as the dispatch" do Puppet::Util::CommandLine.stubs(:args).returns([:get]) - @filebucket.get_command.should == :get + @filebucket.expects(:get) + + @filebucket.run_command end describe "the command get" do before :each do @filebucket.stubs(:print) + @filebucket.stubs(:args).returns([]) end it "should call the client getfile method" do @client.expects(:getfile) @filebucket.get end it "should call the client getfile method with the given md5" do md5="DEADBEEF" @filebucket.stubs(:args).returns([md5]) @client.expects(:getfile).with(md5) @filebucket.get end it "should print the file content" do @client.stubs(:getfile).returns("content") @filebucket.expects(:print).returns("content") @filebucket.get end end describe "the command backup" do it "should call the client backup method for each given parameter" do @filebucket.stubs(:puts) FileTest.stubs(:exists?).returns(true) FileTest.stubs(:readable?).returns(true) @filebucket.stubs(:args).returns(["file1", "file2"]) @client.expects(:backup).with("file1") @client.expects(:backup).with("file2") @filebucket.backup end end describe "the command restore" do it "should call the client getfile method with the given md5" do md5="DEADBEEF" file="testfile" @filebucket.stubs(:args).returns([file, md5]) @client.expects(:restore).with(file,md5) @filebucket.restore end end end end diff --git a/spec/unit/application/kick.rb b/spec/unit/application/kick.rb index b617537d4..c1b780651 100755 --- a/spec/unit/application/kick.rb +++ b/spec/unit/application/kick.rb @@ -1,293 +1,303 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/util/ldap/connection' require 'puppet/application/kick' -describe Puppet::Application[:kick] do +describe Puppet::Application::Kick do before :each do Puppet::Util::Ldap::Connection.stubs(:new).returns(stub_everything) @kick = Puppet::Application[:kick] Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) end it "should ask Puppet::Application to not parse Puppet configuration file" do - p @kick.object_id @kick.should_parse_config?.should be_false end it "should declare a main command" do @kick.should respond_to(:main) end it "should declare a test command" do @kick.should respond_to(:test) end it "should declare a preinit block" do - @kick.should respond_to(:run_preinit) + @kick.should respond_to(:preinit) end describe "during preinit" do before :each do @kick.stubs(:trap) end it "should catch INT and TERM" do @kick.stubs(:trap).with { |arg,block| arg == :INT or arg == :TERM } - @kick.run_preinit + @kick.preinit end it "should set parallel option to 1" do - @kick.run_preinit + @kick.preinit @kick.options[:parallel].should == 1 end it "should set verbose by default" do - @kick.run_preinit + @kick.preinit @kick.options[:verbose].should be_true end it "should set fqdn by default" do - @kick.run_preinit + @kick.preinit @kick.options[:fqdn].should be_true end it "should set ignoreschedules to 'false'" do - @kick.run_preinit + @kick.preinit @kick.options[:ignoreschedules].should be_false end it "should set foreground to 'false'" do - @kick.run_preinit + @kick.preinit @kick.options[:foreground].should be_false end end describe "when applying options" do + before do + @kick.preinit + end + [:all, :foreground, :debug, :ping, :test].each do |option| it "should declare handle_#{option} method" do @kick.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @kick.options.expects(:[]=).with(option, 'arg') @kick.send("handle_#{option}".to_sym, 'arg') end end it "should add to the host list with the host option" do @kick.handle_host('host') @kick.hosts.should == ['host'] end it "should add to the tag list with the tag option" do @kick.handle_tag('tag') @kick.tags.should == ['tag'] end it "should add to the class list with the class option" do @kick.handle_class('class') @kick.classes.should == ['class'] end end describe "during setup" do before :each do @kick.classes = [] @kick.tags = [] @kick.hosts = [] Puppet::Log.stubs(:level=) @kick.stubs(:trap) @kick.stubs(:puts) Puppet.stubs(:parse_config) @kick.options.stubs(:[]).with(any_parameters) end it "should set log level to debug if --debug was passed" do @kick.options.stubs(:[]).with(:debug).returns(true) Puppet::Log.expects(:level=).with(:debug) - @kick.run_setup + @kick.setup end it "should set log level to info if --verbose was passed" do @kick.options.stubs(:[]).with(:verbose).returns(true) Puppet::Log.expects(:level=).with(:info) - @kick.run_setup + @kick.setup end it "should Parse puppet config" do Puppet.expects(:parse_config) - @kick.run_setup + @kick.setup end describe "when using the ldap node terminus" do before :each do Puppet.stubs(:[]).with(:node_terminus).returns("ldap") end it "should pass the fqdn option to search" do @kick.options.stubs(:[]).with(:fqdn).returns(:something) @kick.options.stubs(:[]).with(:all).returns(true) @kick.stubs(:puts) Puppet::Node.expects(:search).with("whatever",:fqdn => :something).returns([]) - @kick.run_setup + @kick.setup end it "should search for all nodes if --all" do @kick.options.stubs(:[]).with(:all).returns(true) @kick.stubs(:puts) Puppet::Node.expects(:search).with("whatever",:fqdn => nil).returns([]) - @kick.run_setup + @kick.setup end it "should search for nodes including given classes" do @kick.options.stubs(:[]).with(:all).returns(false) @kick.stubs(:puts) @kick.classes = ['class'] Puppet::Node.expects(:search).with("whatever", :class => "class", :fqdn => nil).returns([]) - @kick.run_setup + @kick.setup end end describe "when using regular nodes" do it "should fail if some classes have been specified" do $stderr.stubs(:puts) @kick.classes = ['class'] @kick.expects(:exit).with(24) - @kick.run_setup + @kick.setup end end end describe "when running" do before :each do @kick.stubs(:puts) end it "should dispatch to test if --test is used" do @kick.options.stubs(:[]).with(:test).returns(true) - @kick.get_command.should == :test + @kick.expects(:test) + @kick.run_command end it "should dispatch to main if --test is not used" do @kick.options.stubs(:[]).with(:test).returns(false) - @kick.get_command.should == :main + @kick.expects(:main) + @kick.run_command end describe "the test command" do it "should exit with exit code 0 " do @kick.expects(:exit).with(0) @kick.test end end describe "the main command" do before :each do @kick.options.stubs(:[]).with(:parallel).returns(1) @kick.options.stubs(:[]).with(:ping).returns(false) @kick.options.stubs(:[]).with(:ignoreschedules).returns(false) @kick.options.stubs(:[]).with(:foreground).returns(false) + @kick.options.stubs(:[]).with(:debug).returns(false) @kick.stubs(:print) @kick.stubs(:exit) + @kick.preinit + @kick.parse_options + @kick.setup $stderr.stubs(:puts) end it "should create as much childs as --parallel" do @kick.options.stubs(:[]).with(:parallel).returns(3) @kick.hosts = ['host1', 'host2', 'host3'] @kick.stubs(:exit).raises(SystemExit) Process.stubs(:wait).returns(1).then.returns(2).then.returns(3).then.raises(Errno::ECHILD) @kick.expects(:fork).times(3).returns(1).then.returns(2).then.returns(3) lambda { @kick.main }.should raise_error end it "should delegate to run_for_host per host" do @kick.hosts = ['host1', 'host2'] @kick.stubs(:exit).raises(SystemExit) @kick.stubs(:fork).returns(1).yields Process.stubs(:wait).returns(1).then.raises(Errno::ECHILD) @kick.expects(:run_for_host).times(2) lambda { @kick.main }.should raise_error end describe "during call of run_for_host" do before do require 'puppet/run' options = { :background => true, :ignoreschedules => false, :tags => [] } + @kick.preinit @agent_run = Puppet::Run.new( options.dup ) @agent_run.stubs(:status).returns("success") Puppet::Run.indirection.expects(:terminus_class=).with( :rest ) Puppet::Run.expects(:new).with( options ).returns(@agent_run) end it "should call run on a Puppet::Run for the given host" do @agent_run.expects(:save).with('https://host:8139/production/run/host').returns(@agent_run) @kick.run_for_host('host') end it "should exit the child with 0 on success" do @agent_run.stubs(:status).returns("success") @kick.expects(:exit).with(0) @kick.run_for_host('host') end it "should exit the child with 3 on running" do @agent_run.stubs(:status).returns("running") @kick.expects(:exit).with(3) @kick.run_for_host('host') end it "should exit the child with 12 on unknown answer" do @agent_run.stubs(:status).returns("whatever") @kick.expects(:exit).with(12) @kick.run_for_host('host') end end end end end diff --git a/spec/unit/application/master.rb b/spec/unit/application/master.rb index b3c1a7275..2672fdb16 100644 --- a/spec/unit/application/master.rb +++ b/spec/unit/application/master.rb @@ -1,450 +1,456 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/master' -describe "PuppetMaster" do +describe Puppet::Application::Master do before :each do @master = Puppet::Application[:master] @daemon = stub_everything 'daemon' Puppet::Daemon.stubs(:new).returns(@daemon) Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) Puppet::Node.stubs(:terminus_class=) Puppet::Node.stubs(:cache_class=) Puppet::Node::Facts.stubs(:terminus_class=) Puppet::Node::Facts.stubs(:cache_class=) Puppet::Transaction::Report.stubs(:terminus_class=) Puppet::Resource::Catalog.stubs(:terminus_class=) end it "should ask Puppet::Application to parse Puppet configuration file" do @master.should_parse_config?.should be_true end it "should declare a main command" do @master.should respond_to(:main) end it "should declare a parseonly command" do @master.should respond_to(:parseonly) end it "should declare a compile command" do @master.should respond_to(:compile) end it "should declare a preinit block" do - @master.should respond_to(:run_preinit) + @master.should respond_to(:preinit) end describe "during preinit" do before :each do @master.stubs(:trap) end it "should catch INT" do @master.stubs(:trap).with { |arg,block| arg == :INT } - @master.run_preinit + @master.preinit end it "should create a Puppet Daemon" do Puppet::Daemon.expects(:new).returns(@daemon) - @master.run_preinit + @master.preinit end it "should give ARGV to the Daemon" do argv = stub 'argv' ARGV.stubs(:dup).returns(argv) @daemon.expects(:argv=).with(argv) - @master.run_preinit + @master.preinit end end [:debug,:verbose].each do |option| it "should declare handle_#{option} method" do @master.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @master.options.expects(:[]=).with(option, 'arg') @master.send("handle_#{option}".to_sym, 'arg') end end describe "when applying options" do before do @old_argv = ARGV.dup ARGV.clear end after do ARGV.clear @old_argv.each { |a| ARGV << a } end it "should set the log destination with --logdest" do Puppet::Log.expects(:newdestination).with("console") @master.handle_logdest("console") end it "should put the setdest options to true" do @master.options.expects(:[]=).with(:setdest,true) @master.handle_logdest("console") end it "should parse the log destination from ARGV" do ARGV << "--logdest" << "/my/file" Puppet::Util::Log.expects(:newdestination).with("/my/file") @master.parse_options end end describe "during setup" do before :each do Puppet::Log.stubs(:newdestination) Puppet.stubs(:settraps) Puppet::Log.stubs(:level=) Puppet::SSL::CertificateAuthority.stubs(:instance) Puppet::SSL::CertificateAuthority.stubs(:ca?) Puppet.settings.stubs(:use) @master.options.stubs(:[]).with(any_parameters) end it "should set log level to debug if --debug was passed" do @master.options.stubs(:[]).with(:debug).returns(true) Puppet::Log.expects(:level=).with(:debug) - @master.run_setup + @master.setup end it "should set log level to info if --verbose was passed" do @master.options.stubs(:[]).with(:verbose).returns(true) Puppet::Log.expects(:level=).with(:info) - @master.run_setup + @master.setup end it "should set console as the log destination if no --logdest and --daemonize" do @master.stubs(:[]).with(:daemonize).returns(:false) Puppet::Log.expects(:newdestination).with(:syslog) - @master.run_setup + @master.setup end it "should set syslog as the log destination if no --logdest and not --daemonize" do Puppet::Log.expects(:newdestination).with(:syslog) - @master.run_setup + @master.setup end it "should set syslog as the log destination if --rack" do @master.options.stubs(:[]).with(:rack).returns(:true) Puppet::Log.expects(:newdestination).with(:syslog) - @master.run_setup + @master.setup end it "should print puppet config if asked to in Puppet config" do @master.stubs(:exit) Puppet.settings.stubs(:print_configs?).returns(true) Puppet.settings.expects(:print_configs) - @master.run_setup + @master.setup end it "should exit after printing puppet config if asked to in Puppet config" do Puppet.settings.stubs(:print_configs?).returns(true) - lambda { @master.run_setup }.should raise_error(SystemExit) + lambda { @master.setup }.should raise_error(SystemExit) end it "should tell Puppet.settings to use :main,:ssl and :puppetmasterd category" do Puppet.settings.expects(:use).with(:main,:puppetmasterd,:ssl) - @master.run_setup + @master.setup end it "should set node facst terminus to yaml" do Puppet::Node::Facts.expects(:terminus_class=).with(:yaml) - @master.run_setup + @master.setup end it "should cache class in yaml" do Puppet::Node.expects(:cache_class=).with(:yaml) - @master.run_setup + @master.setup end describe "with no ca" do it "should set the ca_location to none" do Puppet::SSL::Host.expects(:ca_location=).with(:none) - @master.run_setup + @master.setup end end describe "with a ca configured" do before :each do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true) end it "should set the ca_location to local" do Puppet::SSL::Host.expects(:ca_location=).with(:local) - @master.run_setup + @master.setup end it "should tell Puppet.settings to use :ca category" do Puppet.settings.expects(:use).with(:ca) - @master.run_setup + @master.setup end it "should instantiate the CertificateAuthority singleton" do Puppet::SSL::CertificateAuthority.expects(:instance) - @master.run_setup + @master.setup end end end describe "when running" do + before do + @master.preinit + end it "should dispatch to parseonly if parseonly is set" do Puppet.stubs(:[]).with(:parseonly).returns(true) @master.options[:node] = nil - @master.get_command.should == :parseonly + @master.expects(:parseonly) + @master.run_command end it "should dispatch to compile if called with --compile" do @master.options[:node] = "foo" - @master.get_command.should == :compile + @master.expects(:compile) + @master.run_command end it "should dispatch to main if parseonly is not set" do Puppet.stubs(:[]).with(:parseonly).returns(false) @master.options[:node] = nil - @master.get_command.should == :main + @master.expects(:main) + @master.run_command end describe "the parseonly command" do before :each do Puppet.stubs(:[]).with(:environment) Puppet.stubs(:[]).with(:manifest).returns("site.pp") Puppet.stubs(:err) @master.stubs(:exit) @collection = stub_everything Puppet::Resource::TypeCollection.stubs(:new).returns(@collection) end it "should use a Puppet Resource Type Collection to parse the file" do @collection.expects(:perform_initial_import) @master.parseonly end it "should exit with exit code 0 if no error" do @master.expects(:exit).with(0) @master.parseonly end it "should exit with exit code 1 if error" do @collection.stubs(:perform_initial_import).raises(Puppet::ParseError) @master.expects(:exit).with(1) @master.parseonly end end describe "the compile command" do before do Puppet.stubs(:[]).with(:environment) Puppet.stubs(:[]).with(:manifest).returns("site.pp") Puppet.stubs(:err) @master.stubs(:exit) Puppet.features.stubs(:pson?).returns true end it "should fail if pson isn't available" do Puppet.features.expects(:pson?).returns false lambda { @master.compile }.should raise_error end it "should compile a catalog for the specified node" do @master.options[:node] = "foo" Puppet::Resource::Catalog.expects(:find).with("foo").returns Puppet::Resource::Catalog.new $stdout.stubs(:puts) @master.compile end it "should render the catalog to pson and print the output" do @master.options[:node] = "foo" catalog = Puppet::Resource::Catalog.new catalog.expects(:render).with(:pson).returns "mypson" Puppet::Resource::Catalog.expects(:find).returns catalog $stdout.expects(:puts).with("mypson") @master.compile end it "should exit with error code 30 if no catalog can be found" do @master.options[:node] = "foo" Puppet::Resource::Catalog.expects(:find).returns nil @master.expects(:exit).with(30) $stderr.expects(:puts) @master.compile end it "should exit with error code 30 if there's a failure" do @master.options[:node] = "foo" Puppet::Resource::Catalog.expects(:find).raises ArgumentError @master.expects(:exit).with(30) $stderr.expects(:puts) @master.compile end end describe "the main command" do before :each do - @master.run_preinit + @master.preinit @server = stub_everything 'server' Puppet::Network::Server.stubs(:new).returns(@server) @app = stub_everything 'app' Puppet::SSL::Host.stubs(:localhost) Puppet::SSL::CertificateAuthority.stubs(:ca?) Process.stubs(:uid).returns(1000) Puppet.stubs(:service) Puppet.stubs(:[]) Puppet.stubs(:notice) Puppet.stubs(:start) end it "should create a Server" do Puppet::Network::Server.expects(:new) @master.main end it "should give the server to the daemon" do @daemon.expects(:server=).with(@server) @master.main end it "should create the server with the right XMLRPC handlers" do Puppet::Network::Server.expects(:new).with { |args| args[:xmlrpc_handlers] == [:Status, :FileServer, :Master, :Report, :Filebucket]} @master.main end it "should create the server with a :ca xmlrpc handler if needed" do Puppet.stubs(:[]).with(:ca).returns(true) Puppet::Network::Server.expects(:new).with { |args| args[:xmlrpc_handlers].include?(:CA) } @master.main end it "should generate a SSL cert for localhost" do Puppet::SSL::Host.expects(:localhost) @master.main end it "should make sure to *only* hit the CA for data" do Puppet::SSL::CertificateAuthority.stubs(:ca?).returns(true) Puppet::SSL::Host.expects(:ca_location=).with(:only) @master.main end it "should drop privileges if running as root" do Process.stubs(:uid).returns(0) Puppet::Util.expects(:chuser) @master.main end it "should daemonize if needed" do Puppet.stubs(:[]).with(:daemonize).returns(true) @daemon.expects(:daemonize) @master.main end it "should start the service" do @daemon.expects(:start) @master.main end describe "with --rack" do confine "Rack is not available" => Puppet.features.rack? before do require 'puppet/network/http/rack' Puppet::Network::HTTP::Rack.stubs(:new).returns(@app) end it "it should create the app with REST and XMLRPC support" do @master.options.stubs(:[]).with(:rack).returns(:true) Puppet::Network::HTTP::Rack.expects(:new).with { |args| args[:xmlrpc_handlers] == [:Status, :FileServer, :Master, :Report, :Filebucket] and args[:protocols] == [:rest, :xmlrpc] } @master.main end it "it should not start a daemon" do @master.options.stubs(:[]).with(:rack).returns(:true) @daemon.expects(:start).never @master.main end it "it should return the app" do @master.options.stubs(:[]).with(:rack).returns(:true) app = @master.main app.should equal(@app) end end end end end diff --git a/spec/unit/application/queue.rb b/spec/unit/application/queue.rb index e761aece6..9f5b6c28c 100755 --- a/spec/unit/application/queue.rb +++ b/spec/unit/application/queue.rb @@ -1,186 +1,186 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/queue' -describe "queue" do +describe Puppet::Application::Queue do before :each do @queue = Puppet::Application[:queue] @queue.stubs(:puts) @daemon = stub_everything 'daemon', :daemonize => nil Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) Puppet::Resource::Catalog.stubs(:terminus_class=) end it "should ask Puppet::Application to parse Puppet configuration file" do @queue.should_parse_config?.should be_true end it "should declare a main command" do @queue.should respond_to(:main) end it "should declare a preinit block" do - @queue.should respond_to(:run_preinit) + @queue.should respond_to(:preinit) end describe "in preinit" do before :each do @queue.stubs(:trap) end it "should catch INT" do @queue.expects(:trap).with { |arg,block| arg == :INT } - @queue.run_preinit + @queue.preinit end it "should init :verbose to false" do - @queue.run_preinit + @queue.preinit @queue.options[:verbose].should be_false end it "should init :debug to false" do - @queue.run_preinit + @queue.preinit @queue.options[:debug].should be_false end it "should create a Daemon instance and copy ARGV to it" do ARGV.expects(:dup).returns "eh" daemon = mock("daemon") daemon.expects(:argv=).with("eh") Puppet::Daemon.expects(:new).returns daemon - @queue.run_preinit + @queue.preinit end end describe "when handling options" do [:debug, :verbose].each do |option| it "should declare handle_#{option} method" do @queue.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @queue.options.expects(:[]=).with(option, 'arg') @queue.send("handle_#{option}".to_sym, 'arg') end end end describe "during setup" do before :each do @queue.options.stubs(:[]) @queue.daemon.stubs(:daemonize) Puppet.stubs(:info) Puppet.features.stubs(:stomp?).returns true Puppet::Resource::Catalog.stubs(:terminus_class=) Puppet.stubs(:settraps) Puppet.settings.stubs(:print_config?) Puppet.settings.stubs(:print_config) end it "should fail if the stomp feature is missing" do Puppet.features.expects(:stomp?).returns false - lambda { @queue.run_setup }.should raise_error(ArgumentError) + lambda { @queue.setup }.should raise_error(ArgumentError) end it "should print puppet config if asked to in Puppet config" do @queue.stubs(:exit) Puppet.settings.stubs(:print_configs?).returns(true) Puppet.settings.expects(:print_configs) - @queue.run_setup + @queue.setup end it "should exit after printing puppet config if asked to in Puppet config" do Puppet.settings.stubs(:print_configs?).returns(true) - lambda { @queue.run_setup }.should raise_error(SystemExit) + lambda { @queue.setup }.should raise_error(SystemExit) end it "should call setup_logs" do @queue.expects(:setup_logs) - @queue.run_setup + @queue.setup end describe "when setting up logs" do before :each do Puppet::Util::Log.stubs(:newdestination) end it "should set log level to debug if --debug was passed" do @queue.options.stubs(:[]).with(:debug).returns(true) Puppet::Util::Log.expects(:level=).with(:debug) @queue.setup_logs end it "should set log level to info if --verbose was passed" do @queue.options.stubs(:[]).with(:verbose).returns(true) Puppet::Util::Log.expects(:level=).with(:info) @queue.setup_logs end [:verbose, :debug].each do |level| it "should set console as the log destination with level #{level}" do @queue.options.stubs(:[]).with(level).returns(true) Puppet::Util::Log.expects(:newdestination).with(:console) @queue.setup_logs end end end it "should configure the Catalog class to use ActiveRecord" do Puppet::Resource::Catalog.expects(:terminus_class=).with(:active_record) - @queue.run_setup + @queue.setup end it "should daemonize if needed" do Puppet.expects(:[]).with(:daemonize).returns(true) @queue.daemon.expects(:daemonize) - @queue.run_setup + @queue.setup end end describe "when running" do before :each do @queue.stubs(:sleep_forever) Puppet::Resource::Catalog::Queue.stubs(:subscribe) Thread.list.each { |t| t.stubs(:join) } end it "should subscribe to the queue" do Puppet::Resource::Catalog::Queue.expects(:subscribe) @queue.main end it "should log and save each catalog passed by the queue" do catalog = mock 'catalog', :name => 'eh' catalog.expects(:save) Puppet::Resource::Catalog::Queue.expects(:subscribe).yields(catalog) Puppet.expects(:notice).times(2) @queue.main end it "should join all of the running threads" do Thread.list.each { |t| t.expects(:join) } @queue.main end end end diff --git a/spec/unit/application/resource.rb b/spec/unit/application/resource.rb index 90fd3cc66..2e90cc288 100755 --- a/spec/unit/application/resource.rb +++ b/spec/unit/application/resource.rb @@ -1,232 +1,232 @@ #!/usr/bin/env ruby require File.dirname(__FILE__) + '/../../spec_helper' require 'puppet/application/resource' -describe "resource" do +describe Puppet::Application::Resource do before :each do @resource = Puppet::Application[:resource] Puppet::Util::Log.stubs(:newdestination) Puppet::Util::Log.stubs(:level=) Puppet::Resource.indirection.stubs(:terminus_class=) end it "should ask Puppet::Application to not parse Puppet configuration file" do @resource.should_parse_config?.should be_false end it "should declare a main command" do @resource.should respond_to(:main) end it "should declare a host option" do @resource.should respond_to(:handle_host) end it "should declare a types option" do @resource.should respond_to(:handle_types) end it "should declare a param option" do @resource.should respond_to(:handle_param) end it "should declare a preinit block" do - @resource.should respond_to(:run_preinit) + @resource.should respond_to(:preinit) end describe "in preinit" do it "should set hosts to nil" do - @resource.run_preinit + @resource.preinit @resource.host.should be_nil end it "should init extra_params to empty array" do - @resource.run_preinit + @resource.preinit @resource.extra_params.should == [] end it "should load Facter facts" do Facter.expects(:loadfacts).once - @resource.run_preinit + @resource.preinit end end describe "when handling options" do [:debug, :verbose, :edit].each do |option| it "should declare handle_#{option} method" do @resource.should respond_to("handle_#{option}".to_sym) end it "should store argument value when calling handle_#{option}" do @resource.options.expects(:[]=).with(option, 'arg') @resource.send("handle_#{option}".to_sym, 'arg') end end it "should set options[:host] to given host" do @resource.handle_host(:whatever) @resource.host.should == :whatever end it "should load an display all types with types option" do type1 = stub_everything 'type1', :name => :type1 type2 = stub_everything 'type2', :name => :type2 Puppet::Type.stubs(:loadall) Puppet::Type.stubs(:eachtype).multiple_yields(type1,type2) @resource.stubs(:exit) @resource.expects(:puts).with(['type1','type2']) @resource.handle_types(nil) end it "should add param to extra_params list" do @resource.extra_params = [ :param1 ] @resource.handle_param("whatever") @resource.extra_params.should == [ :param1, :whatever ] end end describe "during setup" do before :each do Puppet::Log.stubs(:newdestination) Puppet::Log.stubs(:level=) Puppet.stubs(:parse_config) end it "should set console as the log destination" do Puppet::Log.expects(:newdestination).with(:console) - @resource.run_setup + @resource.setup end it "should set log level to debug if --debug was passed" do @resource.options.stubs(:[]).with(:debug).returns(true) Puppet::Log.expects(:level=).with(:debug) - @resource.run_setup + @resource.setup end it "should set log level to info if --verbose was passed" do @resource.options.stubs(:[]).with(:debug).returns(false) @resource.options.stubs(:[]).with(:verbose).returns(true) Puppet::Log.expects(:level=).with(:info) - @resource.run_setup + @resource.setup end it "should Parse puppet config" do Puppet.expects(:parse_config) - @resource.run_setup + @resource.setup end end describe "when running" do before :each do @type = stub_everything 'type', :properties => [] Puppet::Util::CommandLine.stubs(:args).returns(['type']) Puppet::Type.stubs(:type).returns(@type) end it "should raise an error if no type is given" do Puppet::Util::CommandLine.stubs(:args).returns([]) lambda { @resource.main }.should raise_error end it "should raise an error when editing a remote host" do @resource.options.stubs(:[]).with(:edit).returns(true) @resource.host = 'host' lambda { @resource.main }.should raise_error end it "should raise an error if the type is not found" do Puppet::Type.stubs(:type).returns(nil) lambda { @resource.main }.should raise_error end describe "with a host" do before :each do @resource.stubs(:puts) @resource.host = 'host' Puppet::Resource.stubs(:find ).never Puppet::Resource.stubs(:search).never Puppet::Resource.stubs(:save ).never end it "should search for resources" do Puppet::Resource.expects(:search).with('https://host:8139/production/resources/type/', {}).returns([]) @resource.main end it "should describe the given resource" do Puppet::Util::CommandLine.stubs(:args).returns(['type', 'name']) x = stub_everything 'resource' Puppet::Resource.expects(:find).with('https://host:8139/production/resources/type/name').returns(x) @resource.main end it "should add given parameters to the object" do Puppet::Util::CommandLine.stubs(:args).returns(['type','name','param=temp']) res = stub "resource" res.expects(:save).with('https://host:8139/production/resources/type/name').returns(res) res.expects(:collect) res.expects(:to_manifest) Puppet::Resource.expects(:new).with('type', 'name', {'param' => 'temp'}).returns(res) @resource.main end end describe "without a host" do before :each do @resource.stubs(:puts) @resource.host = nil Puppet::Resource.stubs(:find ).never Puppet::Resource.stubs(:search).never Puppet::Resource.stubs(:save ).never end it "should search for resources" do Puppet::Resource.expects(:search).with('type/', {}).returns([]) @resource.main end it "should describe the given resource" do Puppet::Util::CommandLine.stubs(:args).returns(['type','name']) x = stub_everything 'resource' Puppet::Resource.expects(:find).with('type/name').returns(x) @resource.main end it "should add given parameters to the object" do Puppet::Util::CommandLine.stubs(:args).returns(['type','name','param=temp']) res = stub "resource" res.expects(:save).with('type/name').returns(res) res.expects(:collect) res.expects(:to_manifest) Puppet::Resource.expects(:new).with('type', 'name', {'param' => 'temp'}).returns(res) @resource.main end end end end