diff --git a/lib/puppet/interface/option.rb b/lib/puppet/interface/option.rb index f4c56cb2c..3d3840ff6 100644 --- a/lib/puppet/interface/option.rb +++ b/lib/puppet/interface/option.rb @@ -1,104 +1,106 @@ +require 'puppet/interface' + class Puppet::Interface::Option def initialize(parent, *declaration, &block) @parent = parent @optparse = [] # Collect and sort the arguments in the declaration. dups = {} declaration.each do |item| if item.is_a? String and item.to_s =~ /^-/ then unless item =~ /^-[a-z]\b/ or item =~ /^--[^-]/ then raise ArgumentError, "#{item.inspect}: long options need two dashes (--)" end @optparse << item # Duplicate checking... name = optparse_to_name(item) if dup = dups[name] then raise ArgumentError, "#{item.inspect}: duplicates existing alias #{dup.inspect} in #{@parent}" else dups[name] = item end else raise ArgumentError, "#{item.inspect} is not valid for an option argument" end end if @optparse.empty? then raise ArgumentError, "No option declarations found while building" end # Now, infer the name from the options; we prefer the first long option as # the name, rather than just the first option. @name = optparse_to_name(@optparse.find do |a| a =~ /^--/ end || @optparse.first) @aliases = @optparse.map { |o| optparse_to_name(o) } # Do we take an argument? If so, are we consistent about it, because # incoherence here makes our life super-difficult, and we can more easily # relax this rule later if we find a valid use case for it. --daniel 2011-03-30 @argument = @optparse.any? { |o| o =~ /[ =]/ } if @argument and not @optparse.all? { |o| o =~ /[ =]/ } then raise ArgumentError, "Option #{@name} is inconsistent about taking an argument" end # Is our argument optional? The rules about consistency apply here, also, # just like they do to taking arguments at all. --daniel 2011-03-30 @optional_argument = @optparse.any? { |o| o=~/[ =]\[/ } @optional_argument and raise ArgumentError, "Options with optional arguments are not supported" if @optional_argument and not @optparse.all? { |o| o=~/[ =]\[/ } then raise ArgumentError, "Option #{@name} is inconsistent about the argument being optional" end end # to_s and optparse_to_name are roughly mirrored, because they are used to # transform options to name symbols, and vice-versa. This isn't a full # bidirectional transformation though. --daniel 2011-04-07 def to_s @name.to_s.tr('_', '-') end def optparse_to_name(declaration) unless found = declaration.match(/^-+(?:\[no-\])?([^ =]+)/) then raise ArgumentError, "Can't find a name in the declaration #{declaration.inspect}" end name = found.captures.first.tr('-', '_') raise "#{name.inspect} is an invalid option name" unless name.to_s =~ /^[a-z]\w*$/ name.to_sym end def takes_argument? !!@argument end def optional_argument? !!@optional_argument end def required? !!@required end attr_reader :parent, :name, :aliases, :optparse attr_accessor :required, :desc attr_accessor :before_action def before_action=(proc) proc.is_a? Proc or raise ArgumentError, "before action hook for #{self} is a #{proc.class.name.inspect}, not a proc" @before_action = @parent.__send__(:__add_method, __decoration_name(:before), proc) end attr_accessor :after_action def after_action=(proc) proc.is_a? Proc or raise ArgumentError, "after action hook for #{self} is a #{proc.class.name.inspect}, not a proc" @after_action = @parent.__send__(:__add_method, __decoration_name(:after), proc) end def __decoration_name(type) if @parent.is_a? Puppet::Interface::Action then :"option #{name} from #{parent.name} #{type} decoration" else :"option #{name} #{type} decoration" end end end diff --git a/spec/unit/face/catalog_spec.rb b/spec/unit/face/catalog_spec.rb index 28c2aa9be..c77a9d153 100755 --- a/spec/unit/face/catalog_spec.rb +++ b/spec/unit/face/catalog_spec.rb @@ -1,4 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' 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 index a83a92df8..e237800ff 100755 --- a/spec/unit/face/certificate_request_spec.rb +++ b/spec/unit/face/certificate_request_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + 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 index 22c0fa2bf..1033df7ff 100755 --- a/spec/unit/face/certificate_revocation_list_spec.rb +++ b/spec/unit/face/certificate_revocation_list_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + describe Puppet::Face[:certificate_revocation_list, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/face/certificate_spec.rb b/spec/unit/face/certificate_spec.rb index b0bbf1af6..0cb905b75 100755 --- a/spec/unit/face/certificate_spec.rb +++ b/spec/unit/face/certificate_spec.rb @@ -1,19 +1,23 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + require 'puppet/ssl/host' 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 Puppet::SSL::Host.expects(:ca_location=).with(:foo) Puppet::SSL::Host.indirection.expects(:save) subject.sign "hello, friend", :ca_location => :foo end it "(#7059) should set the ca location when an inherited action is invoked" do Puppet::SSL::Host.expects(:ca_location=).with(:foo) subject.indirection.expects(:find) subject.find "hello, friend", :ca_location => :foo end end diff --git a/spec/unit/face/config_spec.rb b/spec/unit/face/config_spec.rb index 6004d700f..0c762f2aa 100755 --- a/spec/unit/face/config_spec.rb +++ b/spec/unit/face/config_spec.rb @@ -1,23 +1,24 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'puppet/face' 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/face/facts_spec.rb b/spec/unit/face/facts_spec.rb index 6ab6ad5be..06b229aa1 100755 --- a/spec/unit/face/facts_spec.rb +++ b/spec/unit/face/facts_spec.rb @@ -1,16 +1,17 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'puppet/face' describe Puppet::Face[:facts, '0.0.1'] do it "should define an 'upload' action" do subject.should be_action(:upload) 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/face/file_spec.rb b/spec/unit/face/file_spec.rb index 97e8bcc08..a362923e3 100755 --- a/spec/unit/face/file_spec.rb +++ b/spec/unit/face/file_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + describe Puppet::Face[:file, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/face/help_spec.rb b/spec/unit/face/help_spec.rb index f28c4f273..ef66660ff 100755 --- a/spec/unit/face/help_spec.rb +++ b/spec/unit/face/help_spec.rb @@ -1,128 +1,129 @@ +#!/usr/bin/env rspec require 'spec_helper' -require 'puppet/face/help' +require 'puppet/face' 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 subject.get_action('help').should be_default 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::Face[:huzzah, :current] subject.help(:huzzah, :version => face.version). should == subject.help(:huzzah, :version => :current) end context "when listing subcommands" do subject { Puppet::Face[:help, :current].help } RSpec::Matchers.define :have_a_summary do match do |instance| instance.summary.is_a?(String) end end # Check a precondition for the next block; if this fails you have # 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::Face.faces.should be_any do |name| Puppet::Face[name, :current].summary end end it "should list all faces" do Puppet::Face.faces.each do |name| face = Puppet::Face[name, :current] summary = face.summary subject.should =~ %r{ #{name} } summary and subject.should =~ %r{ #{name} +#{summary}} end end Puppet::Face.faces.each do |name| it "should have a summary for #{name}" do Puppet::Face[name, :current].should have_a_summary end end it "should list all legacy applications" do Puppet::Face[:help, :current].legacy_applications.each do |appname| subject.should =~ %r{ #{appname} } summary = Puppet::Face[:help, :current].horribly_extract_summary_from(appname) summary and subject.should =~ %r{ #{summary}\b} end end end context "#legacy_applications" do 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{face_base indirection_base}.each do |name| it { should_not include name } end end context "help for legacy applications" do 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/face/key_spec.rb b/spec/unit/face/key_spec.rb index 10d664790..7de4c6e76 100755 --- a/spec/unit/face/key_spec.rb +++ b/spec/unit/face/key_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + describe Puppet::Face[:key, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/face/node_spec.rb b/spec/unit/face/node_spec.rb index d19312c58..027a4cce0 100755 --- a/spec/unit/face/node_spec.rb +++ b/spec/unit/face/node_spec.rb @@ -1,6 +1,7 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'puppet/face' describe Puppet::Face[:node, '0.0.1'] do it "REVISIT: really should have some tests" end diff --git a/spec/unit/face/report_spec.rb b/spec/unit/face/report_spec.rb index b1b28167e..befc4e496 100755 --- a/spec/unit/face/report_spec.rb +++ b/spec/unit/face/report_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + describe Puppet::Face[:report, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/face/resource_spec.rb b/spec/unit/face/resource_spec.rb index 084e2a6a9..0671af4c2 100755 --- a/spec/unit/face/resource_spec.rb +++ b/spec/unit/face/resource_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + 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 index 2adaedca1..30a1adfcb 100755 --- a/spec/unit/face/resource_type_spec.rb +++ b/spec/unit/face/resource_type_spec.rb @@ -1,3 +1,7 @@ +#!/usr/bin/env rspec +require 'spec_helper' +require 'puppet/face' + describe Puppet::Face[:resource_type, '0.0.1'] do it "should actually have some tests..." end diff --git a/spec/unit/face/secret_agent_spec.rb b/spec/unit/face/secret_agent_spec.rb index 9117ad44d..beeb4f57b 100755 --- a/spec/unit/face/secret_agent_spec.rb +++ b/spec/unit/face/secret_agent_spec.rb @@ -1,23 +1,24 @@ #!/usr/bin/env rspec require 'spec_helper' +require 'puppet/face' require 'puppet/indirector/catalog/rest' require 'tempfile' describe Puppet::Face[:secret_agent, '0.0.1'] do describe "#synchronize" do it "should retrieve and apply a catalog and return a report" do dirname = Dir.mktmpdir("puppetdir") Puppet[:vardir] = dirname Puppet[:confdir] = dirname @catalog = Puppet::Resource::Catalog.new @file = Puppet::Resource.new(:file, File.join(dirname, "tmp_dir_resource"), :parameters => {:ensure => :present}) @catalog.add_resource(@file) Puppet::Resource::Catalog::Rest.any_instance.stubs(:find).returns(@catalog) report = subject.synchronize("foo") report.kind.should == "apply" report.status.should == "changed" end end end