Class: Puppet::Application::FaceBase
- Inherits:
-
Puppet::Application
- Object
- Puppet::Application
- Puppet::Application::FaceBase
- Defined in:
- lib/puppet/application/face_base.rb
Direct Known Subclasses
Ca, Config, Epp, Generate, Help, IndirectionBase, Man, Module, Parser, Plugin
Constant Summary
Constants inherited from Puppet::Application
Constants included from Util
Util::AbsolutePathPosix, Util::AbsolutePathWindows, Util::DEFAULT_POSIX_MODE, Util::DEFAULT_WINDOWS_MODE
Constants included from Util::POSIX
Util::POSIX::LOCALE_ENV_VARS, Util::POSIX::USER_ENV_VARS
Constants included from Util::SymbolicFileMode
Util::SymbolicFileMode::SetGIDBit, Util::SymbolicFileMode::SetUIDBit, Util::SymbolicFileMode::StickyBit, Util::SymbolicFileMode::SymbolicMode, Util::SymbolicFileMode::SymbolicSpecialToBit
Instance Attribute Summary collapse
-
#action ⇒ Object
Returns the value of attribute action.
-
#arguments ⇒ Object
Returns the value of attribute arguments.
-
#face ⇒ Object
Returns the value of attribute face.
-
#render_as ⇒ Object
Returns the value of attribute render_as.
-
#type ⇒ Object
Returns the value of attribute type.
Attributes inherited from Puppet::Application
Instance Method Summary collapse
- #find_application_argument(item) ⇒ Object
- #find_global_settings_argument(item) ⇒ Object
- #main ⇒ Object
- #parse_options ⇒ Object
- #preinit ⇒ Object
- #render(result, args_and_options) ⇒ Object
- #setup ⇒ Object
Methods inherited from Puppet::Application
[], #app_defaults, available_application_names, banner, clear!, clear?, clear_everything_for_tests, #configure_indirector_routes, controlled_run, #deprecate, #deprecated?, exit, find, #handle_logdest_arg, #handlearg, #help, #initialize, #initialize_app_defaults, interrupted?, #log_runtime_environment, #name, option, option_parser_commands, restart!, restart_requested?, #run, #run_command, run_mode, #set_log_level, #setup_logs, stop!, stop_requested?, #summary, try_load_class
Methods included from Util
absolute_path?, benchmark, chuser, clear_environment, default_env, deterministic_rand, deterministic_rand_int, exit_on_fail, get_env, get_environment, logmethods, merge_environment, path_to_uri, pretty_backtrace, replace_file, safe_posix_fork, set_env, symbolizehash, thinmark, uri_encode, uri_query_encode, uri_to_path, which, withenv, withumask
Methods included from Util::POSIX
#get_posix_field, #gid, #idfield, #methodbyid, #methodbyname, #search_posix_field, #uid
Methods included from Util::SymbolicFileMode
#normalize_symbolic_mode, #symbolic_mode_to_int, #valid_symbolic_mode?
Constructor Details
This class inherits a constructor from Puppet::Application
Instance Attribute Details
#action ⇒ Object
Returns the value of attribute action.
30 31 32 |
# File 'lib/puppet/application/face_base.rb', line 30 def action @action end |
#arguments ⇒ Object
Returns the value of attribute arguments.
30 31 32 |
# File 'lib/puppet/application/face_base.rb', line 30 def arguments @arguments end |
#face ⇒ Object
Returns the value of attribute face.
30 31 32 |
# File 'lib/puppet/application/face_base.rb', line 30 def face @face end |
#render_as ⇒ Object
Returns the value of attribute render_as.
30 31 32 |
# File 'lib/puppet/application/face_base.rb', line 30 def render_as @render_as end |
#type ⇒ Object
Returns the value of attribute type.
30 31 32 |
# File 'lib/puppet/application/face_base.rb', line 30 def type @type end |
Instance Method Details
#find_application_argument(item) ⇒ Object
160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/puppet/application/face_base.rb', line 160 def find_application_argument(item) self.class.option_parser_commands.each do |, function| .each do |option| next unless option =~ /^-/ pattern = /^#{option.sub('[no-]', '').sub(/[ =].*$/, '')}(?:[ =].*)?$/ next unless pattern.match(item) return { :argument => option =~ /[ =]/, :optional => option =~ /[ =]\[/ } end end return nil # not found end |
#find_global_settings_argument(item) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/puppet/application/face_base.rb', line 148 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 |
#main ⇒ Object
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/puppet/application/face_base.rb', line 200 def main status = false # Call the method associated with the provided action (e.g., 'find'). unless @action puts Puppet::Face[:help, :current].help(@face.name) raise _("%{face} does not respond to action %{arg}") % { face: face, arg: arguments.first } end # 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, 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 } end end if @face.deprecated? Puppet.deprecation_warning(_("'puppet %{face}' is deprecated and will be removed in a future release") % { face: @face.name }) end result = @face.send(@action.name, *arguments) puts render(result, arguments) unless result.nil? status = true # We need an easy way for the action to set a specific exit code, so we # rescue SystemExit here; This allows each action to set the desired exit # code by simply calling Kernel::exit. eg: # # exit(2) # # --kelsey 2012-02-14 rescue SystemExit => detail status = detail.status rescue => detail Puppet.log_exception(detail) Puppet.err _("Try 'puppet help %{face} %{action}' for usage") % { face: @face.name, action: @action.name } ensure exit status end |
#parse_options ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/puppet/application/face_base.rb', line 61 def # 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 = Puppet::Util::ConstantInflector.constant2file(self.class.name.to_s.sub(/.+:/, '')).to_sym @face = Puppet::Face[@type, :current] # 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_name = nil index = -1 until action_name or (index += 1) >= command_line.args.length do item = command_line.args[index] if item =~ /^-/ then option = @face..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 # ... But, the mandatory argument will not be the next item if an = is # employed in the long form of the option. --jeffmccune 2012-09-18 index += 1 unless item =~ /^--#{option.name}=/ end elsif option = find_application_argument(item) then index += 1 if (option[:argument] and not option[:optional]) else raise OptionParser::InvalidOption.new(item.sub(/=.*$/, '')) end else # Stash away the requested action name for later, and try to fetch the # action object it represents; if this is an invalid action name that # will be nil, and handled later. action_name = item.to_sym @action = Puppet::Face.find_action(@face.name, action_name) @face = @action.face if @action end end if @action.nil? if @action = @face.get_default_action() then @is_default_action = true else # First try to handle global command line options # But ignoring invalid options as this is a invalid action, and # we want the error message for that instead. begin super rescue OptionParser::InvalidOption end face = @face.name action = action_name.nil? ? 'default' : "'#{action_name}'" msg = _("'%{face}' has no %{action} action. See `puppet help %{face}`.") % { face: face, action: action } Puppet.err(msg) Puppet::Util::Log.force_flushqueue() exit false end 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..each do |o| o = @action.get_option(o) # make it the object. self.class.option(*o.optparse) # ...and make the CLI parse it. end # ...and invoke our parent to parse all the command line options. super end |
#preinit ⇒ Object
53 54 55 56 57 58 59 |
# File 'lib/puppet/application/face_base.rb', line 53 def preinit super Signal.trap(:INT) do $stderr.puts _("Cancelling Face") exit(0) end end |
#render(result, args_and_options) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/puppet/application/face_base.rb', line 37 def render(result, ) hook = action.when_rendering(render_as.name) if hook # when defining when_rendering on your action you can optionally # include arguments and options if hook.arity > 1 result = hook.call(result, *) else result = hook.call(result) end end render_as.render(result) end |
#setup ⇒ Object
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/puppet/application/face_base.rb', line 175 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 # Of course, now that we have default actions, we should leave the # "action" name on if we didn't actually consume it when we found our # action. @arguments.delete_at(0) unless @is_default_action # 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 << # If we don't have a rendering format, set one early. self.render_as ||= (@action.render_as || :console) end |