Class: WatchmonkeyCli::Application

Inherits:
Object
  • Object
show all
Includes:
Colorize, Configuration::AppHelper, Dispatch, Checker::AppHelper, Helpers
Defined in:
lib/watchmonkey_cli/application.rb,
lib/watchmonkey_cli/application/colorize.rb,
lib/watchmonkey_cli/application/dispatch.rb,
lib/watchmonkey_cli/application/configuration.rb

Defined Under Namespace

Modules: Colorize, Dispatch Classes: Configuration

Constant Summary

Constants included from Colorize

Colorize::COLORMAP

Constants included from Helpers

Helpers::BYTE_UNITS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Checker::AppHelper

#init_checkers!, #start_checkers!, #stop_checkers!

Methods included from Configuration::AppHelper

#config_directory, #config_filename, #config_files, #generate_config, #load_configs!

Methods included from Dispatch

#dispatch, #dispatch_generate_config, #dispatch_help, #dispatch_index, #dispatch_info

Methods included from Colorize

#colorize

Methods included from Helpers

#human_filesize, #human_number

Constructor Details

#initialize(env, argv) {|_self| ... } ⇒ Application

Returns a new instance of Application.

Yields:

  • (_self)

Yield Parameters:



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/watchmonkey_cli/application.rb', line 29

def initialize env, argv
  @env, @argv = env, argv
  @connections = {}
  @hooks = {}
  @monitor = Monitor.new
  @threads = []
  @queue = Queue.new
  @processed = 0
  @running = false
  @opts = {
    dump: false,             # (internal) if true app will dump itself and exit before running any checks
    dispatch: :index,        # (internal) action to dispatch
    check_for_updates: true, # -z flag
    colorize: true,          # -m flag
    debug: false,            # -d flag
    threads: 10,             # -t flag
    loop_forever: false,     # (internal) loop forever (app mode)
    loop_wait_empty: 1,      # (internal) time to wait in thread if queue is empty
    silent: false,           # -s flag
    quiet: false,            # -q flag
  }
  init_params
  yield(self)
end

Instance Attribute Details

#checkersObject (readonly)

Returns the value of attribute checkers.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def checkers
  @checkers
end

#connectionsObject (readonly)

Returns the value of attribute connections.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def connections
  @connections
end

#hooksObject (readonly)

Returns the value of attribute hooks.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def hooks
  @hooks
end

#optsObject (readonly)

Returns the value of attribute opts.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def opts
  @opts
end

#processedObject (readonly)

Returns the value of attribute processed.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def processed
  @processed
end

#queueObject (readonly)

Returns the value of attribute queue.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def queue
  @queue
end

#threadsObject (readonly)

Returns the value of attribute threads.



3
4
5
# File 'lib/watchmonkey_cli/application.rb', line 3

def threads
  @threads
end

Class Method Details

.dispatch(*a) ⇒ Object

Setup =



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/watchmonkey_cli/application.rb', line 13

def self.dispatch *a
  new(*a) do |app|
    app.load_config
    app.parse_params
    begin
      app.dispatch
      app.haltpoint
    rescue Interrupt
      app.abort("Interrupted", 1)
    ensure
      app.fire(:wm_shutdown)
      app.debug "#{Thread.list.length} threads remain..."
    end
  end
end

Instance Method Details

#_queueoffObject



194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/watchmonkey_cli/application.rb', line 194

def _queueoff
  while !@queue.empty? || @opts[:loop_forever]
    break if $wm_runtime_exiting
    item = queue.pop(true) rescue false
    if item
      Thread.current[:working] = true
      fire(:wm_work_start, Thread.current)
      sync { @processed += 1 }
      item[2].call(*item[1])
      Thread.current[:working] = false
      fire(:wm_work_end, Thread.current)
    end
    sleep @opts[:loop_wait_empty] if @opts[:loop_forever] && @opts[:loop_wait_empty] && @queue.empty?
  end
end

#abort(msg, exit_code = 1) ⇒ Object



96
97
98
99
# File 'lib/watchmonkey_cli/application.rb', line 96

def abort msg, exit_code = 1
  puts c("[ABORT] #{msg}", :red)
  exit(exit_code)
end

#close_connections!Object



133
134
135
136
137
# File 'lib/watchmonkey_cli/application.rb', line 133

def close_connections!
  @connections.each do |type, clist|
    clist.each{|id, con| con.close! }
  end
end

#debug(msg) ⇒ Object



92
93
94
# File 'lib/watchmonkey_cli/application.rb', line 92

def debug msg
  puts c("[DEBUG] #{msg}", :black) if @opts[:debug]
end

#dump_and_exit!Object



248
249
250
251
252
253
# File 'lib/watchmonkey_cli/application.rb', line 248

def dump_and_exit!
  puts "   Queue: #{@queue.length}"
  puts " AppOpts: #{@opts}"
  puts "Checkers: #{@checkers.keys.join(",")}"
  exit 9
end

#enqueue(checker, *a, &block) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/watchmonkey_cli/application.rb', line 158

def enqueue checker, *a, &block
  sync do
    cb = block || checker.method(:check!)
    evreg = @disable_event_registration
    fire(:enqueue, checker, a, cb) unless evreg
    @queue << [checker, a, ->(*a) {
      begin
        result = Checker::Result.new(checker, *a)
        checker.debug(result.str_running)
        checker.safe(result.str_safe) { cb.call(result, *a) }
        fire(:result_dump, result, a, checker)
        result.dump!
      ensure
        fire(:dequeue, checker, a) unless evreg
      end
    }]
  end
end

#enqueue_sub(checker, which, *args) ⇒ Object



177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/watchmonkey_cli/application.rb', line 177

def enqueue_sub checker, which, *args
  sync do
    if sec = @checkers[which.to_s]
      begin
        # ef_was = @disable_event_firing
        er_was = @disable_event_registration
        # @disable_event_firing = true
        @disable_event_registration = true
        sec.enqueue(*args)
      ensure
        # @disable_event_firing = ef_was
        @disable_event_registration = er_was
      end
    end
  end
end

#error(msg) ⇒ Object



101
102
103
# File 'lib/watchmonkey_cli/application.rb', line 101

def error msg
  warn c(msg, :red)
end

#fetch_connection(type, id, opts = {}, &initializer) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/watchmonkey_cli/application.rb', line 118

def fetch_connection type, id, opts = {}, &initializer
  if !@connections[type] || !@connections[type][id]
    @connections[type] ||= {}
    case type
    when :loopback
      @connections[type][id] = LoopbackConnection.new(id, opts, &initializer)
    when :ssh
      @connections[type][id] = SshConnection.new(id, opts, &initializer)
    else
      raise NotImplementedError, "unknown connection type `#{type}'!"
    end
  end
  @connections[type][id]
end

#fire(which, *args) ⇒ Object



112
113
114
115
116
# File 'lib/watchmonkey_cli/application.rb', line 112

def fire which, *args
  return if @disable_event_firing
  sync { debug "[Event] Firing #{which} (#{@hooks[which].try(:length) || 0} handlers) #{args.map(&:class)}" }
  @hooks[which] && @hooks[which].each{|h| h.call(*args) }
end

#haltpointObject

Raises:



244
245
246
# File 'lib/watchmonkey_cli/application.rb', line 244

def haltpoint
  raise Interrupt if $wm_runtime_exiting
end

#hook(*which, &hook_block) ⇒ Object



105
106
107
108
109
110
# File 'lib/watchmonkey_cli/application.rb', line 105

def hook *which, &hook_block
  which.each do |w|
    @hooks[w.to_sym] ||= []
    @hooks[w.to_sym] << hook_block
  end
end

#init_paramsObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/watchmonkey_cli/application.rb', line 54

def init_params
  @optparse = OptionParser.new do |opts|
    opts.banner = "Usage: watchmonkey [options]"

    opts.separator(c "# Application options", :blue)
    opts.on("--generate-config [myconfig]", "Generates a example config in ~/.watchmonkey") {|s| @opts[:dispatch] = :generate_config; @opts[:config_name] = s }
    opts.on("-l", "--log [file]", "Log to file, defaults to ~/.watchmonkey/logs/watchmonkey.log") {|s| @opts[:logfile] = s || logger_filename }
    opts.on("-t", "--threads [NUM]", Integer, "Amount of threads to be used for checking (default: 10)") {|s| @opts[:threads] = s }
    opts.on("-s", "--silent", "Only print errors and infos") { @opts[:silent] = true }
    opts.on("-q", "--quiet", "Only print errors") { @opts[:quiet] = true }

    opts.separator("\n" << c("# General options", :blue))
    opts.on("-d", "--debug", "Enable debug output") { @opts[:debug] = true }
    opts.on("-m", "--monochrome", "Don't colorize output") { @opts[:colorize] = false }
    opts.on("-h", "--help", "Shows this help") { @opts[:dispatch] = :help }
    opts.on("-v", "--version", "Shows version and other info") { @opts[:dispatch] = :info }
    opts.on("-z", "Do not check for updates on GitHub (with -v/--version)") { @opts[:check_for_updates] = false }
    opts.on("--dump-core", "for developers") { @opts[:dump] = true }
  end
end

#load_configObject



87
88
89
90
# File 'lib/watchmonkey_cli/application.rb', line 87

def load_config
  return unless File.exist?(wm_cfg_configfile)
  eval File.read(wm_cfg_configfile, encoding: "utf-8"), binding, wm_cfg_configfile
end

#loggerObject



222
223
224
225
226
227
228
229
# File 'lib/watchmonkey_cli/application.rb', line 222

def logger
  sync do
    @logger ||= begin
      FileUtils.mkdir_p(File.dirname(@opts[:logfile]))
      Logger.new(@opts[:logfile], 10, 1024000)
    end
  end
end

#logger_filenameObject



218
219
220
# File 'lib/watchmonkey_cli/application.rb', line 218

def logger_filename
  "#{wm_cfg_path}/logs/watchmonkey.log"
end

#parse_paramsObject



75
76
77
78
79
80
81
# File 'lib/watchmonkey_cli/application.rb', line 75

def parse_params
  @optparse.parse!(@argv)
rescue OptionParser::ParseError => e
  abort(e.message)
  dispatch(:help)
  exit 1
end

#release_signalsObject



239
240
241
242
# File 'lib/watchmonkey_cli/application.rb', line 239

def release_signals
  debug "Releasing INT signal..."
  Signal.trap("INT", "DEFAULT")
end

#running?Boolean

Returns:



83
84
85
# File 'lib/watchmonkey_cli/application.rb', line 83

def running?
  @running
end

#spawn_threads_and_run!Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/watchmonkey_cli/application.rb', line 143

def spawn_threads_and_run!
  if @opts[:threads] > 1
    debug "Spawning #{@opts[:threads]} consumer threads..."
    @opts[:threads].times do
      @threads << Thread.new do
        Thread.current.abort_on_exception = true
        _queueoff
      end
    end
  else
    debug "Running threadless..."
    _queueoff
  end
end

#sync(&block) ⇒ Object



139
140
141
# File 'lib/watchmonkey_cli/application.rb', line 139

def sync &block
  @monitor.synchronize(&block)
end

#trap_signalsObject



231
232
233
234
235
236
237
# File 'lib/watchmonkey_cli/application.rb', line 231

def trap_signals
  debug "Trapping INT signal..."
  Signal.trap("INT") do
    $wm_runtime_exiting = true
    puts "Interrupting..."
  end
end

#wm_cfg_configfileObject



214
215
216
# File 'lib/watchmonkey_cli/application.rb', line 214

def wm_cfg_configfile
  "#{wm_cfg_path}/config.rb"
end

#wm_cfg_pathObject



210
211
212
# File 'lib/watchmonkey_cli/application.rb', line 210

def wm_cfg_path
  ENV["WM_CFGDIR"].presence || File.expand_path("~/.watchmonkey")
end