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



211
212
213
214
215
# File 'lib/deputy.rb', line 211

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



155
156
157
158
159
160
161
# File 'lib/deputy.rb', line 155

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



205
206
207
208
209
# File 'lib/deputy.rb', line 205

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

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



137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/deputy.rb', line 137

def self.get(path, options = {})
  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
  raise e
end

.install_cronObject



91
92
93
94
95
96
97
98
99
100
# File 'lib/deputy.rb', line 91

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



163
164
165
166
167
# File 'lib/deputy.rb', line 163

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



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

def self.run_plugins(options={})
  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



176
177
178
179
180
181
# File 'lib/deputy.rb', line 176

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

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



132
133
134
135
# File 'lib/deputy.rb', line 132

def self.send_report(group, value, options = {})
  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



151
152
153
# File 'lib/deputy.rb', line 151

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

.sleep_random_intervalObject



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

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