flapjack 0.7.1 → 0.7.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/CHANGELOG.md +29 -0
- data/README.md +1 -4
- data/bin/flapjack +24 -2
- data/bin/flapjack-nagios-receiver +4 -2
- data/bin/receive-events +191 -0
- data/bin/simulate-failed-check +144 -0
- data/features/notification_rules.feature +63 -2
- data/features/steps/events_steps.rb +15 -3
- data/flapjack.gemspec +1 -1
- data/lib/flapjack/data/contact.rb +15 -9
- data/lib/flapjack/data/entity.rb +19 -1
- data/lib/flapjack/data/entity_check.rb +12 -0
- data/lib/flapjack/data/event.rb +10 -2
- data/lib/flapjack/data/notification.rb +12 -8
- data/lib/flapjack/data/notification_rule.rb +3 -1
- data/lib/flapjack/executive.rb +71 -17
- data/lib/flapjack/gateways/api.rb +5 -2
- data/lib/flapjack/gateways/jabber.rb +26 -17
- data/lib/flapjack/gateways/web.rb +54 -9
- data/lib/flapjack/gateways/web/public/css/bootstrap-responsive.min.css +9 -0
- data/lib/flapjack/gateways/web/public/css/bootstrap.min.css +9 -0
- data/lib/flapjack/gateways/web/public/css/flapjack.css +51 -0
- data/lib/flapjack/gateways/web/public/img/flapjack_white_bg_400_353.jpeg +0 -0
- data/lib/flapjack/gateways/web/public/img/glyphicons-halflings-white.png +0 -0
- data/lib/flapjack/gateways/web/public/img/glyphicons-halflings.png +0 -0
- data/lib/flapjack/gateways/web/public/js/bootstrap.min.js +6 -0
- data/lib/flapjack/gateways/web/views/_foot.haml +8 -0
- data/lib/flapjack/gateways/web/views/_head.haml +10 -0
- data/lib/flapjack/gateways/web/views/_nav.haml +9 -3
- data/lib/flapjack/gateways/web/views/check.haml +140 -138
- data/lib/flapjack/gateways/web/views/checks.haml +49 -0
- data/lib/flapjack/gateways/web/views/contact.haml +78 -37
- data/lib/flapjack/gateways/web/views/contacts.haml +23 -17
- data/lib/flapjack/gateways/web/views/entities.haml +28 -0
- data/lib/flapjack/gateways/web/views/entity.haml +44 -0
- data/lib/flapjack/gateways/web/views/index.haml +27 -44
- data/lib/flapjack/gateways/web/views/self_stats.haml +65 -22
- data/lib/flapjack/version.rb +1 -1
- data/spec/lib/flapjack/executive_spec.rb +6 -2
- data/spec/lib/flapjack/gateways/api_spec.rb +15 -0
- data/spec/lib/flapjack/gateways/web/views/contact.haml_spec.rb +2 -1
- data/spec/lib/flapjack/gateways/web/views/index.haml_spec.rb +3 -2
- data/spec/lib/flapjack/gateways/web_spec.rb +23 -9
- data/tmp/create_events_failure.rb +6 -4
- metadata +23 -12
data/CHANGELOG.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
## Flapjack Changelog
|
2
|
+
|
3
|
+
# 0.7.2 - 2013-05-06
|
4
|
+
- Feature: executive instance keys now expire after 7 days, touched every event gh-111 (@jessereynolds)
|
5
|
+
- Feature: slightly less sucky looking web UI, also now includes entity listing screens (@jessereynolds)
|
6
|
+
- Feature: expose notification rules and intervals via the Web UI gh-150, gh-151 (@jessereynolds)
|
7
|
+
- Feature: command line - support "--version", "help" etc gh-134 (@jessereynolds)
|
8
|
+
- Feature: replay events from another flapjack gh-138 (@jessereynolds)
|
9
|
+
- Bug: recovery is not resetting notification intervals gh-136 (@jessereynolds)
|
10
|
+
- Bug: recoveries are blocked for users with notification rules gh-148 (@jessereynolds)
|
11
|
+
- Bug: jabber gateway now uses configured alias for commands gh-138 (@jessereynolds)
|
12
|
+
- Bug: jabber gateway was crashing on querying entities with invalid regex gh-147 (@jessereynolds)
|
13
|
+
- Bug: handle media addresses correctly when adding contacts and generating messages gh-145 (@jessereynolds)
|
14
|
+
|
15
|
+
# 0.7.1 - 2013-04-24
|
16
|
+
- Feature: archive incoming events in a sliding window gh-127 (@jessereynolds)
|
17
|
+
- Bug: Unable to retrieve status of a check containing non word characters via the API gh-117 (@ali-graham)
|
18
|
+
- Bug: Disable Thin's loading of Daemons gh-133 (@jessereynolds, thanks @johnf)
|
19
|
+
|
20
|
+
# 0.7.0 - 2013-04-18
|
21
|
+
- Feature: Introduce Notification Rules gh-55 (@jessereynolds)
|
22
|
+
- Feature: Tagging on contacts and entities, expose via API gh-125 (@ali-graham)
|
23
|
+
- Feature: API improvements (notification rules, contact's timezone and notification intervals per media, tags) (@ali-graham, @jessereynolds)
|
24
|
+
- Feature: Contact mass update (rather than drop all then import) gh-124 (@ali-graham)
|
25
|
+
- Feature: Improve error handling (log file paths, permissions), expose internal stats as json gh-122 (@auxesis)
|
26
|
+
- Incompatable Change: POST /contacts in the API now includes intervals per media and is incompatible with previous versions
|
27
|
+
|
28
|
+
# 0.6.61 - 2013-01-11
|
29
|
+
- todo (and previous versions)
|
data/README.md
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
# Flapjack
|
2
2
|
|
3
|
-
[![
|
4
|
-
|
5
|
-
[id_travis_link]: https://secure.travis-ci.org/#!/flpjck/flapjack
|
6
|
-
[id_travis_img]: https://secure.travis-ci.org/flpjck/flapjack.png
|
3
|
+
[](https://travis-ci.org/flpjck/flapjack)
|
7
4
|
|
8
5
|
[flapjack-project.com](http://flapjack-project.com/)
|
9
6
|
|
data/bin/flapjack
CHANGED
@@ -10,6 +10,7 @@ require 'optparse'
|
|
10
10
|
require 'ostruct'
|
11
11
|
|
12
12
|
require 'flapjack/configuration'
|
13
|
+
require 'flapjack/version'
|
13
14
|
|
14
15
|
options = OpenStruct.new
|
15
16
|
options.config = File.join('etc', 'flapjack_config.yaml')
|
@@ -17,7 +18,7 @@ options.daemonize = nil
|
|
17
18
|
|
18
19
|
@exe = File.basename(__FILE__)
|
19
20
|
|
20
|
-
OptionParser.new do |opts|
|
21
|
+
optparse = OptionParser.new do |opts|
|
21
22
|
opts.banner = "Usage: flapjack COMMAND [OPTIONS]"
|
22
23
|
|
23
24
|
opts.separator ""
|
@@ -27,6 +28,8 @@ OptionParser.new do |opts|
|
|
27
28
|
opts.separator " restart #{" " * 23} (re)start flapjack"
|
28
29
|
opts.separator " reload #{" " * 24} reload flapjack configuration"
|
29
30
|
opts.separator " status #{" " * 24} see if flapjack is running"
|
31
|
+
opts.separator " version #{" " * 23} display flapjack version and exit"
|
32
|
+
opts.separator " help #{" " * 26} display this usage info"
|
30
33
|
opts.separator ""
|
31
34
|
opts.separator "Options"
|
32
35
|
|
@@ -46,7 +49,13 @@ OptionParser.new do |opts|
|
|
46
49
|
options.log_path = l
|
47
50
|
end
|
48
51
|
|
49
|
-
|
52
|
+
opts.on("-v", "--version", "display flapjack version") do |v|
|
53
|
+
options.version = v
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
optparse.parse!(ARGV)
|
50
59
|
|
51
60
|
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
|
52
61
|
|
@@ -71,6 +80,10 @@ daemonize = options.daemonize.nil? ?
|
|
71
80
|
!!config_env['daemonize'] :
|
72
81
|
options.daemonize
|
73
82
|
|
83
|
+
if options.version
|
84
|
+
puts Flapjack::VERSION
|
85
|
+
exit
|
86
|
+
end
|
74
87
|
|
75
88
|
flapjack_coord = Proc.new {
|
76
89
|
require 'flapjack/coordinator'
|
@@ -177,12 +190,21 @@ when "status"
|
|
177
190
|
exit 3
|
178
191
|
end
|
179
192
|
|
193
|
+
when "help"
|
194
|
+
puts optparse
|
195
|
+
exit
|
196
|
+
|
197
|
+
when "version"
|
198
|
+
puts Flapjack::VERSION
|
199
|
+
exit
|
200
|
+
|
180
201
|
else
|
181
202
|
if ARGV.nil? || ARGV.empty?
|
182
203
|
puts "No command provided"
|
183
204
|
else
|
184
205
|
puts "Unknown command provided: '#{ARGV[0]}'"
|
185
206
|
end
|
207
|
+
puts "\n#{optparse}"
|
186
208
|
exit 1
|
187
209
|
|
188
210
|
end
|
@@ -74,7 +74,7 @@ options.daemonize = nil
|
|
74
74
|
|
75
75
|
exe = File.basename(__FILE__)
|
76
76
|
|
77
|
-
OptionParser.new do |opts|
|
77
|
+
optparse = OptionParser.new do |opts|
|
78
78
|
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
79
79
|
|
80
80
|
opts.separator ""
|
@@ -106,7 +106,8 @@ OptionParser.new do |opts|
|
|
106
106
|
options.log_path = l
|
107
107
|
end
|
108
108
|
|
109
|
-
end
|
109
|
+
end
|
110
|
+
optparse.parse!(ARGV)
|
110
111
|
|
111
112
|
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
|
112
113
|
|
@@ -219,6 +220,7 @@ else
|
|
219
220
|
else
|
220
221
|
puts "Unknown command provided: '#{ARGV[0]}'"
|
221
222
|
end
|
223
|
+
puts "\n#{optparse}"
|
222
224
|
exit 1
|
223
225
|
|
224
226
|
end
|
data/bin/receive-events
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
4
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
require 'ostruct'
|
9
|
+
require 'redis'
|
10
|
+
require 'yajl/json_gem'
|
11
|
+
|
12
|
+
require 'flapjack/configuration'
|
13
|
+
|
14
|
+
def pike(message)
|
15
|
+
puts "piking out: #{message}"
|
16
|
+
exit 1
|
17
|
+
end
|
18
|
+
|
19
|
+
def send_event(event, opts)
|
20
|
+
redis = opts[:redis]
|
21
|
+
redis.lpush 'events', event
|
22
|
+
end
|
23
|
+
|
24
|
+
def receive(opts)
|
25
|
+
redis = Redis.new(opts[:redis_options])
|
26
|
+
source_redis = Redis.new(:url => opts[:source])
|
27
|
+
|
28
|
+
archives = get_archive_keys_stats(source_redis)
|
29
|
+
raise "found no archives!" unless archives && archives.length > 0
|
30
|
+
|
31
|
+
puts "found archives: #{archives.inspect}"
|
32
|
+
|
33
|
+
# each archive bucket is a redis list that is written
|
34
|
+
# with brpoplpush, that is newest items are added to the left (head)
|
35
|
+
# of the list, so oldest events are to be found at the tail of the list.
|
36
|
+
#
|
37
|
+
# the index of these archives, in the 'archives' array, also stores the
|
38
|
+
# redis key names for each bucket in oldest to newest
|
39
|
+
events_sent = 0
|
40
|
+
case
|
41
|
+
when opts[:all]
|
42
|
+
archive_key = archives[0][:name]
|
43
|
+
cursor = -1
|
44
|
+
when opts[:last], opts[:time]
|
45
|
+
raise "Sorry, unimplemented"
|
46
|
+
else
|
47
|
+
# wait for the next event to be archived, so point the cursor at a non-existant
|
48
|
+
# slot in the list, the one before the 0'th
|
49
|
+
archive_key = archives[-1][:name]
|
50
|
+
cursor = -1 - archives[-1][:size]
|
51
|
+
end
|
52
|
+
|
53
|
+
puts archive_key
|
54
|
+
|
55
|
+
loop do
|
56
|
+
new_archive_key = false
|
57
|
+
# something to read at cursor?
|
58
|
+
event = source_redis.lindex(archive_key, cursor)
|
59
|
+
if event
|
60
|
+
send_event(event, :redis => redis)
|
61
|
+
events_sent += 1
|
62
|
+
print "#{events_sent} " if events_sent % 1000 == 0
|
63
|
+
cursor -= 1
|
64
|
+
else
|
65
|
+
puts "\narchive key: #{archive_key}, cursor: #{cursor}"
|
66
|
+
# do we need to look at the next archive bucket?
|
67
|
+
archives = get_archive_keys_stats(source_redis)
|
68
|
+
i = archives.index {|a| a[:name] == archive_key }
|
69
|
+
if archives[i][:size] = (cursor.abs + 1)
|
70
|
+
if archives[i + 1]
|
71
|
+
archive_key = archives[i + 1][:name]
|
72
|
+
puts archive_key
|
73
|
+
cursor = -1
|
74
|
+
new_archive_key = true
|
75
|
+
else
|
76
|
+
return unless opts[:follow]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
sleep 1 unless new_archive_key
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def get_archive_keys_stats(source_redis)
|
85
|
+
source_redis.keys("events_archive:*").sort.map {|a|
|
86
|
+
{ :name => a,
|
87
|
+
:size => source_redis.llen(a) }
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
options = OpenStruct.new
|
92
|
+
options.config = nil
|
93
|
+
options.daemonize = nil
|
94
|
+
|
95
|
+
exe = File.basename(__FILE__)
|
96
|
+
|
97
|
+
optparse = OptionParser.new do |opts|
|
98
|
+
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
99
|
+
|
100
|
+
opts.separator ""
|
101
|
+
opts.separator "Commands"
|
102
|
+
opts.separator " help"
|
103
|
+
opts.separator ""
|
104
|
+
opts.separator "Options"
|
105
|
+
|
106
|
+
opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
|
107
|
+
options.config = c
|
108
|
+
end
|
109
|
+
|
110
|
+
opts.on("-s", "--source URL", String, "URL of source redis database, eg redis://localhost:6379/0") do |s|
|
111
|
+
options.source = s
|
112
|
+
end
|
113
|
+
|
114
|
+
opts.on("-f", "--follow", String, "keep reading events as they are archived on the source") do |f|
|
115
|
+
options.follow = true
|
116
|
+
end
|
117
|
+
|
118
|
+
opts.on("-a", "--all", String, "replay all archived events from the source") do |a|
|
119
|
+
options.all = true
|
120
|
+
end
|
121
|
+
|
122
|
+
opts.on("-l", "--last COUNT", String, "replay the last COUNT events from the source") do |l|
|
123
|
+
options.count = l
|
124
|
+
end
|
125
|
+
|
126
|
+
opts.on("-t", "--time TIME", String, "replay all events archived on the source since TIME") do |t|
|
127
|
+
options.since = t
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
optparse.parse!(ARGV)
|
132
|
+
|
133
|
+
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
|
134
|
+
|
135
|
+
if options.config
|
136
|
+
config_file = options.config
|
137
|
+
pike "specified config file cannot be read" unless File.readable?(config_file)
|
138
|
+
else
|
139
|
+
[ 'etc/flapjack_config.yaml',
|
140
|
+
File.dirname(__FILE__) + 'etc/flapjack_config.yaml',
|
141
|
+
'/etc/flapjack/flapjack_config.yaml' ].each do |candidate|
|
142
|
+
if File.readable?(candidate)
|
143
|
+
config_file = candidate
|
144
|
+
break
|
145
|
+
else
|
146
|
+
puts "not found and/or not readable: #{candidate}"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
pike "no config file specified and none found in default locations" unless config_file
|
150
|
+
end
|
151
|
+
|
152
|
+
config = Flapjack::Configuration.new
|
153
|
+
config.load(config_file)
|
154
|
+
config_env = config.all
|
155
|
+
redis_options = config.for_redis
|
156
|
+
|
157
|
+
if config_env.nil? || config_env.empty?
|
158
|
+
puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
|
159
|
+
exit(false)
|
160
|
+
end
|
161
|
+
|
162
|
+
unless options.source
|
163
|
+
puts "--source URL is required"
|
164
|
+
exit 1
|
165
|
+
end
|
166
|
+
|
167
|
+
unless options.follow || options.all
|
168
|
+
puts "one or both of --follow or --all is required"
|
169
|
+
exit 1
|
170
|
+
end
|
171
|
+
|
172
|
+
case ARGV[0]
|
173
|
+
when "help"
|
174
|
+
puts optparse
|
175
|
+
exit
|
176
|
+
else
|
177
|
+
unless ARGV.nil? || ARGV.empty?
|
178
|
+
puts "Unknown command provided: '#{ARGV[0]}'"
|
179
|
+
puts "\n#{optparse}"
|
180
|
+
exit 1
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
receive(:follow => options.follow,
|
185
|
+
:all => options.all,
|
186
|
+
:source => options.source,
|
187
|
+
:last => options.last,
|
188
|
+
:time => options.time,
|
189
|
+
:redis_options => redis_options)
|
190
|
+
|
191
|
+
|
@@ -0,0 +1,144 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
unless $:.include?(File.dirname(__FILE__) + '/../lib/')
|
4
|
+
$: << File.dirname(__FILE__) + '/../lib'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'optparse'
|
8
|
+
require 'ostruct'
|
9
|
+
require 'redis'
|
10
|
+
require 'yajl/json_gem'
|
11
|
+
require 'eventmachine'
|
12
|
+
|
13
|
+
require 'flapjack/configuration'
|
14
|
+
|
15
|
+
def pike(message)
|
16
|
+
puts "piking out: #{message}"
|
17
|
+
exit 1
|
18
|
+
end
|
19
|
+
|
20
|
+
def send_event(event, opts)
|
21
|
+
redis = opts[:redis]
|
22
|
+
redis.lpush 'events', event.to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
def fail(opts)
|
26
|
+
redis = Redis.new(opts[:redis_options])
|
27
|
+
stop_after = opts[:minutes].to_i * 60
|
28
|
+
recover = opts[:recover]
|
29
|
+
event = {
|
30
|
+
'entity' => opts[:entity] || 'foo-app-01',
|
31
|
+
'check' => opts[:check] || 'HTTP',
|
32
|
+
'type' => 'service',
|
33
|
+
'timestamp' => Time.now.to_i
|
34
|
+
}
|
35
|
+
failure = event.merge('state' => 'critical', 'summary' => 'Connection refused')
|
36
|
+
recovery = event.merge('state' => 'ok', 'summary' => '200 OK, 37 ms')
|
37
|
+
key = "#{event['entity']}:#{event['check']}"
|
38
|
+
|
39
|
+
puts "#{Time.now}: sending failure event for #{key}"
|
40
|
+
send_event(failure, :redis => redis)
|
41
|
+
|
42
|
+
EM.run {
|
43
|
+
|
44
|
+
EM.add_timer(stop_after) do
|
45
|
+
puts "#{Time.now}: stopping"
|
46
|
+
if recover
|
47
|
+
puts "#{Time.now}: sending recovery event for #{key}"
|
48
|
+
send_event(recovery, :redis => redis)
|
49
|
+
end
|
50
|
+
EM.stop
|
51
|
+
end
|
52
|
+
|
53
|
+
EM.add_periodic_timer(10) do
|
54
|
+
puts "#{Time.now}: sending failure event for #{key}"
|
55
|
+
send_event(failure, :redis => redis)
|
56
|
+
end
|
57
|
+
|
58
|
+
}
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
options = OpenStruct.new
|
64
|
+
options.config = nil
|
65
|
+
options.daemonize = nil
|
66
|
+
|
67
|
+
exe = File.basename(__FILE__)
|
68
|
+
|
69
|
+
optparse = OptionParser.new do |opts|
|
70
|
+
opts.banner = "Usage: #{exe} COMMAND [OPTIONS]"
|
71
|
+
|
72
|
+
opts.separator ""
|
73
|
+
opts.separator "Commands"
|
74
|
+
opts.separator " fail-and-recover"
|
75
|
+
opts.separator " fail"
|
76
|
+
opts.separator ""
|
77
|
+
opts.separator "Options"
|
78
|
+
|
79
|
+
opts.on("-c", "--config [PATH]", String, "PATH to the config file to use") do |c|
|
80
|
+
options.config = c
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("-t", "--time MINUTES", String, "MINUTES to generate failure events for") do |t|
|
84
|
+
options.minutes = t
|
85
|
+
end
|
86
|
+
|
87
|
+
opts.on("-e", "--entity ENTITY", String, "ENTITY to generate failure events for ('foo-app-01')") do |e|
|
88
|
+
options.entity = e
|
89
|
+
end
|
90
|
+
|
91
|
+
opts.on("-k", "--check CHECK", String, "CHECK to generate failure events for ('HTTP')") do |k|
|
92
|
+
options.check = k
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
optparse.parse!(ARGV)
|
97
|
+
|
98
|
+
FLAPJACK_ENV = ENV['FLAPJACK_ENV'] || 'development'
|
99
|
+
|
100
|
+
if options.config
|
101
|
+
config_file = options.config
|
102
|
+
pike "specified config file cannot be read" unless File.readable?(config_file)
|
103
|
+
else
|
104
|
+
[ 'etc/flapjack_config.yaml',
|
105
|
+
File.dirname(__FILE__) + 'etc/flapjack_config.yaml',
|
106
|
+
'/etc/flapjack/flapjack_config.yaml' ].each do |candidate|
|
107
|
+
if File.readable?(candidate)
|
108
|
+
config_file = candidate
|
109
|
+
break
|
110
|
+
else
|
111
|
+
puts "not found and/or not readable: #{candidate}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
pike "no config file specified and none found in default locations" unless config_file
|
115
|
+
end
|
116
|
+
|
117
|
+
config = Flapjack::Configuration.new
|
118
|
+
config.load(config_file)
|
119
|
+
config_env = config.all
|
120
|
+
redis_options = config.for_redis
|
121
|
+
|
122
|
+
if config_env.nil? || config_env.empty?
|
123
|
+
puts "No config data for environment '#{FLAPJACK_ENV}' found in '#{options.config}'"
|
124
|
+
exit(false)
|
125
|
+
end
|
126
|
+
|
127
|
+
options = {:redis_options => redis_options, :minutes => options.minutes,
|
128
|
+
:entity => options.entity, :check => options.check}
|
129
|
+
case ARGV[0]
|
130
|
+
when "fail-and-recover"
|
131
|
+
fail(options.merge(:recover => true))
|
132
|
+
puts " done."
|
133
|
+
when "fail"
|
134
|
+
fail(options.merge(:recover => false))
|
135
|
+
puts " done."
|
136
|
+
else
|
137
|
+
if ARGV.nil? || ARGV.empty?
|
138
|
+
puts "No command provided."
|
139
|
+
else
|
140
|
+
puts "Unknown command provided: '#{ARGV[0]}'"
|
141
|
+
end
|
142
|
+
puts "\n#{optparse}"
|
143
|
+
exit 1
|
144
|
+
end
|