diff --git a/lib/puppet/application/config.rb b/lib/puppet/application/config.rb index 41a46c339..a94441e7f 100644 --- a/lib/puppet/application/config.rb +++ b/lib/puppet/application/config.rb @@ -1,4 +1,4 @@ -require 'puppet/application/faces_base' +require 'puppet/application/face_base' -class Puppet::Application::Config < Puppet::Application::FacesBase +class Puppet::Application::Config < Puppet::Application::FaceBase end diff --git a/lib/puppet/application/configurer.rb b/lib/puppet/application/configurer.rb index 751e6b4d7..6e86cd2d4 100644 --- a/lib/puppet/application/configurer.rb +++ b/lib/puppet/application/configurer.rb @@ -1,23 +1,23 @@ require 'puppet/application' -require 'puppet/faces' +require 'puppet/face' class Puppet::Application::Configurer < Puppet::Application should_parse_config run_mode :agent option("--debug", "-d") option("--verbose", "-v") def setup if options[:debug] or options[:verbose] Puppet::Util::Log.level = options[:debug] ? :debug : :info end Puppet::Util::Log.newdestination(:console) end def run_command - report = Puppet::Faces[:configurer, '0.0.1'].synchronize(Puppet[:certname]) - Puppet::Faces[:report, '0.0.1'].submit(report) + report = Puppet::Face[:configurer, '0.0.1'].synchronize(Puppet[:certname]) + Puppet::Face[:report, '0.0.1'].submit(report) end end diff --git a/lib/puppet/application/faces_base.rb b/lib/puppet/application/face_base.rb similarity index 97% rename from lib/puppet/application/faces_base.rb rename to lib/puppet/application/face_base.rb index f1b77f285..2a048a532 100644 --- a/lib/puppet/application/faces_base.rb +++ b/lib/puppet/application/face_base.rb @@ -1,158 +1,158 @@ require 'puppet/application' -require 'puppet/faces' +require 'puppet/face' require 'optparse' -class Puppet::Application::FacesBase < Puppet::Application +class Puppet::Application::FaceBase < Puppet::Application should_parse_config run_mode :agent option("--debug", "-d") do |arg| Puppet::Util::Log.level = :debug end option("--verbose", "-v") do Puppet::Util::Log.level = :info end option("--format FORMAT") do |arg| @format = arg.to_sym end option("--mode RUNMODE", "-r") do |arg| raise "Invalid run mode #{arg}; supported modes are user, agent, master" unless %w{user agent master}.include?(arg) self.class.run_mode(arg.to_sym) set_run_mode self.class.run_mode end attr_accessor :face, :action, :type, :arguments, :format attr_writer :exit_code # This allows you to set the exit code if you don't want to just exit # immediately but you need to indicate a failure. def exit_code @exit_code || 0 end # Override this if you need custom rendering. def render(result) render_method = Puppet::Network::FormatHandler.format(format).render_method if render_method == "to_pson" jj result exit(0) else result.send(render_method) end end def preinit super Signal.trap(:INT) do $stderr.puts "Cancelling Face" exit(0) end end def parse_options # We need to parse enough of the command line out early, to identify what # the action is, so that we can obtain the full set of options to parse. # REVISIT: These should be configurable versions, through a global # '--version' option, but we don't implement that yet... --daniel 2011-03-29 @type = self.class.name.to_s.sub(/.+:/, '').downcase.to_sym - @face = Puppet::Faces[@type, :current] + @face = Puppet::Face[@type, :current] @format = @face.default_format # Now, walk the command line and identify the action. We skip over # arguments based on introspecting the action and all, and find the first # non-option word to use as the action. action = nil index = -1 until @action or (index += 1) >= command_line.args.length do item = command_line.args[index] if item =~ /^-/ then option = @face.options.find do |name| item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/ end if option then option = @face.get_option(option) # If we have an inline argument, just carry on. We don't need to # care about optional vs mandatory in that case because we do a real # parse later, and that will totally take care of raising the error # when we get there. --daniel 2011-04-04 if option.takes_argument? and !item.index('=') then index += 1 unless (option.optional_argument? and command_line.args[index + 1] =~ /^-/) end elsif option = find_global_settings_argument(item) then unless Puppet.settings.boolean? option.name then # As far as I can tell, we treat non-bool options as always having # a mandatory argument. --daniel 2011-04-05 index += 1 # ...so skip the argument. end else raise OptionParser::InvalidOption.new(item.sub(/=.*$/, '')) end else action = @face.get_action(item.to_sym) if action.nil? then raise OptionParser::InvalidArgument.new("#{@face} does not have an #{item} action") end @action = action end end unless @action raise OptionParser::MissingArgument.new("No action given on the command line") end # Now we can interact with the default option code to build behaviour # around the full set of options we now know we support. @action.options.each do |option| option = @action.get_option(option) # make it the object. self.class.option(*option.optparse) # ...and make the CLI parse it. end # ...and invoke our parent to parse all the command line options. super end def find_global_settings_argument(item) Puppet.settings.each do |name, object| object.optparse_args.each do |arg| next unless arg =~ /^-/ # sadly, we have to emulate some of optparse here... pattern = /^#{arg.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/ pattern.match item and return object end end return nil # nothing found. end def setup Puppet::Util::Log.newdestination :console @arguments = command_line.args # Note: because of our definition of where the action is set, we end up # with it *always* being the first word of the remaining set of command # line arguments. So, strip that off when we construct the arguments to # pass down to the face action. --daniel 2011-04-04 @arguments.delete_at(0) # We copy all of the app options to the end of the call; This allows each # action to read in the options. This replaces the older model where we # would invoke the action with options set as global state in the # interface object. --daniel 2011-03-28 @arguments << options end def main # Call the method associated with the provided action (e.g., 'find'). if result = @face.send(@action.name, *arguments) puts render(result) end exit(exit_code) end end diff --git a/lib/puppet/application/faces.rb b/lib/puppet/application/faces.rb index a7b227e23..3dd3f0312 100644 --- a/lib/puppet/application/faces.rb +++ b/lib/puppet/application/faces.rb @@ -1,88 +1,88 @@ require 'puppet/application' -require 'puppet/faces' +require 'puppet/face' class Puppet::Application::Faces < Puppet::Application should_parse_config run_mode :agent option("--debug", "-d") do |arg| Puppet::Util::Log.level = :debug end option("--help", "-h") do |arg| puts "Usage: puppet faces [actions|terminuses] -Lists all available interfaces, and by default includes all available terminuses and actions. +Lists all available faces, and by default includes all available terminuses and actions. " end option("--verbose", "-v") do Puppet::Util::Log.level = :info end def list(*arguments) if arguments.empty? arguments = %w{terminuses actions} end faces.each do |name| str = "#{name}:\n" if arguments.include?("terminuses") begin terms = terminus_classes(name.to_sym) str << "\tTerminuses: #{terms.join(", ")}\n" rescue => detail puts detail.backtrace if Puppet[:trace] $stderr.puts "Could not load terminuses for #{name}: #{detail}" end end if arguments.include?("actions") begin actions = actions(name.to_sym) str << "\tActions: #{actions.join(", ")}\n" rescue => detail puts detail.backtrace if Puppet[:trace] $stderr.puts "Could not load actions for #{name}: #{detail}" end end print str end end attr_accessor :name, :arguments def main list(*arguments) end def setup Puppet::Util::Log.newdestination :console load_applications # Call this to load all of the apps @arguments = command_line.args @arguments ||= [] end def faces - Puppet::Faces.faces + Puppet::Face.faces end def terminus_classes(indirection) Puppet::Indirector::Terminus.terminus_classes(indirection).collect { |t| t.to_s }.sort end def actions(indirection) - return [] unless faces = Puppet::Faces[indirection, '0.0.1'] - faces.load_actions - return faces.actions.sort { |a, b| a.to_s <=> b.to_s } + return [] unless face = Puppet::Face[indirection, '0.0.1'] + face.load_actions + return face.actions.sort { |a, b| a.to_s <=> b.to_s } end def load_applications command_line.available_subcommands.each do |app| command_line.require_application app end end end diff --git a/lib/puppet/application/help.rb b/lib/puppet/application/help.rb index fd8818db0..0d7767632 100644 --- a/lib/puppet/application/help.rb +++ b/lib/puppet/application/help.rb @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -require 'puppet/application/faces_base' +require 'puppet/application/face_base' -class Puppet::Application::Help < Puppet::Application::FacesBase +class Puppet::Application::Help < Puppet::Application::FaceBase # Meh. Disable the default behaviour, which is to inspect the # string and return that – not so helpful. --daniel 2011-04-11 def render(result) result end end diff --git a/lib/puppet/application/indirection_base.rb b/lib/puppet/application/indirection_base.rb index 7455ebedf..580a0999a 100644 --- a/lib/puppet/application/indirection_base.rb +++ b/lib/puppet/application/indirection_base.rb @@ -1,4 +1,4 @@ -require 'puppet/application/faces_base' +require 'puppet/application/face_base' -class Puppet::Application::IndirectionBase < Puppet::Application::FacesBase +class Puppet::Application::IndirectionBase < Puppet::Application::FaceBase end diff --git a/lib/puppet/faces.rb b/lib/puppet/face.rb similarity index 82% rename from lib/puppet/faces.rb rename to lib/puppet/face.rb index 947eecf24..f73b2fc3b 100644 --- a/lib/puppet/faces.rb +++ b/lib/puppet/face.rb @@ -1,12 +1,12 @@ -# The public name of this feature is 'faces', but we have hidden all the +# The public name of this feature is 'face', but we have hidden all the # plumbing over in the 'interfaces' namespace to make clear the distinction # between the two. # # This file exists to ensure that the public name is usable without revealing # the details of the implementation; you really only need go look at anything # under Interfaces if you are looking to extend the implementation. # # It isn't hidden to gratuitously hide things, just to make it easier to # separate out the interests people will have. --daniel 2011-04-07 require 'puppet/interface' -Puppet::Faces = Puppet::Interface +Puppet::Face = Puppet::Interface diff --git a/lib/puppet/faces/catalog.rb b/lib/puppet/face/catalog.rb similarity index 85% rename from lib/puppet/faces/catalog.rb rename to lib/puppet/face/catalog.rb index 3353d5d04..0dcde3591 100644 --- a/lib/puppet/faces/catalog.rb +++ b/lib/puppet/face/catalog.rb @@ -1,40 +1,40 @@ -require 'puppet/faces/indirector' +require 'puppet/face/indirector' -Puppet::Faces::Indirector.define(:catalog, '0.0.1') do +Puppet::Face::Indirector.define(:catalog, '0.0.1') do action(:apply) do when_invoked do |catalog, options| report = Puppet::Transaction::Report.new("apply") report.configuration_version = catalog.version Puppet::Util::Log.newdestination(report) begin benchmark(:notice, "Finished catalog run") do catalog.apply(:report => report) end rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Failed to apply catalog: #{detail}" end report.finalize_report report end end action(:download) do when_invoked do |certname, facts, options| Puppet::Resource::Catalog.indirection.terminus_class = :rest facts_to_upload = {:facts_format => :b64_zlib_yaml, :facts => CGI.escape(facts.render(:b64_zlib_yaml))} catalog = nil retrieval_duration = thinmark do - catalog = Puppet::Faces[:catalog, '0.0.1'].find(certname, facts_to_upload) + catalog = Puppet::Face[:catalog, '0.0.1'].find(certname, facts_to_upload) end catalog = catalog.to_ral catalog.finalize catalog.retrieval_duration = retrieval_duration catalog.write_class_file catalog end end end diff --git a/lib/puppet/faces/catalog/select.rb b/lib/puppet/face/catalog/select.rb similarity index 86% rename from lib/puppet/faces/catalog/select.rb rename to lib/puppet/face/catalog/select.rb index e29d19970..ba27117bc 100644 --- a/lib/puppet/faces/catalog/select.rb +++ b/lib/puppet/face/catalog/select.rb @@ -1,10 +1,10 @@ # Select and show a list of resources of a given type. -Puppet::Faces.define(:catalog, '0.0.1') do +Puppet::Face.define(:catalog, '0.0.1') do action :select do when_invoked do |host, type, options| catalog = Puppet::Resource::Catalog.indirection.find(host) catalog.resources.reject { |res| res.type != type }.each { |res| puts res } end end end diff --git a/lib/puppet/faces/certificate.rb b/lib/puppet/face/certificate.rb similarity index 93% rename from lib/puppet/faces/certificate.rb rename to lib/puppet/face/certificate.rb index b10bee579..77e80f099 100644 --- a/lib/puppet/faces/certificate.rb +++ b/lib/puppet/face/certificate.rb @@ -1,46 +1,46 @@ -require 'puppet/faces/indirector' +require 'puppet/face/indirector' require 'puppet/ssl/host' -Puppet::Faces::Indirector.define(:certificate, '0.0.1') do +Puppet::Face::Indirector.define(:certificate, '0.0.1') do # REVISIT: This should use a pre-invoke hook to run the common code that # needs to happen before we invoke any action; that would be much nicer than # the "please repeat yourself" stuff found in here right now. # # option "--ca-location LOCATION" do # type [:whatever, :location, :symbols] # hook :before do |value| # Puppet::SSL::Host.ca_location = value # end # end # # ...but should I pass the arguments as well? # --daniel 2011-04-05 option "--ca-location LOCATION" action :generate do when_invoked do |name, options| Puppet::SSL::Host.ca_location = options[:ca_location].to_sym host = Puppet::SSL::Host.new(name) host.generate_certificate_request host.certificate_request.class.indirection.save(host.certificate_request) end end action :list do when_invoked do |options| Puppet::SSL::Host.ca_location = options[:ca_location].to_sym Puppet::SSL::Host.indirection.search("*", { :for => :certificate_request, }).map { |h| h.inspect } end end action :sign do when_invoked do |name, options| Puppet::SSL::Host.ca_location = options[:ca_location].to_sym host = Puppet::SSL::Host.new(name) host.desired_state = 'signed' Puppet::SSL::Host.indirection.save(host) end end end diff --git a/lib/puppet/face/certificate_request.rb b/lib/puppet/face/certificate_request.rb new file mode 100644 index 000000000..1feba25ab --- /dev/null +++ b/lib/puppet/face/certificate_request.rb @@ -0,0 +1,4 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:certificate_request, '0.0.1') do +end diff --git a/lib/puppet/face/certificate_revocation_list.rb b/lib/puppet/face/certificate_revocation_list.rb new file mode 100644 index 000000000..6a75aa578 --- /dev/null +++ b/lib/puppet/face/certificate_revocation_list.rb @@ -0,0 +1,4 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:certificate_revocation_list, '0.0.1') do +end diff --git a/lib/puppet/faces/config.rb b/lib/puppet/face/config.rb similarity index 75% rename from lib/puppet/faces/config.rb rename to lib/puppet/face/config.rb index 647bf5052..45cb6b156 100644 --- a/lib/puppet/faces/config.rb +++ b/lib/puppet/face/config.rb @@ -1,12 +1,12 @@ -require 'puppet/faces' +require 'puppet/face' -Puppet::Faces.define(:config, '0.0.1') do +Puppet::Face.define(:config, '0.0.1') do action(:print) do when_invoked do |*args| options = args.pop Puppet.settings[:configprint] = args.join(",") Puppet.settings.print_config_options nil end end end diff --git a/lib/puppet/face/configurer.rb b/lib/puppet/face/configurer.rb new file mode 100644 index 000000000..74dfb854e --- /dev/null +++ b/lib/puppet/face/configurer.rb @@ -0,0 +1,12 @@ +require 'puppet/face' + +Puppet::Face.define(:configurer, '0.0.1') do + action(:synchronize) do + when_invoked do |certname, options| + facts = Puppet::Face[:facts, '0.0.1'].find(certname) + catalog = Puppet::Face[:catalog, '0.0.1'].download(certname, facts) + report = Puppet::Face[:catalog, '0.0.1'].apply(catalog) + report + end + end +end diff --git a/lib/puppet/faces/facts.rb b/lib/puppet/face/facts.rb similarity index 84% rename from lib/puppet/faces/facts.rb rename to lib/puppet/face/facts.rb index 33eacef38..8668b2531 100644 --- a/lib/puppet/faces/facts.rb +++ b/lib/puppet/face/facts.rb @@ -1,18 +1,18 @@ -require 'puppet/faces/indirector' +require 'puppet/face/indirector' require 'puppet/node/facts' -Puppet::Faces::Indirector.define(:facts, '0.0.1') do +Puppet::Face::Indirector.define(:facts, '0.0.1') do set_default_format :yaml # Upload our facts to the server action(:upload) do when_invoked do |options| Puppet::Node::Facts.indirection.terminus_class = :facter facts = Puppet::Node::Facts.indirection.find(Puppet[:certname]) Puppet::Node::Facts.indirection.terminus_class = :rest Puppet::Node::Facts.indirection.save(facts) Puppet.notice "Uploaded facts for '#{Puppet[:certname]}'" nil end end end diff --git a/lib/puppet/face/file.rb b/lib/puppet/face/file.rb new file mode 100644 index 000000000..1aa9462dd --- /dev/null +++ b/lib/puppet/face/file.rb @@ -0,0 +1,5 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:file, '0.0.1') do + set_indirection_name :file_bucket_file +end diff --git a/lib/puppet/faces/help.rb b/lib/puppet/face/help.rb similarity index 93% rename from lib/puppet/faces/help.rb rename to lib/puppet/face/help.rb index 1d8abe20e..1c2da9e83 100644 --- a/lib/puppet/faces/help.rb +++ b/lib/puppet/face/help.rb @@ -1,104 +1,104 @@ -require 'puppet/faces' +require 'puppet/face' require 'puppet/util/command_line' require 'pathname' require 'erb' -Puppet::Faces.define(:help, '0.0.1') do +Puppet::Face.define(:help, '0.0.1') do summary "Displays help about puppet subcommands" action(:help) do summary "Display help about faces and their actions." option "--version VERSION" do desc "Which version of the interface to show help for" end when_invoked do |*args| # Check our invocation, because we want varargs and can't do defaults # yet. REVISIT: when we do option defaults, and positional options, we # should rewrite this to use those. --daniel 2011-04-04 options = args.pop if options.nil? or args.length > 2 then raise ArgumentError, "help only takes two (optional) arguments, a face name, and an action" end version = :current if options.has_key? :version then if options[:version].to_s !~ /^current$/i then version = options[:version] else if args.length == 0 then raise ArgumentError, "version only makes sense when a face is given" end end end # Name those parameters... facename, actionname = args if facename then if legacy_applications.include? facename then actionname and raise ArgumentError, "Legacy subcommands don't take actions" return Puppet::Application[facename].help else - face = Puppet::Faces[facename.to_sym, version] + face = Puppet::Face[facename.to_sym, version] actionname and action = face.get_action(actionname.to_sym) end end case args.length when 0 then template = erb 'global.erb' when 1 then face or fail ArgumentError, "Unable to load face #{facename}" template = erb 'face.erb' when 2 then face or fail ArgumentError, "Unable to load face #{facename}" action or fail ArgumentError, "Unable to load action #{actionname} from #{face}" template = erb 'action.erb' else fail ArgumentError, "Too many arguments to help action" end # Run the ERB template in our current binding, including all the local # variables we established just above. --daniel 2011-04-11 return template.result(binding) end end def erb(name) template = (Pathname(__FILE__).dirname + "help" + name) erb = ERB.new(template.read, nil, '%') erb.filename = template.to_s return erb end def legacy_applications # The list of applications, less those that are duplicated as a face. Puppet::Util::CommandLine.available_subcommands.reject do |appname| - Puppet::Faces.face? appname.to_sym, :current or + Puppet::Face.face? appname.to_sym, :current or # ...this is a nasty way to exclude non-applications. :( - %w{faces_base indirection_base}.include? appname + %w{face_base indirection_base}.include? appname end.sort end def horribly_extract_summary_from(appname) begin require "puppet/application/#{appname}" help = Puppet::Application[appname].help.split("\n") # Now we find the line with our summary, extract it, and return it. This # depends on the implementation coincidence of how our pages are # formatted. If we can't match the pattern we expect we return the empty # string to ensure we don't blow up in the summary. --daniel 2011-04-11 while line = help.shift do if md = /^puppet-#{appname}\([^\)]+\) -- (.*)$/.match(line) then return md[1] end end rescue Exception # Damn, but I hate this: we just ignore errors here, no matter what # class they are. Meh. end return '' end end diff --git a/lib/puppet/faces/help/action.erb b/lib/puppet/face/help/action.erb similarity index 100% rename from lib/puppet/faces/help/action.erb rename to lib/puppet/face/help/action.erb diff --git a/lib/puppet/faces/help/face.erb b/lib/puppet/face/help/face.erb similarity index 100% rename from lib/puppet/faces/help/face.erb rename to lib/puppet/face/help/face.erb diff --git a/lib/puppet/faces/help/global.erb b/lib/puppet/face/help/global.erb similarity index 89% rename from lib/puppet/faces/help/global.erb rename to lib/puppet/face/help/global.erb index e123367a2..f4c761b2b 100644 --- a/lib/puppet/faces/help/global.erb +++ b/lib/puppet/face/help/global.erb @@ -1,20 +1,20 @@ puppet [options] [options] Available subcommands, from Puppet Faces: -% Puppet::Faces.faces.sort.each do |name| -% face = Puppet::Faces[name, :current] +% Puppet::Face.faces.sort.each do |name| +% face = Puppet::Face[name, :current] <%= face.name.to_s.ljust(16) %> <%= face.summary %> % end % unless legacy_applications.empty? then # great victory when this is true! Available applications, soon to be ported to Faces: % legacy_applications.each do |appname| % summary = horribly_extract_summary_from appname <%= appname.to_s.ljust(16) %> <%= summary %> % end % end See 'puppet help ' for help on a specific subcommand action. See 'puppet help ' for help on a specific subcommand. See 'puppet man ' for the full man page. Puppet v<%= Puppet::PUPPETVERSION %> diff --git a/lib/puppet/faces/indirector.rb b/lib/puppet/face/indirector.rb similarity index 97% rename from lib/puppet/faces/indirector.rb rename to lib/puppet/face/indirector.rb index 7e4e0f00f..f48611e4b 100644 --- a/lib/puppet/faces/indirector.rb +++ b/lib/puppet/face/indirector.rb @@ -1,94 +1,94 @@ require 'puppet' -require 'puppet/faces' +require 'puppet/face' -class Puppet::Faces::Indirector < Puppet::Faces +class Puppet::Face::Indirector < Puppet::Face option "--terminus TERMINUS" do desc "REVISIT: You can select a terminus, which has some bigger effect that we should describe in this file somehow." end def self.indirections Puppet::Indirector::Indirection.instances.collect { |t| t.to_s }.sort end def self.terminus_classes(indirection) Puppet::Indirector::Terminus.terminus_classes(indirection.to_sym).collect { |t| t.to_s }.sort end def call_indirection_method(method, *args) options = args.last options.has_key?(:terminus) and set_terminus(options[:terminus]) begin result = indirection.__send__(method, *args) rescue => detail puts detail.backtrace if Puppet[:trace] raise "Could not call '#{method}' on '#{indirection_name}': #{detail}" end indirection.reset_terminus_class return result end action :destroy do when_invoked { |*args| call_indirection_method(:destroy, *args) } end action :find do when_invoked { |*args| call_indirection_method(:find, *args) } end action :save do when_invoked { |*args| call_indirection_method(:save, *args) } end action :search do when_invoked { |*args| call_indirection_method(:search, *args) } end # Print the configuration for the current terminus class action :info do when_invoked do |*args| options = args.pop options.has_key?(:terminus) and set_terminus(options[:terminus]) if t = indirection.terminus_class puts "Run mode '#{Puppet.run_mode.name}': #{t}" else $stderr.puts "No default terminus class for run mode '#{Puppet.run_mode.name}'" end indirection.reset_terminus_class end end attr_accessor :from def indirection_name @indirection_name || name.to_sym end # Here's your opportunity to override the indirection name. By default it # will be the same name as the face. def set_indirection_name(name) @indirection_name = name end # Return an indirection associated with a face, if one exists; # One usually does. def indirection unless @indirection @indirection = Puppet::Indirector::Indirection.instance(indirection_name) @indirection or raise "Could not find terminus for #{indirection_name}" end @indirection end def set_terminus(from) begin indirection.terminus_class = from rescue => detail raise "Could not set '#{indirection.name}' terminus to '#{from}' (#{detail}); valid terminus types are #{self.class.terminus_classes(indirection.name).join(", ") }" end end end diff --git a/lib/puppet/face/key.rb b/lib/puppet/face/key.rb new file mode 100644 index 000000000..3a11ddb03 --- /dev/null +++ b/lib/puppet/face/key.rb @@ -0,0 +1,4 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:key, '0.0.1') do +end diff --git a/lib/puppet/face/node.rb b/lib/puppet/face/node.rb new file mode 100644 index 000000000..fd1a548d6 --- /dev/null +++ b/lib/puppet/face/node.rb @@ -0,0 +1,5 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:node, '0.0.1') do + set_default_format :yaml +end diff --git a/lib/puppet/faces/report.rb b/lib/puppet/face/report.rb similarity index 77% rename from lib/puppet/faces/report.rb rename to lib/puppet/face/report.rb index 23a518981..6e6f0b335 100644 --- a/lib/puppet/faces/report.rb +++ b/lib/puppet/face/report.rb @@ -1,15 +1,15 @@ -require 'puppet/faces/indirector' +require 'puppet/face/indirector' -Puppet::Faces::Indirector.define(:report, '0.0.1') do +Puppet::Face::Indirector.define(:report, '0.0.1') do action(:submit) do when_invoked do |report, options| begin Puppet::Transaction::Report.terminus_class = :rest report.save rescue => detail puts detail.backtrace if Puppet[:trace] Puppet.err "Could not send report: #{detail}" end end end end diff --git a/lib/puppet/face/resource.rb b/lib/puppet/face/resource.rb new file mode 100644 index 000000000..d162f728a --- /dev/null +++ b/lib/puppet/face/resource.rb @@ -0,0 +1,4 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:resource, '0.0.1') do +end diff --git a/lib/puppet/face/resource_type.rb b/lib/puppet/face/resource_type.rb new file mode 100644 index 000000000..0cdbd719f --- /dev/null +++ b/lib/puppet/face/resource_type.rb @@ -0,0 +1,4 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:resource_type, '0.0.1') do +end diff --git a/lib/puppet/face/status.rb b/lib/puppet/face/status.rb new file mode 100644 index 000000000..7085e7cd7 --- /dev/null +++ b/lib/puppet/face/status.rb @@ -0,0 +1,4 @@ +require 'puppet/face/indirector' + +Puppet::Face::Indirector.define(:status, '0.0.1') do +end diff --git a/lib/puppet/faces/certificate_request.rb b/lib/puppet/faces/certificate_request.rb deleted file mode 100644 index 5e91bdb7f..000000000 --- a/lib/puppet/faces/certificate_request.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:certificate_request, '0.0.1') do -end diff --git a/lib/puppet/faces/certificate_revocation_list.rb b/lib/puppet/faces/certificate_revocation_list.rb deleted file mode 100644 index 2f2d72874..000000000 --- a/lib/puppet/faces/certificate_revocation_list.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:certificate_revocation_list, '0.0.1') do -end diff --git a/lib/puppet/faces/configurer.rb b/lib/puppet/faces/configurer.rb deleted file mode 100644 index d40987697..000000000 --- a/lib/puppet/faces/configurer.rb +++ /dev/null @@ -1,12 +0,0 @@ -require 'puppet/faces' - -Puppet::Faces.define(:configurer, '0.0.1') do - action(:synchronize) do - when_invoked do |certname, options| - facts = Puppet::Faces[:facts, '0.0.1'].find(certname) - catalog = Puppet::Faces[:catalog, '0.0.1'].download(certname, facts) - report = Puppet::Faces[:catalog, '0.0.1'].apply(catalog) - report - end - end -end diff --git a/lib/puppet/faces/file.rb b/lib/puppet/faces/file.rb deleted file mode 100644 index e8ad18c17..000000000 --- a/lib/puppet/faces/file.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:file, '0.0.1') do - set_indirection_name :file_bucket_file -end diff --git a/lib/puppet/faces/key.rb b/lib/puppet/faces/key.rb deleted file mode 100644 index 7b6ad52ac..000000000 --- a/lib/puppet/faces/key.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:key, '0.0.1') do -end diff --git a/lib/puppet/faces/node.rb b/lib/puppet/faces/node.rb deleted file mode 100644 index 7eed0df91..000000000 --- a/lib/puppet/faces/node.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:node, '0.0.1') do - set_default_format :yaml -end diff --git a/lib/puppet/faces/resource.rb b/lib/puppet/faces/resource.rb deleted file mode 100644 index 60b0d94db..000000000 --- a/lib/puppet/faces/resource.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:resource, '0.0.1') do -end diff --git a/lib/puppet/faces/resource_type.rb b/lib/puppet/faces/resource_type.rb deleted file mode 100644 index 4321d65e7..000000000 --- a/lib/puppet/faces/resource_type.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:resource_type, '0.0.1') do -end diff --git a/lib/puppet/faces/status.rb b/lib/puppet/faces/status.rb deleted file mode 100644 index e035f281f..000000000 --- a/lib/puppet/faces/status.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces/indirector' - -Puppet::Faces::Indirector.define(:status, '0.0.1') do -end diff --git a/lib/puppet/interface.rb b/lib/puppet/interface.rb index 27b3584b9..6570ebe46 100644 --- a/lib/puppet/interface.rb +++ b/lib/puppet/interface.rb @@ -1,120 +1,120 @@ require 'puppet' require 'puppet/util/autoload' class Puppet::Interface require 'puppet/interface/face_collection' require 'puppet/interface/action_manager' include Puppet::Interface::ActionManager extend Puppet::Interface::ActionManager require 'puppet/interface/option_manager' include Puppet::Interface::OptionManager extend Puppet::Interface::OptionManager include Puppet::Util class << self # This is just so we can search for actions. We only use its # list of directories to search. # Can't we utilize an external autoloader, or simply use the $LOAD_PATH? -pvb def autoloader - @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/faces") + @autoloader ||= Puppet::Util::Autoload.new(:application, "puppet/face") end def faces Puppet::Interface::FaceCollection.faces end def face?(name, version) Puppet::Interface::FaceCollection.face?(name, version) end def register(instance) Puppet::Interface::FaceCollection.register(instance) end def define(name, version, &block) if face?(name, version) face = Puppet::Interface::FaceCollection[name, version] else face = self.new(name, version) Puppet::Interface::FaceCollection.register(face) # REVISIT: Shouldn't this be delayed until *after* we evaluate the # current block, not done before? --daniel 2011-04-07 face.load_actions end face.instance_eval(&block) if block_given? return face end def [](name, version) unless face = Puppet::Interface::FaceCollection[name, version] if current = Puppet::Interface::FaceCollection[name, :current] raise Puppet::Error, "Could not find version #{version} of #{current}" else raise Puppet::Error, "Could not find Puppet Face #{name.inspect}" end end face end end attr_accessor :default_format def set_default_format(format) self.default_format = format.to_sym end attr_accessor :summary def summary(value = nil) @summary = value unless value.nil? @summary end attr_reader :name, :version def initialize(name, version, &block) unless Puppet::Interface::FaceCollection.validate_version(version) raise ArgumentError, "Cannot create face #{name.inspect} with invalid version number '#{version}'!" end @name = Puppet::Interface::FaceCollection.underscorize(name) @version = version @default_format = :pson instance_eval(&block) if block_given? end # Try to find actions defined in other files. def load_actions - path = "puppet/faces/#{name}" + path = "puppet/face/#{name}" loaded = [] [path, "#{name}@#{version}/#{path}"].each do |path| Puppet::Interface.autoloader.search_directories.each do |dir| fdir = ::File.join(dir, path) next unless FileTest.directory?(fdir) Dir.chdir(fdir) do Dir.glob("*.rb").each do |file| aname = file.sub(/\.rb/, '') if loaded.include?(aname) Puppet.debug "Not loading duplicate action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" next end loaded << aname Puppet.debug "Loading action '#{aname}' for '#{name}' from '#{fdir}/#{file}'" require "#{Dir.pwd}/#{aname}" end end end end end def to_s - "Puppet::Faces[#{name.inspect}, #{version.inspect}]" + "Puppet::Face[#{name.inspect}, #{version.inspect}]" end end diff --git a/lib/puppet/interface/face_collection.rb b/lib/puppet/interface/face_collection.rb index e4eb22fa3..591471d4b 100644 --- a/lib/puppet/interface/face_collection.rb +++ b/lib/puppet/interface/face_collection.rb @@ -1,131 +1,131 @@ # -*- coding: utf-8 -*- require 'puppet/interface' module Puppet::Interface::FaceCollection SEMVER_VERSION = /^(\d+)\.(\d+)\.(\d+)([A-Za-z][0-9A-Za-z-]*|)$/ @faces = Hash.new { |hash, key| hash[key] = {} } def self.faces unless @loaded @loaded = true $LOAD_PATH.each do |dir| next unless FileTest.directory?(dir) Dir.chdir(dir) do - Dir.glob("puppet/faces/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| + Dir.glob("puppet/face/*.rb").collect { |f| f.sub(/\.rb/, '') }.each do |file| iname = file.sub(/\.rb/, '') begin require iname rescue Exception => detail puts detail.backtrace if Puppet[:trace] raise "Could not load #{iname} from #{dir}/#{file}: #{detail}" end end end end end return @faces.keys end def self.validate_version(version) !!(SEMVER_VERSION =~ version.to_s) end def self.cmp_semver(a, b) a, b = [a, b].map do |x| parts = SEMVER_VERSION.match(x).to_a[1..4] parts[0..2] = parts[0..2].map { |e| e.to_i } parts end cmp = a[0..2] <=> b[0..2] if cmp == 0 cmp = a[3] <=> b[3] cmp = +1 if a[3].empty? && !b[3].empty? cmp = -1 if b[3].empty? && !a[3].empty? end cmp end def self.[](name, version) @faces[underscorize(name)][version] if face?(name, version) end def self.face?(name, version) name = underscorize(name) # Note: be careful not to accidentally create the top level key, either, # because it will result in confusion when people try to enumerate the # list of valid faces later. --daniel 2011-04-11 return true if @faces.has_key?(name) and @faces[name].has_key?(version) # We always load the current version file; the common case is that we have # the expected version and any compatibility versions in the same file, # the default. Which means that this is almost always the case. # # We use require to avoid executing the code multiple times, like any # other Ruby library that we might want to use. --daniel 2011-04-06 begin - require "puppet/faces/#{name}" + require "puppet/face/#{name}" # If we wanted :current, we need to index to find that; direct version # requests just work™ as they go. --daniel 2011-04-06 if version == :current then # We need to find current out of this. This is the largest version # number that doesn't have a dedicated on-disk file present; those # represent "experimental" versions of faces, which we don't fully # support yet. # # We walk the versions from highest to lowest and take the first version # that is not defined in an explicitly versioned file on disk as the # current version. # # This constrains us to only ship experimental versions with *one* # version in the file, not multiple, but given you can't reliably load # them except by side-effect when you ignore that rule this seems safe # enough... # # Given those constraints, and that we are not going to ship a versioned # interface that is not :current in this release, we are going to leave # these thoughts in place, and just punt on the actual versioning. # # When we upgrade the core to support multiple versions we can solve the # problems then; as lazy as possible. # # We do support multiple versions in the same file, though, so we sort # versions here and return the last item in that set. # # --daniel 2011-04-06 latest_ver = @faces[name].keys.sort {|a, b| cmp_semver(a, b) }.last @faces[name][:current] = @faces[name][latest_ver] end rescue LoadError => e - raise unless e.message =~ %r{-- puppet/faces/#{name}$} + raise unless e.message =~ %r{-- puppet/face/#{name}$} # ...guess we didn't find the file; return a much better problem. end # Now, either we have the version in our set of faces, or we didn't find # the version they were looking for. In the future we will support # loading versioned stuff from some look-aside part of the Ruby load path, # but we don't need that right now. # # So, this comment is a place-holder for that. --daniel 2011-04-06 # # Note: be careful not to accidentally create the top level key, either, # because it will result in confusion when people try to enumerate the # list of valid faces later. --daniel 2011-04-11 return !! (@faces.has_key?(name) and @faces[name].has_key?(version)) end def self.register(face) @faces[underscorize(face.name)][face.version] = face end def self.underscorize(name) unless name.to_s =~ /^[-_a-z]+$/i then raise ArgumentError, "#{name.inspect} (#{name.class}) is not a valid face name" end name.to_s.downcase.split(/[-_]/).join('_').to_sym end end diff --git a/lib/puppet/util/command_line.rb b/lib/puppet/util/command_line.rb index fa462ee2d..a884b8658 100644 --- a/lib/puppet/util/command_line.rb +++ b/lib/puppet/util/command_line.rb @@ -1,112 +1,112 @@ require "puppet/util/plugins" module Puppet module Util class CommandLine LegacyName = Hash.new{|h,k| k}.update( 'agent' => 'puppetd', 'cert' => 'puppetca', 'doc' => 'puppetdoc', 'filebucket' => 'filebucket', 'apply' => 'puppet', 'describe' => 'pi', 'queue' => 'puppetqd', 'resource' => 'ralsh', 'kick' => 'puppetrun', 'master' => 'puppetmasterd' ) def initialize(zero = $0, argv = ARGV, stdin = STDIN) @zero = zero @argv = argv.dup @stdin = stdin @subcommand_name, @args = subcommand_and_args(@zero, @argv, @stdin) Puppet::Plugins.on_commandline_initialization(:command_line_object => self) end attr :subcommand_name attr :args def appdir File.join('puppet', 'application') end def self.available_subcommands absolute_appdirs = $LOAD_PATH.collect do |x| File.join(x,'puppet','application') end.select{ |x| File.directory?(x) } absolute_appdirs.inject([]) do |commands, dir| commands + Dir[File.join(dir, '*.rb')].map{|fn| File.basename(fn, '.rb')} end.uniq end # available_subcommands was previously an instance method, not a class # method, and we have an unknown number of user-implemented applications # that depend on that behaviour. Forwarding allows us to preserve a # backward compatible API. --daniel 2011-04-11 def available_subcommands self.class.available_subcommands end def require_application(application) require File.join(appdir, application) end def execute if subcommand_name and available_subcommands.include?(subcommand_name) then require_application subcommand_name app = Puppet::Application.find(subcommand_name).new(self) Puppet::Plugins.on_application_initialization(:appliation_object => self) app.run elsif execute_external_subcommand then # Logically, we shouldn't get here, but we do, so whatever. We just # return to the caller. How strange we are. --daniel 2011-04-11 else unless subcommand_name.nil? then puts "Error: Unknown Puppet subcommand #{subcommand_name}.\n" end # Doing this at the top of the file is natural, but causes puppet.rb # to load too early, which causes things to break. This is a nasty # thing, found in #7065. --daniel 2011-04-11 - require 'puppet/faces/help' - puts Puppet::Faces[:help, :current].help + require 'puppet/face' + puts Puppet::Face[:help, :current].help end end def execute_external_subcommand external_command = "puppet-#{subcommand_name}" require 'puppet/util' path_to_subcommand = Puppet::Util.which(external_command) return false unless path_to_subcommand system(path_to_subcommand, *args) true end def legacy_executable_name LegacyName[ subcommand_name ] end private def subcommand_and_args(zero, argv, stdin) zero = File.basename(zero, '.rb') if zero == 'puppet' case argv.first when nil; [ stdin.tty? ? nil : "apply", argv] # ttys get usage info when "--help", "-h"; [nil, argv] # help should give you usage, not the help for `puppet apply` when /^-|\.pp$|\.rb$/; ["apply", argv] else [ argv.first, argv[1..-1] ] end else [ zero, argv ] end end end end end diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb index 9d0e0a715..cec8a57d9 100644 --- a/lib/puppet/util/selinux.rb +++ b/lib/puppet/util/selinux.rb @@ -1,216 +1,216 @@ -# Provides utility functions to help interfaces Puppet to SELinux. +# Provides utility functions to help interface Puppet to SELinux. # # This requires the very new SELinux Ruby bindings. These bindings closely # mirror the SELinux C library interface. # # Support for the command line tools is not provided because the performance # was abysmal. At this time (2008-11-02) the only distribution providing # these Ruby SELinux bindings which I am aware of is Fedora (in libselinux-ruby). Puppet.features.selinux? # check, but continue even if it's not require 'pathname' module Puppet::Util::SELinux def selinux_support? return false unless defined?(Selinux) if Selinux.is_selinux_enabled == 1 return true end false end # Retrieve and return the full context of the file. If we don't have # SELinux support or if the SELinux call fails then return nil. def get_selinux_current_context(file) return nil unless selinux_support? retval = Selinux.lgetfilecon(file) if retval == -1 return nil end retval[1] end # Retrieve and return the default context of the file. If we don't have # SELinux support or if the SELinux call fails to file a default then return nil. def get_selinux_default_context(file) return nil unless selinux_support? # If the filesystem has no support for SELinux labels, return a default of nil # instead of what matchpathcon would return return nil unless selinux_label_support?(file) # If the file exists we should pass the mode to matchpathcon for the most specific # matching. If not, we can pass a mode of 0. begin filestat = File.lstat(file) mode = filestat.mode rescue Errno::ENOENT mode = 0 end retval = Selinux.matchpathcon(file, mode) if retval == -1 return nil end retval[1] end # Take the full SELinux context returned from the tools and parse it # out to the three (or four) component parts. Supports :seluser, :selrole, # :seltype, and on systems with range support, :selrange. def parse_selinux_context(component, context) if context.nil? or context == "unlabeled" return nil end unless context =~ /^([a-z0-9_]+):([a-z0-9_]+):([a-zA-Z0-9_]+)(?::([a-zA-Z0-9:,._-]+))?/ raise Puppet::Error, "Invalid context to parse: #{context}" end ret = { :seluser => $1, :selrole => $2, :seltype => $3, :selrange => $4, } ret[component] end # This updates the actual SELinux label on the file. You can update # only a single component or update the entire context. # The caveat is that since setting a partial context makes no sense the # file has to already exist. Puppet (via the File resource) will always # just try to set components, even if all values are specified by the manifest. # I believe that the OS should always provide at least a fall-through context # though on any well-running system. def set_selinux_context(file, value, component = false) return nil unless selinux_support? && selinux_label_support?(file) if component # Must first get existing context to replace a single component context = Selinux.lgetfilecon(file)[1] if context == -1 # We can't set partial context components when no context exists # unless/until we can find a way to make Puppet call this method # once for all selinux file label attributes. Puppet.warning "Can't set SELinux context on file unless the file already has some kind of context" return nil end context = context.split(':') case component when :seluser context[0] = value when :selrole context[1] = value when :seltype context[2] = value when :selrange context[3] = value else raise ArguementError, "set_selinux_context component must be one of :seluser, :selrole, :seltype, or :selrange" end context = context.join(':') else context = value end retval = Selinux.lsetfilecon(file, context) if retval == 0 return true else Puppet.warning "Failed to set SELinux context #{context} on #{file}" return false end end # Since this call relies on get_selinux_default_context it also needs a # full non-relative path to the file. Fortunately, that seems to be all # Puppet uses. This will set the file's SELinux context to the policy's # default context (if any) if it differs from the context currently on # the file. def set_selinux_default_context(file) new_context = get_selinux_default_context(file) return nil unless new_context cur_context = get_selinux_current_context(file) if new_context != cur_context set_selinux_context(file, new_context) return new_context end nil end # Internal helper function to read and parse /proc/mounts def read_mounts mounts = "" begin if File.instance_methods.include? "read_nonblock" # If possible we use read_nonblock in a loop rather than read to work- # a linux kernel bug. See ticket #1963 for details. mountfh = File.open("/proc/mounts") mounts += mountfh.read_nonblock(1024) while true else # Otherwise we shell out and let cat do it for us mountfh = IO.popen("/bin/cat /proc/mounts") mounts = mountfh.read end rescue EOFError # that's expected rescue return nil ensure mountfh.close if mountfh end mntpoint = {} # Read all entries in /proc/mounts. The second column is the # mountpoint and the third column is the filesystem type. # We skip rootfs because it is always mounted at / mounts.collect do |line| params = line.split(' ') next if params[2] == 'rootfs' mntpoint[params[1]] = params[2] end mntpoint end def realpath(path) path, rest = Pathname.new(path), [] path, rest = path.dirname, [path.basename] + rest while ! path.exist? File.join( path.realpath, *rest ) end def parent_directory(path) Pathname.new(path).dirname.to_s end # Internal helper function to return which type of filesystem a # given file path resides on def find_fs(path) unless mnts = read_mounts return nil end # For a given file: # Check if the filename is in the data structure; # return the fstype if it is. # Just in case: return something if you're down to "/" or "" # Remove the last slash and everything after it, # and repeat with that as the file for the next loop through. path = realpath(path) while not path.empty? return mnts[path] if mnts.has_key?(path) path = parent_directory(path) end mnts['/'] end # Check filesystem a path resides on for SELinux support against # whitelist of known-good filesystems. # Returns true if the filesystem can support SELinux labels and # false if not. def selinux_label_support?(file) fstype = find_fs(file) return false if fstype.nil? filesystems = ['ext2', 'ext3', 'ext4', 'gfs', 'gfs2', 'xfs', 'jfs'] filesystems.include?(fstype) end end diff --git a/spec/lib/puppet/face/basetest.rb b/spec/lib/puppet/face/basetest.rb new file mode 100644 index 000000000..00616f74f --- /dev/null +++ b/spec/lib/puppet/face/basetest.rb @@ -0,0 +1 @@ +Puppet::Face.define(:basetest, '0.0.1') diff --git a/spec/lib/puppet/faces/huzzah.rb b/spec/lib/puppet/face/huzzah.rb similarity index 59% rename from spec/lib/puppet/faces/huzzah.rb rename to spec/lib/puppet/face/huzzah.rb index e86730250..3428c6816 100644 --- a/spec/lib/puppet/faces/huzzah.rb +++ b/spec/lib/puppet/face/huzzah.rb @@ -1,5 +1,5 @@ -require 'puppet/faces' -Puppet::Faces.define(:huzzah, '2.0.1') do +require 'puppet/face' +Puppet::Face.define(:huzzah, '2.0.1') do summary "life is a thing for celebration" action :bar do "is where beer comes from" end end diff --git a/spec/lib/puppet/faces/basetest.rb b/spec/lib/puppet/faces/basetest.rb deleted file mode 100644 index d20c52b97..000000000 --- a/spec/lib/puppet/faces/basetest.rb +++ /dev/null @@ -1 +0,0 @@ -Puppet::Faces.define(:basetest, '0.0.1') diff --git a/spec/unit/application/config_spec.rb b/spec/unit/application/config_spec.rb index 0c1279630..fb224eac6 100755 --- a/spec/unit/application/config_spec.rb +++ b/spec/unit/application/config_spec.rb @@ -1,10 +1,10 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/application/config' describe Puppet::Application::Config do - it "should be a subclass of Puppet::Application::FacesBase" do - Puppet::Application::Config.superclass.should equal(Puppet::Application::FacesBase) + it "should be a subclass of Puppet::Application::FaceBase" do + Puppet::Application::Config.superclass.should equal(Puppet::Application::FaceBase) end end diff --git a/spec/unit/application/faces_base_spec.rb b/spec/unit/application/face_base_spec.rb similarity index 91% rename from spec/unit/application/faces_base_spec.rb rename to spec/unit/application/face_base_spec.rb index 18bd30295..d09e00a32 100755 --- a/spec/unit/application/faces_base_spec.rb +++ b/spec/unit/application/face_base_spec.rb @@ -1,188 +1,188 @@ #!/usr/bin/env rspec require 'spec_helper' -require 'puppet/application/faces_base' +require 'puppet/application/face_base' require 'tmpdir' -class Puppet::Application::FacesBase::Basetest < Puppet::Application::FacesBase +class Puppet::Application::FaceBase::Basetest < Puppet::Application::FaceBase end -describe Puppet::Application::FacesBase do +describe Puppet::Application::FaceBase do before :all do - Puppet::Faces.define(:basetest, '0.0.1') do + Puppet::Face.define(:basetest, '0.0.1') do option("--[no-]boolean") option("--mandatory MANDATORY") option("--optional [OPTIONAL]") action :foo do option("--action") when_invoked { |*args| args.length } end end end let :app do - app = Puppet::Application::FacesBase::Basetest.new + app = Puppet::Application::FaceBase::Basetest.new app.command_line.stubs(:subcommand_name).returns('subcommand') Puppet::Util::Log.stubs(:newdestination) app end describe "#find_global_settings_argument" do it "should not match --ca to --ca-location" do option = mock('ca option', :optparse_args => ["--ca"]) Puppet.settings.expects(:each).yields(:ca, option) app.find_global_settings_argument("--ca-location").should be_nil end end describe "#parse_options" do before :each do app.command_line.stubs(:args).returns %w{} end describe "parsing the command line" do context "with just an action" do before :all do # We have to stub Signal.trap to avoid a crazy mess where we take # over signal handling and make it impossible to cancel the test # suite run. # # It would be nice to fix this elsewhere, but it is actually hard to # capture this in rspec 2.5 and all. :( --daniel 2011-04-08 Signal.stubs(:trap) app.command_line.stubs(:args).returns %w{foo} app.preinit app.parse_options end - it "should set the faces based on the type" do + it "should set the face based on the type" do app.face.name.should == :basetest end - it "should set the format based on the faces default" do + it "should set the format based on the face default" do app.format.should == :pson end it "should find the action" do app.action.should be app.action.name.should == :foo end end it "should fail if no action is given" do expect { app.preinit; app.parse_options }. to raise_error OptionParser::MissingArgument, /No action given/ end it "should report a sensible error when options with = fail" do app.command_line.stubs(:args).returns %w{--action=bar foo} expect { app.preinit; app.parse_options }. to raise_error OptionParser::InvalidOption, /invalid option: --action/ end it "should fail if an action option is before the action" do app.command_line.stubs(:args).returns %w{--action foo} expect { app.preinit; app.parse_options }. to raise_error OptionParser::InvalidOption, /invalid option: --action/ end it "should fail if an unknown option is before the action" do app.command_line.stubs(:args).returns %w{--bar foo} expect { app.preinit; app.parse_options }. to raise_error OptionParser::InvalidOption, /invalid option: --bar/ end it "should fail if an unknown option is after the action" do app.command_line.stubs(:args).returns %w{foo --bar} expect { app.preinit; app.parse_options }. to raise_error OptionParser::InvalidOption, /invalid option: --bar/ end it "should accept --bar as an argument to a mandatory option after action" do app.command_line.stubs(:args).returns %w{foo --mandatory --bar} app.preinit app.parse_options app.action.name.should == :foo app.options.should == { :mandatory => "--bar" } end it "should accept --bar as an argument to a mandatory option before action" do app.command_line.stubs(:args).returns %w{--mandatory --bar foo} app.preinit app.parse_options app.action.name.should == :foo app.options.should == { :mandatory => "--bar" } end it "should not skip when --foo=bar is given" do app.command_line.stubs(:args).returns %w{--mandatory=bar --bar foo} expect { app.preinit; app.parse_options }. to raise_error OptionParser::InvalidOption, /invalid option: --bar/ end { "boolean options before" => %w{--trace foo}, "boolean options after" => %w{foo --trace} }.each do |name, args| it "should accept global boolean settings #{name} the action" do app.command_line.stubs(:args).returns args app.preinit app.parse_options Puppet[:trace].should be_true end end { "before" => %w{--syslogfacility user1 foo}, " after" => %w{foo --syslogfacility user1} }.each do |name, args| it "should accept global settings with arguments #{name} the action" do app.command_line.stubs(:args).returns args app.preinit app.parse_options Puppet[:syslogfacility].should == "user1" end end end end describe "#setup" do it "should remove the action name from the arguments" do app.command_line.stubs(:args).returns %w{--mandatory --bar foo} app.preinit app.parse_options app.setup app.arguments.should == [{ :mandatory => "--bar" }] end it "should pass positional arguments" do app.command_line.stubs(:args).returns %w{--mandatory --bar foo bar baz quux} app.preinit app.parse_options app.setup app.arguments.should == ['bar', 'baz', 'quux', { :mandatory => "--bar" }] end end describe "#main" do before :each do app.expects(:exit).with(0) - app.face = Puppet::Faces[:basetest, '0.0.1'] + app.face = Puppet::Face[:basetest, '0.0.1'] app.action = app.face.get_action(:foo) app.format = :pson app.arguments = ["myname", "myarg"] end - it "should send the specified verb and name to the faces" do + it "should send the specified verb and name to the face" do app.face.expects(:foo).with(*app.arguments) app.main end it "should use its render method to render any result" do app.expects(:render).with(app.arguments.length + 1) app.stubs(:puts) # meh. Don't print nil, thanks. --daniel 2011-04-12 app.main end end end diff --git a/spec/unit/application/faces_spec.rb b/spec/unit/application/faces_spec.rb index c4d15a297..9b6f073f5 100755 --- a/spec/unit/application/faces_spec.rb +++ b/spec/unit/application/faces_spec.rb @@ -1,16 +1,15 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/application/faces' describe Puppet::Application::Faces do it "should be an application" do Puppet::Application::Faces.superclass.should equal(Puppet::Application) end it "should always call 'list'" do - faces = Puppet::Application::Faces.new - faces.expects(:list) - faces.main + subject.expects(:list) + subject.main end end diff --git a/spec/unit/application/indirection_base_spec.rb b/spec/unit/application/indirection_base_spec.rb index 98eb3a118..9aac36860 100755 --- a/spec/unit/application/indirection_base_spec.rb +++ b/spec/unit/application/indirection_base_spec.rb @@ -1,39 +1,39 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/application/indirection_base' -require 'puppet/faces/indirector' +require 'puppet/face/indirector' ######################################################################## # Stub for testing; the names are critical, sadly. --daniel 2011-03-30 class Puppet::Application::TestIndirection < Puppet::Application::IndirectionBase end -face = Puppet::Faces::Indirector.define(:testindirection, '0.0.1') do +face = Puppet::Face::Indirector.define(:testindirection, '0.0.1') do end # REVISIT: This horror is required because we don't allow anything to be # :current except for if it lives on, and is loaded from, disk. --daniel 2011-03-29 face.instance_variable_set('@version', :current) -Puppet::Faces.register(face) +Puppet::Face.register(face) ######################################################################## describe Puppet::Application::IndirectionBase do subject { Puppet::Application::TestIndirection.new } it "should accept a terminus command line option" do # It would be nice not to have to stub this, but whatever... writing an # entire indirection stack would cause us more grief. --daniel 2011-03-31 terminus = mock("test indirection terminus") Puppet::Indirector::Indirection.expects(:instance). with(:testindirection).twice.returns() subject.command_line. instance_variable_set('@args', %w{--terminus foo save}) # Not a very nice thing. :( $stderr.stubs(:puts) expect { subject.run }.should raise_error SystemExit end end diff --git a/spec/unit/face/catalog_spec.rb b/spec/unit/face/catalog_spec.rb new file mode 100755 index 000000000..28c2aa9be --- /dev/null +++ b/spec/unit/face/catalog_spec.rb @@ -0,0 +1,4 @@ +require 'puppet/face' +describe Puppet::Face[:catalog, '0.0.1'] do + it "should actually have some testing..." +end diff --git a/spec/unit/face/certificate_request_spec.rb b/spec/unit/face/certificate_request_spec.rb new file mode 100755 index 000000000..a83a92df8 --- /dev/null +++ b/spec/unit/face/certificate_request_spec.rb @@ -0,0 +1,3 @@ +describe Puppet::Face[:certificate_request, '0.0.1'] do + it "should actually have some tests..." +end diff --git a/spec/unit/face/certificate_revocation_list_spec.rb b/spec/unit/face/certificate_revocation_list_spec.rb new file mode 100755 index 000000000..22c0fa2bf --- /dev/null +++ b/spec/unit/face/certificate_revocation_list_spec.rb @@ -0,0 +1,3 @@ +describe Puppet::Face[:certificate_revocation_list, '0.0.1'] do + it "should actually have some tests..." +end diff --git a/spec/unit/faces/certificate_spec.rb b/spec/unit/face/certificate_spec.rb similarity index 74% rename from spec/unit/faces/certificate_spec.rb rename to spec/unit/face/certificate_spec.rb index ba264f967..dbcc888ad 100755 --- a/spec/unit/faces/certificate_spec.rb +++ b/spec/unit/face/certificate_spec.rb @@ -1,14 +1,14 @@ require 'puppet/ssl/host' -describe Puppet::Faces[:certificate, '0.0.1'] do +describe Puppet::Face[:certificate, '0.0.1'] do it "should have a ca-location option" do subject.should be_option :ca_location end it "should set the ca location when invoked" do - pending "#6983: This is broken in the actual faces..." + pending "#6983: This is broken in the actual face..." Puppet::SSL::Host.expects(:ca_location=).with(:foo) Puppet::SSL::Host.indirection.expects(:save) subject.sign :ca_location => :foo end end diff --git a/spec/unit/faces/config_spec.rb b/spec/unit/face/config_spec.rb similarity index 94% rename from spec/unit/faces/config_spec.rb rename to spec/unit/face/config_spec.rb index b71995e9f..3657b9abd 100755 --- a/spec/unit/faces/config_spec.rb +++ b/spec/unit/face/config_spec.rb @@ -1,24 +1,24 @@ #!/usr/bin/env ruby require 'spec_helper' -describe Puppet::Faces[:config, '0.0.1'] do +describe Puppet::Face[:config, '0.0.1'] do it "should use Settings#print_config_options when asked to print" do Puppet.settings.stubs(:puts) Puppet.settings.expects(:print_config_options) subject.print end it "should set 'configprint' to all desired values and call print_config_options when a specific value is provided" do Puppet.settings.stubs(:puts) Puppet.settings.expects(:print_config_options) subject.print("libdir", "ssldir") Puppet.settings[:configprint].should == "libdir,ssldir" end it "should always return nil" do Puppet.settings.stubs(:puts) Puppet.settings.expects(:print_config_options) subject.print("libdir").should be_nil end end diff --git a/spec/unit/faces/configurer_spec.rb b/spec/unit/face/configurer_spec.rb similarity index 94% rename from spec/unit/faces/configurer_spec.rb rename to spec/unit/face/configurer_spec.rb index 6982c00ae..a404c926f 100755 --- a/spec/unit/faces/configurer_spec.rb +++ b/spec/unit/face/configurer_spec.rb @@ -1,26 +1,26 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/indirector/catalog/rest' require 'tempfile' -describe Puppet::Faces[:configurer, '0.0.1'] do +describe Puppet::Face[:configurer, '0.0.1'] do describe "#synchronize" do it "should retrieve and apply a catalog and return a report" do pending "REVISIT: 2.7 changes broke this, and we want the merge published" dirname = Dir.mktmpdir("puppetdir") Puppet[:vardir] = dirname Puppet[:confdir] = dirname @catalog = Puppet::Resource::Catalog.new @file = Puppet::Resource.new(:file, File.join(dirname, "tmp_dir_resource"), :parameters => {:ensure => :present}) @catalog.add_resource(@file) Puppet::Resource::Catalog::Rest.any_instance.stubs(:find).returns(@catalog) report = subject.synchronize("foo") report.kind.should == "apply" report.status.should == "changed" end end end diff --git a/spec/unit/faces/facts_spec.rb b/spec/unit/face/facts_spec.rb similarity index 90% rename from spec/unit/faces/facts_spec.rb rename to spec/unit/face/facts_spec.rb index 46496a839..f574ac741 100755 --- a/spec/unit/faces/facts_spec.rb +++ b/spec/unit/face/facts_spec.rb @@ -1,21 +1,21 @@ #!/usr/bin/env ruby require 'spec_helper' -describe Puppet::Faces[:facts, '0.0.1'] do +describe Puppet::Face[:facts, '0.0.1'] do it "should define an 'upload' fact" do subject.should be_action(:upload) end it "should set its default format to :yaml" do subject.default_format.should == :yaml end describe "when uploading" do it "should set the terminus_class to :facter" it "should set the cach_eclass to :rest" it "should find the current certname" end end diff --git a/spec/unit/faces/file_spec.rb b/spec/unit/face/file_spec.rb similarity index 52% rename from spec/unit/faces/file_spec.rb rename to spec/unit/face/file_spec.rb index fcb52c67e..97e8bcc08 100755 --- a/spec/unit/faces/file_spec.rb +++ b/spec/unit/face/file_spec.rb @@ -1,3 +1,3 @@ -describe Puppet::Faces[:file, '0.0.1'] do +describe Puppet::Face[:file, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/faces/help_spec.rb b/spec/unit/face/help_spec.rb similarity index 81% rename from spec/unit/faces/help_spec.rb rename to spec/unit/face/help_spec.rb index cd74a5bf1..e67f29e07 100644 --- a/spec/unit/faces/help_spec.rb +++ b/spec/unit/face/help_spec.rb @@ -1,112 +1,112 @@ require 'spec_helper' -require 'puppet/faces/help' +require 'puppet/face/help' -describe Puppet::Faces[:help, '0.0.1'] do +describe Puppet::Face[:help, '0.0.1'] do it "should have a help action" do subject.should be_action :help end it "should have a default action of help" do pending "REVISIT: we don't support default actions yet" end it "should accept a call with no arguments" do expect { subject.help() }.should_not raise_error end it "should accept a face name" do expect { subject.help(:help) }.should_not raise_error end it "should accept a face and action name" do expect { subject.help(:help, :help) }.should_not raise_error end it "should fail if more than a face and action are given" do expect { subject.help(:help, :help, :for_the_love_of_god) }. should raise_error ArgumentError end it "should treat :current and 'current' identically" do subject.help(:help, :version => :current).should == subject.help(:help, :version => 'current') end it "should complain when the request version of a face is missing" do expect { subject.help(:huzzah, :bar, :version => '17.0.0') }. should raise_error Puppet::Error end it "should find a face by version" do - face = Puppet::Faces[:huzzah, :current] + face = Puppet::Face[:huzzah, :current] subject.help(:huzzah, :version => face.version). should == subject.help(:huzzah, :version => :current) end context "when listing subcommands" do - subject { Puppet::Faces[:help, :current].help } + subject { Puppet::Face[:help, :current].help } # Check a precondition for the next block; if this fails you have - # something odd in your set of faces, and we skip testing things that + # something odd in your set of face, and we skip testing things that # matter. --daniel 2011-04-10 it "should have at least one face with a summary" do - Puppet::Faces.faces.should be_any do |name| - Puppet::Faces[name, :current].summary + Puppet::Face.faces.should be_any do |name| + Puppet::Face[name, :current].summary end end - Puppet::Faces.faces.each do |name| - face = Puppet::Faces[name, :current] + Puppet::Face.faces.each do |name| + face = Puppet::Face[name, :current] summary = face.summary it { should =~ %r{ #{name} } } it { should =~ %r{ #{name} +#{summary}} } if summary end - Puppet::Faces[:help, :current].legacy_applications.each do |appname| + Puppet::Face[:help, :current].legacy_applications.each do |appname| it { should =~ %r{ #{appname} } } - summary = Puppet::Faces[:help, :current].horribly_extract_summary_from(appname) + summary = Puppet::Face[:help, :current].horribly_extract_summary_from(appname) summary and it { should =~ %r{ #{summary}\b} } end end context "#legacy_applications" do - subject { Puppet::Faces[:help, :current].legacy_applications } + subject { Puppet::Face[:help, :current].legacy_applications } # If we don't, these tests are ... less than useful, because they assume # it. When this breaks you should consider ditching the entire feature # and tests, but if not work out how to fake one. --daniel 2011-04-11 it { should have_at_least(1).item } # Meh. This is nasty, but we can't control the other list; the specific # bug that caused these to be listed is annoyingly subtle and has a nasty # fix, so better to have a "fail if you do something daft" trigger in # place here, I think. --daniel 2011-04-11 - %w{faces_base indirection_base}.each do |name| + %w{face_base indirection_base}.each do |name| it { should_not include name } end end context "help for legacy applications" do - subject { Puppet::Faces[:help, :current] } + subject { Puppet::Face[:help, :current] } let :appname do subject.legacy_applications.first end # This test is purposely generic, so that as we eliminate legacy commands # we don't get into a loop where we either test a face-based replacement # and fail to notice breakage, or where we have to constantly rewrite this # test and all. --daniel 2011-04-11 it "should return the legacy help when given the subcommand" do help = subject.help(appname) help.should =~ /puppet-#{appname}/ %w{SYNOPSIS USAGE DESCRIPTION OPTIONS COPYRIGHT}.each do |heading| help.should =~ /^#{heading}$/ end end it "should fail when asked for an action on a legacy command" do expect { subject.help(appname, :whatever) }. to raise_error ArgumentError, /Legacy subcommands don't take actions/ end end end diff --git a/spec/unit/faces/indirector_spec.rb b/spec/unit/face/indirector_spec.rb similarity index 72% rename from spec/unit/faces/indirector_spec.rb rename to spec/unit/face/indirector_spec.rb index c1aed9617..269e05543 100755 --- a/spec/unit/faces/indirector_spec.rb +++ b/spec/unit/face/indirector_spec.rb @@ -1,60 +1,60 @@ #!/usr/bin/env ruby require 'spec_helper' -require 'puppet/faces/indirector' +require 'puppet/face/indirector' -describe Puppet::Faces::Indirector do +describe Puppet::Face::Indirector do subject do - instance = Puppet::Faces::Indirector.new(:test, '0.0.1') + instance = Puppet::Face::Indirector.new(:test, '0.0.1') indirection = stub('indirection', :name => :stub_indirection, :reset_terminus_class => nil) instance.stubs(:indirection).returns indirection instance end it "should be able to return a list of indirections" do - Puppet::Faces::Indirector.indirections.should be_include("catalog") + Puppet::Face::Indirector.indirections.should be_include("catalog") end it "should be able to return a list of terminuses for a given indirection" do - Puppet::Faces::Indirector.terminus_classes(:catalog).should be_include("compiler") + Puppet::Face::Indirector.terminus_classes(:catalog).should be_include("compiler") end describe "as an instance" do it "should be able to determine its indirection" do # Loading actions here an get, um, complicated - Puppet::Faces.stubs(:load_actions) - Puppet::Faces::Indirector.new(:catalog, '0.0.1').indirection.should equal(Puppet::Resource::Catalog.indirection) + Puppet::Face.stubs(:load_actions) + Puppet::Face::Indirector.new(:catalog, '0.0.1').indirection.should equal(Puppet::Resource::Catalog.indirection) end end [:find, :search, :save, :destroy].each do |method| it "should define a '#{method}' action" do - Puppet::Faces::Indirector.should be_action(method) + Puppet::Face::Indirector.should be_action(method) end it "should call the indirection method with options when the '#{method}' action is invoked" do subject.indirection.expects(method).with(:test, "myargs", {}) subject.send(method, :test, "myargs") end it "should forward passed options" do subject.indirection.expects(method).with(:test, "action", {'one'=>'1'}) subject.send(method, :test, 'action', {'one'=>'1'}) end end it "should be able to override its indirection name" do subject.set_indirection_name :foo subject.indirection_name.should == :foo end it "should be able to set its terminus class" do subject.indirection.expects(:terminus_class=).with(:myterm) subject.set_terminus(:myterm) end it "should define a class-level 'info' action" do - Puppet::Faces::Indirector.should be_action(:info) + Puppet::Face::Indirector.should be_action(:info) end end diff --git a/spec/unit/faces/key_spec.rb b/spec/unit/face/key_spec.rb similarity index 52% rename from spec/unit/faces/key_spec.rb rename to spec/unit/face/key_spec.rb index 9b7a58706..10d664790 100755 --- a/spec/unit/faces/key_spec.rb +++ b/spec/unit/face/key_spec.rb @@ -1,3 +1,3 @@ -describe Puppet::Faces[:key, '0.0.1'] do +describe Puppet::Face[:key, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/faces/node_spec.rb b/spec/unit/face/node_spec.rb similarity index 77% rename from spec/unit/faces/node_spec.rb rename to spec/unit/face/node_spec.rb index c6ed71f59..d27f41b56 100755 --- a/spec/unit/faces/node_spec.rb +++ b/spec/unit/face/node_spec.rb @@ -1,9 +1,9 @@ #!/usr/bin/env ruby require 'spec_helper' -describe Puppet::Faces[:node, '0.0.1'] do +describe Puppet::Face[:node, '0.0.1'] do it "should set its default format to :yaml" do subject.default_format.should == :yaml end end diff --git a/spec/unit/faces/report_spec.rb b/spec/unit/face/report_spec.rb similarity index 51% rename from spec/unit/faces/report_spec.rb rename to spec/unit/face/report_spec.rb index 30897d5e7..b1b28167e 100755 --- a/spec/unit/faces/report_spec.rb +++ b/spec/unit/face/report_spec.rb @@ -1,3 +1,3 @@ -describe Puppet::Faces[:report, '0.0.1'] do +describe Puppet::Face[:report, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/faces/resource_spec.rb b/spec/unit/face/resource_spec.rb similarity index 50% rename from spec/unit/faces/resource_spec.rb rename to spec/unit/face/resource_spec.rb index e3f2e1c62..084e2a6a9 100755 --- a/spec/unit/faces/resource_spec.rb +++ b/spec/unit/face/resource_spec.rb @@ -1,3 +1,3 @@ -describe Puppet::Faces[:resource, '0.0.1'] do +describe Puppet::Face[:resource, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/face/resource_type_spec.rb b/spec/unit/face/resource_type_spec.rb new file mode 100755 index 000000000..2adaedca1 --- /dev/null +++ b/spec/unit/face/resource_type_spec.rb @@ -0,0 +1,3 @@ +describe Puppet::Face[:resource_type, '0.0.1'] do + it "should actually have some tests..." +end diff --git a/spec/unit/faces_spec.rb b/spec/unit/face_spec.rb similarity index 100% rename from spec/unit/faces_spec.rb rename to spec/unit/face_spec.rb diff --git a/spec/unit/faces/catalog_spec.rb b/spec/unit/faces/catalog_spec.rb deleted file mode 100755 index e0a771d10..000000000 --- a/spec/unit/faces/catalog_spec.rb +++ /dev/null @@ -1,4 +0,0 @@ -require 'puppet/faces' -describe Puppet::Faces[:catalog, '0.0.1'] do - it "should actually have some testing..." -end diff --git a/spec/unit/faces/certificate_request_spec.rb b/spec/unit/faces/certificate_request_spec.rb deleted file mode 100755 index 1a71a8379..000000000 --- a/spec/unit/faces/certificate_request_spec.rb +++ /dev/null @@ -1,3 +0,0 @@ -describe Puppet::Faces[:certificate_request, '0.0.1'] do - it "should actually have some tests..." -end diff --git a/spec/unit/faces/certificate_revocation_list_spec.rb b/spec/unit/faces/certificate_revocation_list_spec.rb deleted file mode 100755 index 4f41edef6..000000000 --- a/spec/unit/faces/certificate_revocation_list_spec.rb +++ /dev/null @@ -1,3 +0,0 @@ -describe Puppet::Faces[:certificate_revocation_list, '0.0.1'] do - it "should actually have some tests..." -end diff --git a/spec/unit/faces/resource_type_spec.rb b/spec/unit/faces/resource_type_spec.rb deleted file mode 100755 index fcbf07520..000000000 --- a/spec/unit/faces/resource_type_spec.rb +++ /dev/null @@ -1,3 +0,0 @@ -describe Puppet::Faces[:resource_type, '0.0.1'] do - it "should actually have some tests..." -end diff --git a/spec/unit/interface/face_collection_spec.rb b/spec/unit/interface/face_collection_spec.rb index 752871035..6ba35b4b2 100755 --- a/spec/unit/interface/face_collection_spec.rb +++ b/spec/unit/interface/face_collection_spec.rb @@ -1,181 +1,170 @@ #!/usr/bin/env ruby require 'spec_helper' require 'tmpdir' require 'puppet/interface/face_collection' describe Puppet::Interface::FaceCollection do # To avoid cross-pollution we have to save and restore both the hash # containing all the interface data, and the array used by require. Restoring # both means that we don't leak side-effects across the code. --daniel 2011-04-06 # # Worse luck, we *also* need to flush $" of anything defining a face, # because otherwise we can cross-pollute from other test files and end up # with no faces loaded, but the require value set true. --daniel 2011-04-10 before :each do @original_faces = subject.instance_variable_get("@faces").dup @original_required = $".dup - $".delete_if do |path| path =~ %r{/faces/.*\.rb$} end + $".delete_if do |path| path =~ %r{/face/.*\.rb$} end subject.instance_variable_get("@faces").clear end after :each do subject.instance_variable_set("@faces", @original_faces) $".clear ; @original_required.each do |item| $" << item end end describe "::faces" do it "REVISIT: should have some tests here, if we describe it" end describe "::validate_version" do it 'should permit three number versions' do subject.validate_version('10.10.10').should == true end it 'should permit versions with appended descriptions' do subject.validate_version('10.10.10beta').should == true end it 'should not permit versions with more than three numbers' do subject.validate_version('1.2.3.4').should == false end it 'should not permit versions with only two numbers' do subject.validate_version('10.10').should == false end it 'should not permit versions with only one number' do subject.validate_version('123').should == false end it 'should not permit versions with text in any position but at the end' do subject.validate_version('v1.1.1').should == false end end describe "::[]" do before :each do subject.instance_variable_get("@faces")[:foo]['0.0.1'] = 10 end - before :each do - @dir = Dir.mktmpdir - @lib = FileUtils.mkdir_p(File.join @dir, 'puppet', 'faces') - $LOAD_PATH.push(@dir) - end - - after :each do - FileUtils.remove_entry_secure @dir - $LOAD_PATH.pop - end - - it "should return the faces with the given name" do + it "should return the face with the given name" do subject["foo", '0.0.1'].should == 10 end - it "should attempt to load the faces if it isn't found" do - subject.expects(:require).with('puppet/faces/bar') + it "should attempt to load the face if it isn't found" do + subject.expects(:require).with('puppet/face/bar') subject["bar", '0.0.1'] end - it "should attempt to load the default faces for the specified version :current" do - subject.expects(:require).with('puppet/faces/fozzie') + it "should attempt to load the default face for the specified version :current" do + subject.expects(:require).with('puppet/face/fozzie') subject['fozzie', :current] end end describe "::face?" do - it "should return true if the faces specified is registered" do + it "should return true if the face specified is registered" do subject.instance_variable_get("@faces")[:foo]['0.0.1'] = 10 subject.face?("foo", '0.0.1').should == true end - it "should attempt to require the faces if it is not registered" do + it "should attempt to require the face if it is not registered" do subject.expects(:require).with do |file| subject.instance_variable_get("@faces")[:bar]['0.0.1'] = true - file == 'puppet/faces/bar' + file == 'puppet/face/bar' end subject.face?("bar", '0.0.1').should == true end - it "should return true if requiring the faces registered it" do + it "should return true if requiring the face registered it" do subject.stubs(:require).with do subject.instance_variable_get("@faces")[:bar]['0.0.1'] = 20 end end - it "should return false if the faces is not registered" do + it "should return false if the face is not registered" do subject.stubs(:require).returns(true) subject.face?("bar", '0.0.1').should be_false end - it "should return false if the faces file itself is missing" do + it "should return false if the face file itself is missing" do subject.stubs(:require). - raises(LoadError, 'no such file to load -- puppet/faces/bar') + raises(LoadError, 'no such file to load -- puppet/face/bar') subject.face?("bar", '0.0.1').should be_false end it "should register the version loaded by `:current` as `:current`" do subject.expects(:require).with do |file| - subject.instance_variable_get("@faces")[:huzzah]['2.0.1'] = :huzzah_faces - file == 'puppet/faces/huzzah' + subject.instance_variable_get("@faces")[:huzzah]['2.0.1'] = :huzzah_face + file == 'puppet/face/huzzah' end subject.face?("huzzah", :current) - subject.instance_variable_get("@faces")[:huzzah][:current].should == :huzzah_faces + subject.instance_variable_get("@faces")[:huzzah][:current].should == :huzzah_face end context "with something on disk" do - it "should register the version loaded from `puppet/faces/{name}` as `:current`" do + it "should register the version loaded from `puppet/face/{name}` as `:current`" do subject.should be_face "huzzah", '2.0.1' subject.should be_face "huzzah", :current - Puppet::Faces[:huzzah, '2.0.1'].should == Puppet::Faces[:huzzah, :current] + Puppet::Face[:huzzah, '2.0.1'].should == Puppet::Face[:huzzah, :current] end it "should index :current when the code was pre-required" do subject.instance_variable_get("@faces")[:huzzah].should_not be_key :current - require 'puppet/faces/huzzah' + require 'puppet/face/huzzah' subject.face?(:huzzah, :current).should be_true end end it "should not cause an invalid face to be enumerated later" do subject.face?(:there_is_no_face, :current).should be_false subject.faces.should_not include :there_is_no_face end end describe "::register" do - it "should store the faces by name" do - faces = Puppet::Faces.new(:my_faces, '0.0.1') - subject.register(faces) - subject.instance_variable_get("@faces").should == {:my_faces => {'0.0.1' => faces}} + it "should store the face by name" do + face = Puppet::Face.new(:my_face, '0.0.1') + subject.register(face) + subject.instance_variable_get("@faces").should == {:my_face => {'0.0.1' => face}} end end describe "::underscorize" do faulty = [1, "#foo", "$bar", "sturm und drang", :"sturm und drang"] valid = { "Foo" => :foo, :Foo => :foo, "foo_bar" => :foo_bar, :foo_bar => :foo_bar, "foo-bar" => :foo_bar, :"foo-bar" => :foo_bar, } valid.each do |input, expect| it "should map #{input.inspect} to #{expect.inspect}" do result = subject.underscorize(input) result.should == expect end end faulty.each do |input| it "should fail when presented with #{input.inspect} (#{input.class})" do expect { subject.underscorize(input) }. should raise_error ArgumentError, /not a valid face name/ end end end end diff --git a/spec/unit/interface_spec.rb b/spec/unit/interface_spec.rb index 7e6b7de77..2365d5cac 100755 --- a/spec/unit/interface_spec.rb +++ b/spec/unit/interface_spec.rb @@ -1,185 +1,185 @@ require 'spec_helper' -require 'puppet/faces' +require 'puppet/face' require 'puppet/interface' describe Puppet::Interface do subject { Puppet::Interface } before :all do @faces = Puppet::Interface::FaceCollection.instance_variable_get("@faces").dup end before :each do Puppet::Interface::FaceCollection.instance_variable_get("@faces").clear end after :all do Puppet::Interface::FaceCollection.instance_variable_set("@faces", @faces) end describe "#[]" do it "should fail when no version is requested" do expect { subject[:huzzah] }.should raise_error ArgumentError end it "should raise an exception when the requested version is unavailable" do expect { subject[:huzzah, '17.0.0'] }.should raise_error, Puppet::Error end it "should raise an exception when the requested face doesn't exist" do expect { subject[:burrble_toot, :current] }.should raise_error, Puppet::Error end end describe "#define" do it "should register the face" do face = subject.define(:face_test_register, '0.0.1') face.should == subject[:face_test_register, '0.0.1'] end it "should load actions" do subject.any_instance.expects(:load_actions) subject.define(:face_test_load_actions, '0.0.1') end it "should require a version number" do expect { subject.define(:no_version) }.to raise_error ArgumentError end it "should support summary builder and accessor methods" do subject.new(:foo, '1.0.0').should respond_to(:summary).with(0).arguments subject.new(:foo, '1.0.0').should respond_to(:summary=).with(1).arguments end it "should set the summary text" do text = "hello, freddy, my little pal" subject.define(:face_test_summary, '1.0.0') do summary text end subject[:face_test_summary, '1.0.0'].summary.should == text end it "should support mutating the summary" do text = "hello, freddy, my little pal" subject.define(:face_test_summary, '1.0.0') do summary text end subject[:face_test_summary, '1.0.0'].summary.should == text subject[:face_test_summary, '1.0.0'].summary = text + text subject[:face_test_summary, '1.0.0'].summary.should == text + text end end describe "#initialize" do it "should require a version number" do expect { subject.new(:no_version) }.to raise_error ArgumentError end it "should require a valid version number" do expect { subject.new(:bad_version, 'Rasins') }. should raise_error ArgumentError end it "should instance-eval any provided block" do face = subject.new(:face_test_block, '0.0.1') do action(:something) do when_invoked { "foo" } end end face.something.should == "foo" end end it "should have a name" do subject.new(:me, '0.0.1').name.should == :me end it "should stringify with its own name" do subject.new(:me, '0.0.1').to_s.should =~ /\bme\b/ end it "should allow overriding of the default format" do face = subject.new(:me, '0.0.1') face.set_default_format :foo face.default_format.should == :foo end it "should default to :pson for its format" do subject.new(:me, '0.0.1').default_format.should == :pson end # Why? it "should create a class-level autoloader" do subject.autoloader.should be_instance_of(Puppet::Util::Autoload) end it "should try to require faces that are not known" do pending "mocking require causes random stack overflow" - subject::FaceCollection.expects(:require).with "puppet/faces/foo" + subject::FaceCollection.expects(:require).with "puppet/face/foo" subject[:foo, '0.0.1'] end it "should be able to load all actions in all search paths" it_should_behave_like "things that declare options" do def add_options_to(&block) subject.new(:with_options, '0.0.1', &block) end end describe "with face-level options" do it "should not return any action-level options" do face = subject.new(:with_options, '0.0.1') do option "--foo" option "--bar" action :baz do option "--quux" end end face.options.should =~ [:foo, :bar] end it "should fail when a face option duplicates an action option" do expect { subject.new(:action_level_options, '0.0.1') do action :bar do option "--foo" end option "--foo" end }.should raise_error ArgumentError, /Option foo conflicts with existing option foo on/i end it "should work when two actions have the same option" do face = subject.new(:with_options, '0.0.1') do action :foo do option "--quux" end action :bar do option "--quux" end end face.get_action(:foo).options.should =~ [:quux] face.get_action(:bar).options.should =~ [:quux] end end describe "with inherited options" do let :face do parent = Class.new(subject) parent.option("--inherited") face = parent.new(:example, '0.2.1') face.option("--local") face end describe "#options" do it "should list inherited options" do face.options.should =~ [:inherited, :local] end end describe "#get_option" do it "should return an inherited option object" do face.get_option(:inherited).should be_an_instance_of subject::Option end end end end diff --git a/spec/unit/util/command_line_spec.rb b/spec/unit/util/command_line_spec.rb index 6cf90475b..b0c2a85ae 100755 --- a/spec/unit/util/command_line_spec.rb +++ b/spec/unit/util/command_line_spec.rb @@ -1,143 +1,143 @@ #!/usr/bin/env ruby require 'spec_helper' require 'puppet/util/command_line' describe Puppet::Util::CommandLine do include PuppetSpec::Files before do @tty = stub("tty", :tty? => true ) @pipe = stub("pipe", :tty? => false) end it "should pull off the first argument if it looks like a subcommand" do command_line = Puppet::Util::CommandLine.new("puppet", %w{ client --help whatever.pp }, @tty ) command_line.subcommand_name.should == "client" command_line.args.should == %w{ --help whatever.pp } end it "should use 'apply' if the first argument looks like a .pp file" do command_line = Puppet::Util::CommandLine.new("puppet", %w{ whatever.pp }, @tty ) command_line.subcommand_name.should == "apply" command_line.args.should == %w{ whatever.pp } end it "should use 'apply' if the first argument looks like a .rb file" do command_line = Puppet::Util::CommandLine.new("puppet", %w{ whatever.rb }, @tty ) command_line.subcommand_name.should == "apply" command_line.args.should == %w{ whatever.rb } end it "should use 'apply' if the first argument looks like a flag" do command_line = Puppet::Util::CommandLine.new("puppet", %w{ --debug }, @tty ) command_line.subcommand_name.should == "apply" command_line.args.should == %w{ --debug } end it "should use 'apply' if the first argument is -" do command_line = Puppet::Util::CommandLine.new("puppet", %w{ - }, @tty ) command_line.subcommand_name.should == "apply" command_line.args.should == %w{ - } end it "should return nil if the first argument is --help" do command_line = Puppet::Util::CommandLine.new("puppet", %w{ --help }, @tty ) command_line.subcommand_name.should == nil end it "should return nil if there are no arguments on a tty" do command_line = Puppet::Util::CommandLine.new("puppet", [], @tty ) command_line.subcommand_name.should == nil command_line.args.should == [] end it "should use 'apply' if there are no arguments on a pipe" do command_line = Puppet::Util::CommandLine.new("puppet", [], @pipe ) command_line.subcommand_name.should == "apply" command_line.args.should == [] end it "should return the executable name if it is not puppet" do command_line = Puppet::Util::CommandLine.new("puppetmasterd", [], @tty ) command_line.subcommand_name.should == "puppetmasterd" end it "should translate subcommand names into their legacy equivalent" do command_line = Puppet::Util::CommandLine.new("puppet", ["master"], @tty) command_line.legacy_executable_name.should == "puppetmasterd" end it "should leave legacy command names alone" do command_line = Puppet::Util::CommandLine.new("puppetmasterd", [], @tty) command_line.legacy_executable_name.should == "puppetmasterd" end describe "when the subcommand is not implemented" do it "should find and invoke an executable with a hyphenated name" do commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument'], @tty) Puppet::Util.expects(:which).with('puppet-whatever').returns('/dev/null/puppet-whatever') commandline.expects(:system).with('/dev/null/puppet-whatever', 'argument') commandline.execute end describe "and an external implementation cannot be found" do it "should abort and show the usage message" do commandline = Puppet::Util::CommandLine.new("puppet", ['whatever', 'argument'], @tty) Puppet::Util.expects(:which).with('puppet-whatever').returns(nil) commandline.expects(:system).never - text = Puppet::Faces[:help, :current].help + text = Puppet::Face[:help, :current].help commandline.expects(:puts).with { |x| x =~ /Unknown Puppet subcommand/ } commandline.expects(:puts).with text commandline.execute end end end describe 'when loading commands' do before do @core_apps = %w{describe filebucket kick queue resource agent cert apply doc master} @command_line = Puppet::Util::CommandLine.new("foo", %w{ client --help whatever.pp }, @tty ) end it "should expose available_subcommands as a class method" do @core_apps.each do |command| @command_line.available_subcommands.should include command end end it 'should be able to find all existing commands' do @core_apps.each do |command| @command_line.available_subcommands.should include command end end describe 'when multiple paths have applications' do before do @dir=tmpdir('command_line_plugin_test') @appdir="#{@dir}/puppet/application" FileUtils.mkdir_p(@appdir) FileUtils.touch("#{@appdir}/foo.rb") $LOAD_PATH.unshift(@dir) # WARNING: MUST MATCH THE AFTER ACTIONS! end it 'should be able to find commands from both paths' do found = @command_line.available_subcommands found.should include 'foo' @core_apps.each { |cmd| found.should include cmd } end after do $LOAD_PATH.shift # WARNING: MUST MATCH THE BEFORE ACTIONS! end end end end