Module: Deputy

Defined in:
lib/deputy.rb

Constant Summary collapse

VERSION =
File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
DEFAULT_VALUE =
'OK'
Timeout =

stolen from klarlack – github.com/schoefmax/klarlack to get an reliable timeout that wont fail on other platforms or if sytem_timer is missing

begin
  # Try to use the SystemTimer gem instead of Ruby's timeout library
  # when running on something that looks like Ruby 1.8.x. See:
  # http://ph7spot.com/articles/system_timer
  # We don't want to bother trying to load SystemTimer on jruby and
  # ruby 1.9+.
  if RUBY_VERSION =~ /^1\.8\./ and RUBY_PLATFORM !~ /java/
    require 'system_timer'
    SystemTimer
  else
    require 'timeout'
    Timeout
  end
rescue LoadError => e
  $stderr.puts "Could not load SystemTimer gem, falling back to Ruby's slower/unsafe timeout library: #{e.message}"
  require 'timeout'
  Timeout
end

Class Method Summary collapse

Class Method Details

.add_host_to_url(url, host = nil) ⇒ Object



230
231
232
233
# File 'lib/deputy.rb', line 230

def self.add_host_to_url(url, host=nil)
  query = "hostname=#{host || Socket.gethostname}#{'&forced_host=true' if host}"
  add_query_to_url(url, query)
end

.add_ip_to_url(url, ip = nil) ⇒ Object



236
237
238
239
# File 'lib/deputy.rb', line 236

def self.add_ip_to_url(url, ip=nil)
  query = "ip=#{ip ||real_ip}"
  add_query_to_url(url, query)
end

.add_query_to_url(url, query) ⇒ Object



245
246
247
248
# File 'lib/deputy.rb', line 245

def self.add_query_to_url(url, query)
  separator = (url.include?('?') ? "&" : "?")
  url + separator + query
end

.configObject



173
174
175
176
177
178
179
180
# File 'lib/deputy.rb', line 173

def self.config
  home = File.expand_path('~')
  possible_config_files = ["#{home}/.deputy.yml", '/etc/deputy.yml']
  possible_config_files.each do |file|
    return YAML.load(File.read(file)) if File.exist?(file)
  end
  raise "No configuration file found in " + possible_config_files.join('or') + "\nSee http://github.com/dawanda/deputy for more documentation"
end

.extract_auth_from_url!(url) ⇒ Object



224
225
226
227
228
# File 'lib/deputy.rb', line 224

def self.extract_auth_from_url!(url)
  url.sub!(%r{//(.*?):(.*?)@}, '//')
  auth = [$1, $2].compact
  auth.empty? ? nil : auth
end

.get(path, options = {}) ⇒ Object



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/deputy.rb', line 143

def self.get(path, options = {})
  return if config['disabled']
  url = "#{sheriff_url}#{path}"
  url = "http://#{url}" unless url =~ %r{://}
  options[:http_basic_authentication] = extract_auth_from_url!(url)
  url = add_host_to_url(url, options.delete(:host))
  url = add_ip_to_url(url)
  puts "getting #{url} with options: #{options.inspect}" if options[:verbose]

  http_options = {}
  http_options[:http_basic_authentication] = options[:http_basic_authentication] if options[:http_basic_authentication]

  res = Timeout.timeout(config['timeout']||10) do
    open(url, http_options).read
  end
  puts "result: #{res.inspect}" if options[:verbose]
  res
rescue Exception => e
  e.message << url.to_s
  unless config['silent_on_errors']
    raise e
  else
    puts "caught error: #{e.message} with #{e.backtrace}"
  end
end

.install_cronObject



95
96
97
98
99
100
101
102
103
104
# File 'lib/deputy.rb', line 95

def self.install_cron
  executable = `which deputy`.strip
  unless (`crontab -l`).include?(executable)
    `crontab -l | { cat; echo "* * * * * #{executable} --run-plugins >> /tmp/deputy.log 2>&1"; } | crontab -`
    if executable !~ %r{^/usr/}
      puts "make deputy globally available! or e.g. calls from inside cronjobs do not know deputy"
      puts "sudo ln -s #{executable} /usr/bin/deputy"
    end
  end
end

.minutes_to_wait(start_time, interval) ⇒ Object



182
183
184
185
186
# File 'lib/deputy.rb', line 182

def self.minutes_to_wait(start_time, interval)
  start_minute = start_time / 60
  run_every_n_minutes = interval / 60
  start_minute % run_every_n_minutes
end

.real_ipObject



241
242
243
# File 'lib/deputy.rb', line 241

def self.real_ip
  %x(host $(hostname))[/\d+.\d+.\d+.\d+/]
end

.run_plugins(options = {}) ⇒ Object



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
# File 'lib/deputy.rb', line 106

def self.run_plugins(options={})
  return if config['disabled']
  start_time = Time.now.to_i
  sleep_random_interval unless options[:no_wait]

  content = get("/plugins.rb", options)

  exceptions = []
  Scout.plugins(content).each do |interval, plugin|
    wait = minutes_to_wait(start_time, interval)
    if wait == 0
      puts "#{plugin.clean_class_name}: running"
      begin
        plugin.new.build_report
      rescue Object => e # catch and report plugin-specific errors
        e.message[0..0] = plugin.clean_class_name
        puts e
        exceptions << e
      end
    else
      puts "#{plugin.clean_class_name}: waiting another #{wait} minutes"
    end
  end
  send_report 'Deputies.finished', (exceptions.empty? ? DEFAULT_VALUE : 'Error')

  raise exceptions.first unless exceptions.empty?
rescue Object => e # catch and report neta errors
  send_report "Deputies.Error", e.message
  raise e
end

.seeded_random(max_rand, seed) ⇒ Object



195
196
197
198
199
200
# File 'lib/deputy.rb', line 195

def self.seeded_random(max_rand, seed)
  old = srand(seed)
  result = rand(max_rand)
  srand(old)
  result
end

.send_report(group, value, options = {}) ⇒ Object



137
138
139
140
141
# File 'lib/deputy.rb', line 137

def self.send_report(group, value, options = {})
  return if config['disabled']
  raise "separate #{group} with a ." unless group.split('.',2).size == 2
  get "/notify?group=#{CGI.escape group}&value=#{CGI.escape value.to_s}", options
end

.sheriff_urlObject



169
170
171
# File 'lib/deputy.rb', line 169

def self.sheriff_url
  config['sheriff_url'].sub(%r{/$},'')
end

.sleep_random_intervalObject



188
189
190
191
192
193
# File 'lib/deputy.rb', line 188

def self.sleep_random_interval
  if max = config['max_random_start_delay']
    constant_number = Socket.gethostname.sum{|x| x[0]}
    sleep seeded_random(max, constant_number)
  end
end