litmus_paper 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -23,6 +23,10 @@ Or install it yourself as:
23
23
  Use the sample config to run it under unicorn. Or execute litmus-agent-check to
24
24
  use it as an agent-check for HAProxy.
25
25
 
26
+ ## Releasing
27
+
28
+ $ ./release
29
+
26
30
  ## Contributing
27
31
 
28
32
  1. Fork it
@@ -34,7 +34,12 @@ module LitmusPaper
34
34
  end
35
35
 
36
36
  get "/:service/status" do
37
- health = LitmusPaper.check_service(params[:service])
37
+ health = _cache.get(params[:service])
38
+ _cache.set(
39
+ params[:service],
40
+ health = LitmusPaper.check_service(params[:service])
41
+ ) unless health
42
+
38
43
  if health.nil?
39
44
  _text 404, "NOT FOUND", { "X-Health" => "0" }
40
45
  else
@@ -100,6 +105,14 @@ module LitmusPaper
100
105
  _text 500, "Server Error"
101
106
  end
102
107
 
108
+ def _cache
109
+ @cache ||= LitmusPaper::Cache.new(
110
+ LitmusPaper.cache_location,
111
+ "litmus_cache",
112
+ LitmusPaper.cache_ttl
113
+ )
114
+ end
115
+
103
116
  def _create_status_file(status_file)
104
117
  status_file.create(params[:reason], params[:health])
105
118
  _text 201, "File created"
@@ -0,0 +1,33 @@
1
+ require 'yaml'
2
+
3
+ module LitmusPaper
4
+ class Cache
5
+ def initialize(location, namespace, ttl)
6
+ @path = File.join(location, namespace)
7
+ @ttl = ttl
8
+
9
+ FileUtils.mkdir_p(@path)
10
+ end
11
+
12
+ def set(key, value)
13
+ return unless @ttl > 0
14
+ File.open(File.join(@path, key), "a") do |f|
15
+ f.flock(File::LOCK_EX)
16
+ f.rewind
17
+ f.write("#{Time.now.to_f + @ttl} #{YAML::dump(value)}")
18
+ f.flush
19
+ f.truncate(f.pos)
20
+ end
21
+ end
22
+
23
+ def get(key)
24
+ return unless File.exists?(File.join(@path, key))
25
+ File.open(File.join(@path, key), "r") do |f|
26
+ f.flock(File::LOCK_SH)
27
+ entry = f.read
28
+ expires_at, value = entry.split(" ", 2)
29
+ expires_at.to_f < Time.now.to_f ? nil : YAML::load(value)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,4 +1,11 @@
1
1
  module LitmusPaper
2
- class Configuration < Struct.new(:port, :data_directory, :services)
2
+ fields = [
3
+ :port,
4
+ :data_directory,
5
+ :services,
6
+ :cache_location,
7
+ :cache_ttl
8
+ ]
9
+ class Configuration < Struct.new(*fields)
3
10
  end
4
11
  end
@@ -5,13 +5,21 @@ module LitmusPaper
5
5
  @services = {}
6
6
  @port = 9292
7
7
  @data_directory = "/etc/litmus"
8
+ @cache_location = "/run/shm"
9
+ @cache_ttl = -1
8
10
  end
9
11
 
10
12
  def evaluate(file = @config_file_path)
11
13
  LitmusPaper.logger.info "Loading file #{file}"
12
14
  config_contents = File.read(file)
13
15
  instance_eval(config_contents)
14
- LitmusPaper::Configuration.new(@port, @data_directory, @services)
16
+ LitmusPaper::Configuration.new(
17
+ @port,
18
+ @data_directory,
19
+ @services,
20
+ @cache_location,
21
+ @cache_ttl
22
+ )
15
23
  end
16
24
 
17
25
  def include_files(glob_pattern)
@@ -36,5 +44,13 @@ module LitmusPaper
36
44
  block.call(service)
37
45
  @services[name.to_s] = service
38
46
  end
47
+
48
+ def cache_location(location)
49
+ @cache_location = location
50
+ end
51
+
52
+ def cache_ttl(ttl)
53
+ @cache_ttl = ttl
54
+ end
39
55
  end
40
56
  end
@@ -1,3 +1,3 @@
1
1
  module LitmusPaper
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
data/lib/litmus_paper.rb CHANGED
@@ -14,6 +14,7 @@ require 'forwardable'
14
14
 
15
15
  require 'remote_syslog_logger'
16
16
 
17
+ require 'litmus_paper/cache'
17
18
  require 'litmus_paper/configuration'
18
19
  require 'litmus_paper/configuration_file'
19
20
  require 'litmus_paper/dependency/file_contents'
@@ -35,7 +36,7 @@ require 'litmus_paper/version'
35
36
  module LitmusPaper
36
37
  class << self
37
38
  extend Forwardable
38
- def_delegators :@config, :services, :data_directory, :port
39
+ def_delegators :@config, :services, :data_directory, :port, :cache_location, :cache_ttl
39
40
  attr_accessor :logger
40
41
  end
41
42
 
data/release ADDED
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+
3
+ set -o errexit
4
+ set -o pipefail
5
+ set -o nounset
6
+ set -o xtrace
7
+
8
+ chmod -R go+rX .
9
+ rm -f *.gem
10
+ gem build litmus_paper.gemspec
11
+ gem push litmus_paper*.gem
@@ -272,7 +272,7 @@ describe LitmusPaper::App do
272
272
  last_response.header["X-Health-Forced"].should == "health"
273
273
  end
274
274
 
275
- it "returns the actualy health value for an unhealthy service when the measured health is less than the forced value" do
275
+ it "returns the actual health value for an unhealthy service when the measured health is less than the forced value" do
276
276
  test_service = LitmusPaper::Service.new('test', [NeverAvailableDependency.new], [LitmusPaper::Metric::ConstantMetric.new(100)])
277
277
  LitmusPaper.services['test'] = test_service
278
278
  LitmusPaper::StatusFile.service_health_file("test").create("Forcing health", 88)
@@ -418,6 +418,45 @@ describe LitmusPaper::App do
418
418
  last_response.headers["X-Health-Forced"].should == "up"
419
419
  last_response.body.should match(/Up for testing/)
420
420
  end
421
+
422
+ it "retrieves a cached value during the cache_ttl" do
423
+ begin
424
+ cache = LitmusPaper::Cache.new(
425
+ location = "/tmp/litmus_cache",
426
+ namespace = "test_cache",
427
+ ttl = 0.05
428
+ )
429
+ LitmusPaper::App.any_instance.stub(:_cache).and_return(cache)
430
+ test_service = LitmusPaper::Service.new(
431
+ 'test',
432
+ [AlwaysAvailableDependency.new],
433
+ [LitmusPaper::Metric::ConstantMetric.new(100)]
434
+ )
435
+ LitmusPaper.services['test'] = test_service
436
+
437
+ post "/test/health", :reason => "health for testing", :health => 88
438
+ last_response.status.should == 201
439
+
440
+ get "/test/status"
441
+ last_response.status.should == 200
442
+ last_response.body.should match(/health for testing 88/)
443
+
444
+ delete "/test/health"
445
+ last_response.status.should == 200
446
+
447
+ get "/test/status"
448
+ last_response.should be_ok
449
+ last_response.body.should match(/health for testing 88/)
450
+
451
+ sleep ttl
452
+
453
+ get "/test/status"
454
+ last_response.should be_ok
455
+ last_response.body.should_not match(/health for testing 88/)
456
+ ensure
457
+ FileUtils.rm_rf(location)
458
+ end
459
+ end
421
460
  end
422
461
 
423
462
  describe "server errors" do
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ describe LitmusPaper::Cache do
4
+ before(:each) do
5
+ @location = "/tmp/litmus_cache"
6
+ @namespace = "test_cache"
7
+ @ttl = -1
8
+ end
9
+
10
+ after(:each) do
11
+ FileUtils.rm_rf(@location)
12
+ end
13
+
14
+ describe "initialize" do
15
+ it "creates the directory structure" do
16
+ File.exists?(@location).should be false
17
+ LitmusPaper::Cache.new(@location, @namespace, @ttl)
18
+ File.exists?(File.join(@location, @namespace)).should be true
19
+ end
20
+ end
21
+
22
+ describe "get" do
23
+ it "returns false if the key was not previously set" do
24
+ cache = LitmusPaper::Cache.new(@location, @namespace, @ttl)
25
+ cache.get("non-existant-key").should be_nil
26
+ end
27
+
28
+ context "when called with fresh entry" do
29
+ it "returns the value set" do
30
+ cache = LitmusPaper::Cache.new(@location, @namespace, 10)
31
+ cache.set("key", "some value")
32
+ cache.get("key").should == "some value"
33
+ end
34
+ end
35
+
36
+ context "when called with expired entry" do
37
+ it "returns nil" do
38
+ cache = LitmusPaper::Cache.new(@location, @namespace, -1)
39
+ cache.set("key", "some value")
40
+ cache.get("key").should be_nil
41
+ end
42
+ end
43
+ end
44
+
45
+ describe "set" do
46
+ context "when called with non-positive ttl" do
47
+ it "does not store the value" do
48
+ key = "key"
49
+ cache = LitmusPaper::Cache.new(@location, @namespace, 0)
50
+ cache.set(key, "some value")
51
+ File.exists?(File.join(@location, @namespace, key)).should be false
52
+ end
53
+ end
54
+
55
+ context "when called with positive ttl" do
56
+ it "stores the value" do
57
+ key = "key"
58
+ cache = LitmusPaper::Cache.new(@location, @namespace, 1)
59
+ cache.set(key, "some value")
60
+ File.exists?(File.join(@location, @namespace, key)).should be true
61
+ end
62
+ end
63
+
64
+ it "expires the entry after the ttl" do
65
+ key = "key"
66
+ ttl = 0.01
67
+ cache = LitmusPaper::Cache.new(@location, @namespace, ttl)
68
+ cache.set(key, "some value")
69
+ cache.get(key).should == "some value"
70
+ sleep ttl
71
+ cache.get(key).should be_nil
72
+ end
73
+ end
74
+ end
@@ -19,6 +19,18 @@ describe LitmusPaper::ConfigurationFile do
19
19
  config = config_file.evaluate
20
20
  config.data_directory.should == "/tmp/litmus_paper"
21
21
  end
22
+
23
+ it "configures the cache_location" do
24
+ config_file = LitmusPaper::ConfigurationFile.new(TEST_CONFIG)
25
+ config = config_file.evaluate
26
+ config.cache_location.should == "/tmp/litmus_paper_cache"
27
+ end
28
+
29
+ it "configures the cache_ttl" do
30
+ config_file = LitmusPaper::ConfigurationFile.new(TEST_CONFIG)
31
+ config = config_file.evaluate
32
+ config.cache_ttl.should == -1
33
+ end
22
34
  end
23
35
 
24
36
  describe "include_files" do
@@ -4,6 +4,9 @@ port 9293
4
4
 
5
5
  data_directory "/tmp/litmus_paper"
6
6
 
7
+ cache_location "/tmp/litmus_paper_cache"
8
+ cache_ttl -1
9
+
7
10
  service :test do |s|
8
11
  s.depends Dependency::HTTP, "http://localhost/heartbeat"
9
12
 
@@ -4,6 +4,9 @@ port 9293
4
4
 
5
5
  data_directory "/tmp/litmus_paper"
6
6
 
7
+ cache_location "/tmp/litmus_paper_cache"
8
+ cache_ttl -1
9
+
7
10
  service :foo do |s|
8
11
  s.depends Dependency::HTTP, "http://localhost/heartbeat"
9
12
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: litmus_paper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-10-05 00:00:00.000000000 Z
12
+ date: 2017-12-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sinatra
@@ -165,6 +165,7 @@ files:
165
165
  - lib/litmus_paper/agent_check_handler.rb
166
166
  - lib/litmus_paper/agent_check_server.rb
167
167
  - lib/litmus_paper/app.rb
168
+ - lib/litmus_paper/cache.rb
168
169
  - lib/litmus_paper/cli/admin.rb
169
170
  - lib/litmus_paper/cli/admin/command.rb
170
171
  - lib/litmus_paper/cli/admin/force.rb
@@ -192,9 +193,11 @@ files:
192
193
  - lib/litmus_paper/version.rb
193
194
  - litmus-agent-check.init.sh
194
195
  - litmus_paper.gemspec
196
+ - release
195
197
  - spec/litmus_paper/agent_check_handler_spec.rb
196
198
  - spec/litmus_paper/agent_check_server_spec.rb
197
199
  - spec/litmus_paper/app_spec.rb
200
+ - spec/litmus_paper/cache_spec.rb
198
201
  - spec/litmus_paper/cli/admin_spec.rb
199
202
  - spec/litmus_paper/configuration_file_spec.rb
200
203
  - spec/litmus_paper/dependency/file_contents_spec.rb
@@ -255,6 +258,7 @@ test_files:
255
258
  - spec/litmus_paper/agent_check_handler_spec.rb
256
259
  - spec/litmus_paper/agent_check_server_spec.rb
257
260
  - spec/litmus_paper/app_spec.rb
261
+ - spec/litmus_paper/cache_spec.rb
258
262
  - spec/litmus_paper/cli/admin_spec.rb
259
263
  - spec/litmus_paper/configuration_file_spec.rb
260
264
  - spec/litmus_paper/dependency/file_contents_spec.rb