summaryrefslogtreecommitdiffstats
path: root/lib/puppet/application
diff options
context:
space:
mode:
Diffstat (limited to 'lib/puppet/application')
-rw-r--r--lib/puppet/application/face_base.rb45
1 files changed, 44 insertions, 1 deletions
diff --git a/lib/puppet/application/face_base.rb b/lib/puppet/application/face_base.rb
index d02769412..69c3ad5ad 100644
--- a/lib/puppet/application/face_base.rb
+++ b/lib/puppet/application/face_base.rb
@@ -214,12 +214,55 @@ class Puppet::Application::FaceBase < Puppet::Application
# Call the method associated with the provided action (e.g., 'find').
if @action
begin
+ # We need to do arity checking here because this is generic code
+ # calling generic methods – that have argument defaulting. We need to
+ # make sure we don't accidentally pass the options as the first
+ # argument to a method that takes one argument. eg:
+ #
+ # puppet facts find
+ # => options => {}
+ # @arguments => [{}]
+ # => @face.send :bar, {}
+ #
+ # def face.bar(argument, options = {})
+ # => bar({}, {}) # oops! we thought the options were the
+ # # positional argument!!
+ #
+ # We could also fix this by making it mandatory to pass the options on
+ # every call, but that would make the Ruby API much more annoying to
+ # work with; having the defaulting is a much nicer convention to have.
+ #
+ # We could also pass the arguments implicitly, by having a magic
+ # 'options' method that was visible in the scope of the action, which
+ # returned the right stuff.
+ #
+ # That sounds attractive, but adds complications to all sorts of
+ # things, especially when you think about how to pass options when you
+ # are writing Ruby code that calls multiple faces. Especially if
+ # faces are involved in that. ;)
+ #
+ # --daniel 2011-04-27
+ if (arity = @action.positional_arg_count) > 0
+ unless (count = arguments.length) == arity then
+ raise ArgumentError, "wrong number of arguments (#{count} for #{arity})"
+ end
+ end
+
result = @face.send(@action.name, *arguments)
puts render(result) unless result.nil?
status = true
rescue Exception => detail
puts detail.backtrace if Puppet[:trace]
- Puppet.err detail.to_s
+
+ case detail
+ when ArgumentError then
+ got, want = /\((\d+) for (\d+)\)/.match(detail.to_s).to_a.map {|x| x.to_i }
+ Puppet.err "puppet #{@face.name} #{@action.name}: #{want} argument expected but #{got} given"
+ Puppet.err "Try 'puppet help #{@face.name} #{@action.name}' for usage"
+
+ else # generic exception handling, alas.
+ Puppet.err detail.to_s
+ end
end
else
puts "#{face} does not respond to action #{arguments.first}"