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



220
221
222
223
224
# File 'lib/deputy.rb', line 220

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

.configObject



164
165
166
167
168
169
170
# File 'lib/deputy.rb', line 164

def self.config
  home = File.expand_path('~')
  ["#{home}/.deputy.yml", '/etc/deputy.yml'].each do |file|
    return YAML.load(File.read(file)) if File.exist?(file)
  end
  raise "No deputy.yml found in /etc or #{home}"
end

.extract_auth_from_url!(url) ⇒ Object



214
215
216
217
218
# File 'lib/deputy.rb', line 214

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
# 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))

  Timeout.timeout(config['timeout']||10) do
    open(url, options).read
  end
rescue Exception => e
  e.message << url.to_s
  unless config['silent_on_errors'] 
    raise e
  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



172
173
174
175
176
# File 'lib/deputy.rb', line 172

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

.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")

  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



185
186
187
188
189
190
# File 'lib/deputy.rb', line 185

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



160
161
162
# File 'lib/deputy.rb', line 160

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

.sleep_random_intervalObject



178
179
180
181
182
183
# File 'lib/deputy.rb', line 178

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