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