Module: ScoutAgent::Dispatcher
- Defined in:
- lib/scout_agent/dispatcher.rb
Overview
This is the namespace for the methods that turn a command-line invocation into a command executed by the agent.
Class Method Summary collapse
-
.abort_with_ambiguous_assignment(assignment, matches) ⇒ Object
Abort with an error message to the user that says we matched
assignment
to multiplematches
and we need clarification. -
.abort_with_missing_code(class_name) ⇒ Object
Abort with an error message to the user that warns of a broken command in our system.
-
.abort_with_unknown_assignment(assignment) ⇒ Object
Abort with an error message to the user that says we were unable to match
assignment
to a known command. -
.dispatch(args = ARGV) ⇒ Object
This method handles the command invocation process.
-
.execute_assignment(assignment, code, switches, other_args) ⇒ Object
Requires
code
, loads the Class indicated byassignment
, build an instance passingswitches
andother_args
, then executes the command. -
.load_assignment(assignment) ⇒ Object
Loads the code matching the
assignment
command or dies with an error message if the name cannot be matched. -
.parse_assignment(args) ⇒ Object
Locates the command in
args
. -
.parse_switches(args) ⇒ Object
Removes all supported command-line switches from
args
.
Class Method Details
.abort_with_ambiguous_assignment(assignment, matches) ⇒ Object
Abort with an error message to the user that says we matched assignment
to multiple matches
and we need clarification.
195 196 197 198 199 200 201 |
# File 'lib/scout_agent/dispatcher.rb', line 195 def abort_with_ambiguous_assignment(assignment, matches) choices = matches.map { |m| "'#{File.basename(m, '.rb')}'" } choices[-2..-1] = choices[-2..-1].join(", or ") abort <<-END_AMBIGUOUS.trim Ambiguous command '#{assignment}'. Did you mean #{choices.join(', ')}? END_AMBIGUOUS end |
.abort_with_missing_code(class_name) ⇒ Object
Abort with an error message to the user that warns of a broken command in our system.
215 216 217 |
# File 'lib/scout_agent/dispatcher.rb', line 215 def abort_with_missing_code(class_name) abort "Failed to load '#{class_name}'." end |
.abort_with_unknown_assignment(assignment) ⇒ Object
Abort with an error message to the user that says we were unable to match assignment
to a known command.
207 208 209 |
# File 'lib/scout_agent/dispatcher.rb', line 207 def abort_with_unknown_assignment(assignment) abort "Unknown command '#{assignment}'." end |
.dispatch(args = ARGV) ⇒ Object
This method handles the command invocation process. The passed args
are parsed for switches and command, then the selected code is loaded and run.
18 19 20 21 22 23 |
# File 'lib/scout_agent/dispatcher.rb', line 18 def dispatch(args = ARGV) switches = parse_switches(args) assignment = parse_assignment(args) code = load_assignment(assignment) execute_assignment(assignment, code, switches, args) end |
.execute_assignment(assignment, code, switches, other_args) ⇒ Object
Requires code
, loads the Class indicated by assignment
, build an instance passing switches
and other_args
, then executes the command. This method exits with an error if the code cannot be loaded.
180 181 182 183 184 185 186 187 188 189 |
# File 'lib/scout_agent/dispatcher.rb', line 180 def execute_assignment(assignment, code, switches, other_args) require code class_name = code.basename(".rb").to_s.CamelCase begin loaded = Assignment.const_get(class_name) rescue NameError # can't load module abort_with_missing_code(class_name) end loaded.new(switches, other_args).prepare_and_execute end |
.load_assignment(assignment) ⇒ Object
Loads the code matching the assignment
command or dies with an error message if the name cannot be matched. Returns the loaded code file.
162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/scout_agent/dispatcher.rb', line 162 def load_assignment(assignment) dir = LIB_DIR + "assignment" matches = dir.entries.map { |path| path.to_s }. grep(/#{Regexp.escape(assignment)}\w*\.rb\z/) if matches.size > 1 abort_with_ambiguous_assignment(assignment, matches) elsif matches.first and (code = dir + matches.first).exist? return code else abort_with_unknown_assignment(assignment) end end |
.parse_assignment(args) ⇒ Object
Locates the command in args
. This process aborts with an error message if the given command is malformed. Otherwise the provided name is returned.
If a command is not given, the agent will default "identify"
if not configured, "start"
if not running, or "status"
.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/scout_agent/dispatcher.rb', line 139 def parse_assignment(args) assignment = args.shift.to_s.downcase if assignment.empty? if Plan.present? if IDCard.new(:lifeline).pid_file.exist? return "status" else return "start" end else return "identify" end end unless assignment =~ /\A\w+\z/ abort_with_unknown_assignment(assignment) end assignment end |
.parse_switches(args) ⇒ Object
Removes all supported command-line switches from args
. Each switch sets the corresponding value in the Plan and a Hash of all switches are returned from this method.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 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 |
# File 'lib/scout_agent/dispatcher.rb', line 30 def parse_switches(args) switches = { } args. do |opts| opts. = <<-END_USAGE.trim Usage: [sudo] #{ScoutAgent.agent_name} [OPTIONS] COMMAND Use the commands identify, start, and stop to prepare, launch, and shutdown the agent respectively. Those require super user privileges. You can also use the status command to check in on a running agent. END_USAGE opts.separator "Basic Options:" opts.on( "-s", "--server URL", String, "The URL for the server to report to." ) do |url| switches[:server_url] = url end opts.on( "-p", "--proxy URL", String, "A proxy URL to pass HTTP requests through." ) do |url| switches[:proxy_url] = url end opts.on( "-d", "--[no-]daemon", "Run in the background as a daemon." ) do |boolean| switches[:run_as_daemon] = boolean end opts.on( "-l", "--logging-level LEVEL", %w[DEBUG INFO WARN ERROR FATAL], "The minimum level of log message to record." ) do |level| switches[:logging_level] = level end opts.on( "-x", "--[no-]xmpp", "Allow the server to send XMPP commands." ) do |boolean| switches[:enable_xmpp] = boolean end opts.on( "-t", "--[no-]test-mode", "Used in agent development." ) do |boolean| if switches[:test_mode] = boolean switches[:server_url] = "http://localhost:4567" switches[:run_as_daemon] = false end end opts.separator "Expert Options:" opts.on( "--[no-]periodic-snapshots", "Take regular system snapshots." ) do |boolean| switches[:periodic_snapshots] = boolean end opts.on( "--trusted USER1,USER2,...", Array, "A list of trusted XMPP users." ) do |users| switches[:xmpp_trusted] = users end opts.on( "--users NAME1,NAME2,...", Array, "A list of users to try switching to." ) do |users| switches[:user_choices] = users end opts.on( "--groups NAME1,NAME2,...", Array, "A list of groups to try switching to." ) do |groups| switches[:group_choices] = groups end opts.on( "--prefix PATH", String, "A prefix path prepended to all other paths." ) do |path| switches[:prefix_path] = path end [ %w[os_config_path configuration], %w[os_db_path databases], %w[os_pid_path PID\ files], %w[os_log_path log\ files] ].each do |name, used_for| opts.on( "--#{name.tr('_', '-')} PATH", String, "The path your OS uses for #{used_for}." ) do |path| switches[name.to_sym] = path end end opts.separator "Application Options:" opts.on( "-h", "--help", "Show this message." ) do puts opts # show usage exit end opts.on( "-v", "--version", "Display the current version." ) do puts "#{ScoutAgent.proper_agent_name} v#{ScoutAgent::VERSION}" exit end begin opts.parse! rescue OptionParser::ParseError # failed to parse options puts opts # show usage exit end end # apply switches so paths will be set correctly for load checks Plan.update_from_switches(switches) switches end |