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, Help, IndirectionBase, Man, Module, Parser, Plugin, Secret_agent
Constant Summary
Constants inherited from Puppet::Application
DOCPATTERN, SHOULD_PARSE_CONFIG_DEPRECATION_MSG
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
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, 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, should_not_parse_config, should_parse_config, should_parse_config?, stop!, stop_requested?, try_load_class
Methods included from Util
absolute_path?, activerecord_version, benchmark, binread, chuser, classproxy, deterministic_rand, execfail, execpipe, execute, exit_on_fail, logmethods, memory, path_to_uri, pretty_backtrace, proxy, replace_file, safe_posix_fork, symbolizehash, thinmark, 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
19 20 21 |
# File 'lib/puppet/application/face_base.rb', line 19 def action @action end |
#arguments ⇒ Object
19 20 21 |
# File 'lib/puppet/application/face_base.rb', line 19 def arguments @arguments end |
#render_as ⇒ Object
19 20 21 |
# File 'lib/puppet/application/face_base.rb', line 19 def render_as @render_as end |
Instance Method Details
#find_application_argument(item) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/puppet/application/face_base.rb', line 145 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
133 134 135 136 137 138 139 140 141 142 143 |
# File 'lib/puppet/application/face_base.rb', line 133 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
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 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 |
# File 'lib/puppet/application/face_base.rb', line 185 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 #{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 s = arity == 2 ? '' : 's' raise ArgumentError, "puppet #{@face.name} #{@action.name} takes #{arity-1} argument#{s}, but you gave #{count-1}" end 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.name} #{@action.name}' for usage" ensure exit status end |
#parse_options ⇒ Object
54 55 56 57 58 59 60 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 |
# File 'lib/puppet/application/face_base.rb', line 54 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 face = @face.name action = action_name.nil? ? 'default' : "'#{action_name}'" msg = "'#{face}' has no #{action} action. See `puppet help #{face}`." 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 |option| option = @action.get_option(option) # make it the object. self.class.option(*option.optparse) # ...and make the CLI parse it. end # ...and invoke our parent to parse all the command line options. super end |
#preinit ⇒ Object
46 47 48 49 50 51 52 |
# File 'lib/puppet/application/face_base.rb', line 46 def preinit super Signal.trap(:INT) do $stderr.puts "Cancelling Face" exit(0) end end |
#render(result, args_and_options) ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/puppet/application/face_base.rb', line 30 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
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/puppet/application/face_base.rb', line 160 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 |