nugget 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +27 -0
- data/bin/nugget +5 -0
- data/lib/nugget/backstop.rb +54 -0
- data/lib/nugget/cli.rb +69 -0
- data/lib/nugget/config.rb +10 -0
- data/lib/nugget/log.rb +6 -0
- data/lib/nugget/service.rb +96 -0
- data/lib/nugget/version.rb +3 -0
- data/lib/nugget/web.rb +21 -0
- data/lib/nugget.rb +50 -0
- metadata +152 -0
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
### Nugget
|
2
|
+
|
3
|
+
Nugget is a service for performing http and tcp integration tests. It uses [turd](https://github.com/joewilliams/turd/) under the covers to verify urls are responding properly. Kinda like pingdom, better in some ways, worse in others.
|
4
|
+
|
5
|
+
#### Usage
|
6
|
+
|
7
|
+
The examples directory includes an example config file. The config file is a json description of tests you want to run.
|
8
|
+
|
9
|
+
The following starts nugget up in daemon mode. In this mode nugget just loops performing tests and writing the results in json to `/tmp/nugget_results.json`.
|
10
|
+
|
11
|
+
$ nugget -c examples/config.json -d
|
12
|
+
|
13
|
+
Running nugget once is also possible.
|
14
|
+
|
15
|
+
$ nugget -c examples/config.json
|
16
|
+
|
17
|
+
Nugget also includes a very basic web service daemon that simply reads the current results file.
|
18
|
+
|
19
|
+
$ nugget -w
|
20
|
+
|
21
|
+
Additionally, nugget includes support for sending results of the tests to [backstop](https://github.com/obfuscurity/backstop).
|
22
|
+
|
23
|
+

|
24
|
+
|
25
|
+
#### License
|
26
|
+
|
27
|
+
nugget is open source software available under the MIT License
|
data/bin/nugget
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Nugget
|
2
|
+
class Backstop
|
3
|
+
|
4
|
+
def self.send_metrics(name, result, response)
|
5
|
+
send_test_result(name, result)
|
6
|
+
send_test_timings(name, response)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.send_test_result(name, result)
|
10
|
+
|
11
|
+
if result == "FAIL"
|
12
|
+
backstop_requst("#{name}.result", 1)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.send_test_timings(name, response)
|
18
|
+
|
19
|
+
response.each do |key, value|
|
20
|
+
if key.to_s.include?("_time")
|
21
|
+
backstop_requst("#{name}.#{key}", value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.backstop_requst(metric, value)
|
28
|
+
|
29
|
+
Nugget::Log.debug("Sending the following to backstop: #{metric}: #{value}")
|
30
|
+
|
31
|
+
body = [{
|
32
|
+
metric: metric,
|
33
|
+
value: value,
|
34
|
+
measure_time: Time.now.to_i
|
35
|
+
}].to_json
|
36
|
+
|
37
|
+
request = Typhoeus::Request.new(
|
38
|
+
Nugget::Config.backstop_url,
|
39
|
+
method: :post,
|
40
|
+
body: body,
|
41
|
+
headers: { 'Content-Type' => 'application/json' }
|
42
|
+
)
|
43
|
+
|
44
|
+
response = request.run
|
45
|
+
|
46
|
+
if response.options[:response_code] > 299
|
47
|
+
# hack a bad response error in here
|
48
|
+
Nugget::Log.error("Error publishing #{metric} to backstop, got #{response.options[:response_code]}")
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
data/lib/nugget/cli.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Nugget
|
2
|
+
class CLI
|
3
|
+
include Mixlib::CLI
|
4
|
+
|
5
|
+
option :log_level,
|
6
|
+
:short => "-l LEVEL",
|
7
|
+
:long => "--log_level LEVEL",
|
8
|
+
:description => "Set the log level (debug, info, warn, error, fatal)",
|
9
|
+
:default => :info,
|
10
|
+
:proc => Proc.new { |l| l.to_sym }
|
11
|
+
|
12
|
+
option :interval,
|
13
|
+
:short => "-i SECONDS",
|
14
|
+
:long => "--interval SECONDS",
|
15
|
+
:default => 30,
|
16
|
+
:description => "How long Nugget waits between testing runs when in daemon mode."
|
17
|
+
|
18
|
+
option :config,
|
19
|
+
:short => "-c PATH",
|
20
|
+
:long => "--config PATH",
|
21
|
+
:description => "Path of the json config."
|
22
|
+
|
23
|
+
option :daemon,
|
24
|
+
:short => "-d",
|
25
|
+
:long => "--daemon",
|
26
|
+
:boolean => true,
|
27
|
+
:default => false,
|
28
|
+
:description => "Run as a daemon. If not specified nugget just runs once."
|
29
|
+
|
30
|
+
option :web,
|
31
|
+
:short => "-w",
|
32
|
+
:long => "--web",
|
33
|
+
:boolean => true,
|
34
|
+
:description => "Run the web service."
|
35
|
+
|
36
|
+
option :ip,
|
37
|
+
:short => "-z IP",
|
38
|
+
:long => "--ip IP",
|
39
|
+
:default => "0.0.0.0",
|
40
|
+
:description => "IP for the web service."
|
41
|
+
|
42
|
+
option :port,
|
43
|
+
:short => "-p PORT",
|
44
|
+
:long => "--port PORT",
|
45
|
+
:default => 3000,
|
46
|
+
:description => "Port for the web service."
|
47
|
+
|
48
|
+
option :backstop_url,
|
49
|
+
:short => "-b URL",
|
50
|
+
:long => "--backstop URL",
|
51
|
+
:description => "URL for backstop metrics thing."
|
52
|
+
|
53
|
+
option :resultsfile,
|
54
|
+
:short => "-r FILE",
|
55
|
+
:long => "--results FILE",
|
56
|
+
:default => "/tmp/nugget_results.json",
|
57
|
+
:description => "Path to where results file is written/read."
|
58
|
+
|
59
|
+
option :help,
|
60
|
+
:short => "-h",
|
61
|
+
:long => "--help",
|
62
|
+
:description => "Show this message",
|
63
|
+
:on => :tail,
|
64
|
+
:boolean => true,
|
65
|
+
:show_options => true,
|
66
|
+
:exit => 0
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
data/lib/nugget/log.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
module Nugget
|
2
|
+
class Service
|
3
|
+
|
4
|
+
def self.run_daemon()
|
5
|
+
Nugget::Log.info("Starting up Nugget in daemon mode ...")
|
6
|
+
|
7
|
+
loop do
|
8
|
+
run()
|
9
|
+
|
10
|
+
# chill
|
11
|
+
sleep(Nugget::Config.interval.to_i)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.run_once()
|
16
|
+
Nugget::Log.info("Starting up Nugget in run-once mode ...")
|
17
|
+
run()
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.run()
|
21
|
+
config_file = File.new(Nugget::Config.config, 'r')
|
22
|
+
parser = Yajl::Parser.new(:symbolize_keys => true)
|
23
|
+
config = parser.parse(config_file)
|
24
|
+
|
25
|
+
results = Hash.new
|
26
|
+
|
27
|
+
config.each do |test, definition|
|
28
|
+
result = nil
|
29
|
+
response = nil
|
30
|
+
|
31
|
+
begin
|
32
|
+
request_definition = config_converter(definition)
|
33
|
+
response_definition = definition[:response]
|
34
|
+
|
35
|
+
response = Turd.run(request_definition, response_definition)
|
36
|
+
result = "PASS"
|
37
|
+
rescue Exception => e
|
38
|
+
Nugget::Log.error("#{definition[:type]} test #{test} failed!")
|
39
|
+
Nugget::Log.error(e)
|
40
|
+
|
41
|
+
result = "FAIL"
|
42
|
+
response = e.response
|
43
|
+
end
|
44
|
+
|
45
|
+
Nugget::Log.info("Test #{test} complete with status #{result}")
|
46
|
+
|
47
|
+
results.store(test, {
|
48
|
+
:config => definition,
|
49
|
+
:result => result,
|
50
|
+
:response => response,
|
51
|
+
:timestamp => Time.now.to_i
|
52
|
+
})
|
53
|
+
|
54
|
+
if Nugget::Config.backstop_url
|
55
|
+
Nugget::Backstop.send_metrics(test, result, response)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
if Nugget::Config.daemon
|
60
|
+
Nugget::Service.write_results(results)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.config_converter(definition)
|
65
|
+
options = definition[:request]
|
66
|
+
|
67
|
+
if options[:method]
|
68
|
+
sym_method = options[:method].to_sym
|
69
|
+
options.store(:method, sym_method)
|
70
|
+
end
|
71
|
+
|
72
|
+
if options[:url]
|
73
|
+
url = options[:url]
|
74
|
+
options.delete(:url)
|
75
|
+
end
|
76
|
+
|
77
|
+
{
|
78
|
+
:url => url,
|
79
|
+
:type => definition[:type],
|
80
|
+
:options => options
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.write_results(results)
|
85
|
+
begin
|
86
|
+
file = File.open(Nugget::Config.resultsfile, "w")
|
87
|
+
file.puts(results.to_json)
|
88
|
+
file.close
|
89
|
+
rescue Exception => e
|
90
|
+
Nugget::Log.error("Something went wrong with writing out the results file!")
|
91
|
+
Nugget::Log.error(e)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
data/lib/nugget/web.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Nugget
|
2
|
+
class Web
|
3
|
+
|
4
|
+
def self.run()
|
5
|
+
app = Rack::URLMap.new('/' => Nugget::Web.new)
|
6
|
+
Thin::Server.start(Nugget::Config.ip, Nugget::Config.port, app)
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
time_diff = Time.now.to_i - File.mtime(Nugget::Config.resultsfile).to_i
|
11
|
+
|
12
|
+
if time_diff < 3600
|
13
|
+
body = [File.read(Nugget::Config.resultsfile)]
|
14
|
+
[200, { 'Content-Type' => 'text/plain' }, body]
|
15
|
+
else
|
16
|
+
[500, { 'Content-Type' => 'text/plain' }, ["nugget results file is stale (#{time_diff} seconds), something is wrong"]]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/nugget.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require 'turd'
|
4
|
+
require 'mixlib/cli'
|
5
|
+
require 'mixlib/config'
|
6
|
+
require 'mixlib/log'
|
7
|
+
require 'yajl/json_gem'
|
8
|
+
require 'thin'
|
9
|
+
|
10
|
+
__DIR__ = File.dirname(__FILE__)
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift __DIR__ unless
|
13
|
+
$LOAD_PATH.include?(__DIR__) ||
|
14
|
+
$LOAD_PATH.include?(File.expand_path(__DIR__))
|
15
|
+
|
16
|
+
require 'nugget/config'
|
17
|
+
require 'nugget/log'
|
18
|
+
require 'nugget/cli'
|
19
|
+
require 'nugget/service'
|
20
|
+
require 'nugget/web'
|
21
|
+
require 'nugget/backstop'
|
22
|
+
require 'nugget/version'
|
23
|
+
|
24
|
+
module Nugget
|
25
|
+
class << self
|
26
|
+
|
27
|
+
def main
|
28
|
+
cli = Nugget::CLI.new
|
29
|
+
cli.parse_options
|
30
|
+
Nugget::Config.merge!(cli.config)
|
31
|
+
|
32
|
+
Nugget::Log.level(Nugget::Config.log_level)
|
33
|
+
|
34
|
+
if Nugget::Config.web
|
35
|
+
Nugget::Web.run()
|
36
|
+
else
|
37
|
+
if Nugget::Config.config
|
38
|
+
if Nugget::Config.daemon
|
39
|
+
Nugget::Service.run_daemon()
|
40
|
+
else
|
41
|
+
Nugget::Service.run_once()
|
42
|
+
end
|
43
|
+
else
|
44
|
+
Nugget::Log.error("No config supplied! Use \"-c FILE\".")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nugget
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- joe williams
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: mixlib-config
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: mixlib-log
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: mixlib-cli
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: turd
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: yajl-ruby
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: thin
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description:
|
111
|
+
email: joe@joetify.com
|
112
|
+
executables:
|
113
|
+
- nugget
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files:
|
116
|
+
- README.md
|
117
|
+
files:
|
118
|
+
- bin/nugget
|
119
|
+
- lib/nugget/backstop.rb
|
120
|
+
- lib/nugget/cli.rb
|
121
|
+
- lib/nugget/config.rb
|
122
|
+
- lib/nugget/log.rb
|
123
|
+
- lib/nugget/service.rb
|
124
|
+
- lib/nugget/version.rb
|
125
|
+
- lib/nugget/web.rb
|
126
|
+
- lib/nugget.rb
|
127
|
+
- README.md
|
128
|
+
homepage: http://github.com/joewilliams/nugget
|
129
|
+
licenses: []
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ! '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 1.8.23
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: a http and tcp testing service
|
152
|
+
test_files: []
|