class Puppet::Application::FaceBase

Attributes

action[RW]
arguments[RW]
face[RW]
render_as[RW]
type[RW]

Public Instance Methods

find_application_argument(item) click to toggle source
    # File lib/puppet/application/face_base.rb
167 def find_application_argument(item)
168   self.class.option_parser_commands.each do |options, function|
169     options.each do |option|
170       next unless option =~ /^-/
171       pattern = /^#{option.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/
172       next unless pattern.match(item)
173       return {
174         :argument => option =~ /[ =]/,
175         :optional => option =~ /[ =]\[/
176       }
177     end
178   end
179   return nil                  # not found
180 end
find_global_settings_argument(item) click to toggle source
    # File lib/puppet/application/face_base.rb
155 def find_global_settings_argument(item)
156   Puppet.settings.each do |name, object|
157     object.optparse_args.each do |arg|
158       next unless arg =~ /^-/
159       # sadly, we have to emulate some of optparse here...
160       pattern = /^#{arg.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/
161       pattern.match item and return object
162     end
163   end
164   return nil                  # nothing found.
165 end
main() click to toggle source
    # File lib/puppet/application/face_base.rb
207 def main
208   status = false
209 
210   # Call the method associated with the provided action (e.g., 'find').
211   unless @action
212     puts Puppet::Face[:help, :current].help(@face.name)
213     raise _("%{face} does not respond to action %{arg}") % { face: face, arg: arguments.first }
214   end
215 
216   # We need to do arity checking here because this is generic code
217   # calling generic methods – that have argument defaulting.  We need to
218   # make sure we don't accidentally pass the options as the first
219   # argument to a method that takes one argument.  eg:
220   #
221   #   puppet facts find
222   #   => options => {}
223   #      @arguments => [{}]
224   #   => @face.send :bar, {}
225   #
226   #   def face.bar(argument, options = {})
227   #   => bar({}, {})  # oops!  we thought the options were the
228   #                   # positional argument!!
229   #
230   # We could also fix this by making it mandatory to pass the options on
231   # every call, but that would make the Ruby API much more annoying to
232   # work with; having the defaulting is a much nicer convention to have.
233   #
234   # We could also pass the arguments implicitly, by having a magic
235   # 'options' method that was visible in the scope of the action, which
236   # returned the right stuff.
237   #
238   # That sounds attractive, but adds complications to all sorts of
239   # things, especially when you think about how to pass options when you
240   # are writing Ruby code that calls multiple faces.  Especially if
241   # faces are involved in that. ;)
242   #
243   # --daniel 2011-04-27
244   if (arity = @action.positional_arg_count) > 0
245     unless (count = arguments.length) == arity then
246       raise ArgumentError, n_("puppet %{face} %{action} takes %{arg_count} argument, but you gave %{given_count}", "puppet %{face} %{action} takes %{arg_count} arguments, but you gave %{given_count}", arity - 1) % { face: @face.name, action: @action.name, arg_count: arity-1, given_count: count-1 }
247     end
248   end
249 
250   if @face.deprecated?
251     Puppet.deprecation_warning(_("'puppet %{face}' is deprecated and will be removed in a future release") % { face: @face.name })
252   end
253 
254   result = @face.send(@action.name, *arguments)
255   puts render(result, arguments) unless result.nil?
256   status = true
257 
258 # We need an easy way for the action to set a specific exit code, so we
259 # rescue SystemExit here; This allows each action to set the desired exit
260 # code by simply calling Kernel::exit.  eg:
261 #
262 #   exit(2)
263 #
264 # --kelsey 2012-02-14
265 rescue SystemExit => detail
266   status = detail.status
267 
268 rescue => detail
269   Puppet.log_exception(detail)
270   Puppet.err _("Try 'puppet help %{face} %{action}' for usage") % { face: @face.name, action: @action.name }
271 
272 ensure
273   exit status
274 end
parse_options() click to toggle source
Calls superclass method Puppet::Application#parse_options
    # File lib/puppet/application/face_base.rb
 61 def parse_options
 62   # We need to parse enough of the command line out early, to identify what
 63   # the action is, so that we can obtain the full set of options to parse.
 64 
 65   # REVISIT: These should be configurable versions, through a global
 66   # '--version' option, but we don't implement that yet... --daniel 2011-03-29
 67   @type = Puppet::Util::ConstantInflector.constant2file(self.class.name.to_s.sub(/.+:/, '')).to_sym
 68   @face = Puppet::Face[@type, :current]
 69 
 70   # Now, walk the command line and identify the action.  We skip over
 71   # arguments based on introspecting the action and all, and find the first
 72   # non-option word to use as the action.
 73   action_name = nil
 74   index       = -1
 75   until action_name or (index += 1) >= command_line.args.length do
 76     item = command_line.args[index]
 77     if item =~ /^-/
 78       option = @face.options.find do |name|
 79         item =~ /^-+#{name.to_s.gsub(/[-_]/, '[-_]')}(?:[ =].*)?$/
 80       end
 81       if option
 82         option = @face.get_option(option)
 83         # If we have an inline argument, just carry on.  We don't need to
 84         # care about optional vs mandatory in that case because we do a real
 85         # parse later, and that will totally take care of raising the error
 86         # when we get there. --daniel 2011-04-04
 87         if option.takes_argument? and !item.index('=')
 88           index += 1 unless
 89             (option.optional_argument? and command_line.args[index + 1] =~ /^-/)
 90         end
 91       else
 92         option = find_global_settings_argument(item)
 93         if option
 94           unless Puppet.settings.boolean? option.name
 95             # As far as I can tell, we treat non-bool options as always having
 96             # a mandatory argument. --daniel 2011-04-05
 97             # ... But, the mandatory argument will not be the next item if an = is
 98             # employed in the long form of the option. --jeffmccune 2012-09-18
 99             index += 1 unless item =~ /^--#{option.name}=/
100           end
101         else 
102           option = find_application_argument(item)
103           if option
104             index += 1 if (option[:argument] and not option[:optional])
105           else
106             raise OptionParser::InvalidOption.new(item.sub(/=.*$/, ''))
107           end
108         end
109       end
110     else
111       # Stash away the requested action name for later, and try to fetch the
112       # action object it represents; if this is an invalid action name that
113       # will be nil, and handled later.
114       action_name = item.to_sym
115       @action = Puppet::Face.find_action(@face.name, action_name)
116       @face   = @action.face if @action
117     end
118   end
119 
120   if @action.nil?
121     @action = @face.get_default_action()
122     if @action
123       @is_default_action = true
124     else
125       # First try to handle global command line options
126       # But ignoring invalid options as this is a invalid action, and
127       # we want the error message for that instead.
128       begin
129         super
130       rescue OptionParser::InvalidOption
131       end
132 
133       face   = @face.name
134       action = action_name.nil? ? 'default' : "'#{action_name}'"
135       msg = _("'%{face}' has no %{action} action.  See `puppet help %{face}`.") % { face: face, action: action }
136 
137       Puppet.err(msg)
138       Puppet::Util::Log.force_flushqueue()
139 
140       exit false
141     end
142   end
143 
144   # Now we can interact with the default option code to build behaviour
145   # around the full set of options we now know we support.
146   @action.options.each do |o|
147     o = @action.get_option(o) # make it the object.
148     self.class.option(*o.optparse) # ...and make the CLI parse it.
149   end
150 
151   # ...and invoke our parent to parse all the command line options.
152   super
153 end
preinit() click to toggle source
Calls superclass method Puppet::Application#preinit
   # File lib/puppet/application/face_base.rb
53 def preinit
54   super
55   Signal.trap(:INT) do
56     $stderr.puts _("Cancelling Face")
57     exit(0)
58   end
59 end
render(result, args_and_options) click to toggle source
   # File lib/puppet/application/face_base.rb
37 def render(result, args_and_options)
38   hook = action.when_rendering(render_as.name)
39 
40   if hook
41     # when defining when_rendering on your action you can optionally
42     # include arguments and options
43     if hook.arity > 1
44       result = hook.call(result, *args_and_options)
45     else
46       result = hook.call(result)
47     end
48   end
49 
50   render_as.render(result)
51 end
render_as=(format) click to toggle source
   # File lib/puppet/application/face_base.rb
32 def render_as=(format)
33   @render_as = Puppet::Network::FormatHandler.format(format)
34   @render_as or raise ArgumentError, _("I don't know how to render '%{format}'") % { format: format }
35 end
setup() click to toggle source
    # File lib/puppet/application/face_base.rb
182 def setup
183   Puppet::Util::Log.newdestination :console
184 
185   @arguments = command_line.args
186 
187   # Note: because of our definition of where the action is set, we end up
188   # with it *always* being the first word of the remaining set of command
189   # line arguments.  So, strip that off when we construct the arguments to
190   # pass down to the face action. --daniel 2011-04-04
191   # Of course, now that we have default actions, we should leave the
192   # "action" name on if we didn't actually consume it when we found our
193   # action.
194   @arguments.delete_at(0) unless @is_default_action
195 
196   # We copy all of the app options to the end of the call; This allows each
197   # action to read in the options.  This replaces the older model where we
198   # would invoke the action with options set as global state in the
199   # interface object.  --daniel 2011-03-28
200   @arguments << options
201 
202   # If we don't have a rendering format, set one early.
203   self.render_as ||= (@action.render_as || :console)
204 end