mojombo-god 0.7.7

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.
Files changed (108) hide show
  1. data/History.txt +255 -0
  2. data/Manifest.txt +107 -0
  3. data/README.txt +59 -0
  4. data/Rakefile +35 -0
  5. data/bin/god +127 -0
  6. data/examples/events.god +84 -0
  7. data/examples/gravatar.god +54 -0
  8. data/examples/single.god +66 -0
  9. data/ext/god/extconf.rb +55 -0
  10. data/ext/god/kqueue_handler.c +123 -0
  11. data/ext/god/netlink_handler.c +167 -0
  12. data/init/god +42 -0
  13. data/lib/god.rb +644 -0
  14. data/lib/god/behavior.rb +52 -0
  15. data/lib/god/behaviors/clean_pid_file.rb +21 -0
  16. data/lib/god/behaviors/clean_unix_socket.rb +21 -0
  17. data/lib/god/behaviors/notify_when_flapping.rb +51 -0
  18. data/lib/god/cli/command.rb +206 -0
  19. data/lib/god/cli/run.rb +177 -0
  20. data/lib/god/cli/version.rb +23 -0
  21. data/lib/god/condition.rb +96 -0
  22. data/lib/god/conditions/always.rb +23 -0
  23. data/lib/god/conditions/complex.rb +86 -0
  24. data/lib/god/conditions/cpu_usage.rb +80 -0
  25. data/lib/god/conditions/degrading_lambda.rb +52 -0
  26. data/lib/god/conditions/disk_usage.rb +27 -0
  27. data/lib/god/conditions/flapping.rb +128 -0
  28. data/lib/god/conditions/http_response_code.rb +168 -0
  29. data/lib/god/conditions/lambda.rb +25 -0
  30. data/lib/god/conditions/memory_usage.rb +82 -0
  31. data/lib/god/conditions/process_exits.rb +72 -0
  32. data/lib/god/conditions/process_running.rb +74 -0
  33. data/lib/god/conditions/tries.rb +44 -0
  34. data/lib/god/configurable.rb +57 -0
  35. data/lib/god/contact.rb +106 -0
  36. data/lib/god/contacts/email.rb +95 -0
  37. data/lib/god/dependency_graph.rb +41 -0
  38. data/lib/god/diagnostics.rb +37 -0
  39. data/lib/god/driver.rb +108 -0
  40. data/lib/god/errors.rb +24 -0
  41. data/lib/god/event_handler.rb +111 -0
  42. data/lib/god/event_handlers/dummy_handler.rb +13 -0
  43. data/lib/god/event_handlers/kqueue_handler.rb +17 -0
  44. data/lib/god/event_handlers/netlink_handler.rb +13 -0
  45. data/lib/god/logger.rb +120 -0
  46. data/lib/god/metric.rb +59 -0
  47. data/lib/god/process.rb +325 -0
  48. data/lib/god/registry.rb +32 -0
  49. data/lib/god/simple_logger.rb +53 -0
  50. data/lib/god/socket.rb +96 -0
  51. data/lib/god/sugar.rb +47 -0
  52. data/lib/god/system/portable_poller.rb +42 -0
  53. data/lib/god/system/process.rb +42 -0
  54. data/lib/god/system/slash_proc_poller.rb +82 -0
  55. data/lib/god/task.rb +487 -0
  56. data/lib/god/timeline.rb +25 -0
  57. data/lib/god/trigger.rb +43 -0
  58. data/lib/god/watch.rb +183 -0
  59. data/test/configs/child_events/child_events.god +44 -0
  60. data/test/configs/child_events/simple_server.rb +3 -0
  61. data/test/configs/child_polls/child_polls.god +37 -0
  62. data/test/configs/child_polls/simple_server.rb +12 -0
  63. data/test/configs/complex/complex.god +59 -0
  64. data/test/configs/complex/simple_server.rb +3 -0
  65. data/test/configs/contact/contact.god +74 -0
  66. data/test/configs/contact/simple_server.rb +3 -0
  67. data/test/configs/daemon_events/daemon_events.god +37 -0
  68. data/test/configs/daemon_events/simple_server.rb +8 -0
  69. data/test/configs/daemon_events/simple_server_stop.rb +11 -0
  70. data/test/configs/daemon_polls/daemon_polls.god +17 -0
  71. data/test/configs/daemon_polls/simple_server.rb +6 -0
  72. data/test/configs/degrading_lambda/degrading_lambda.god +31 -0
  73. data/test/configs/degrading_lambda/tcp_server.rb +15 -0
  74. data/test/configs/matias/matias.god +50 -0
  75. data/test/configs/real.rb +59 -0
  76. data/test/configs/running_load/running_load.god +16 -0
  77. data/test/configs/stress/simple_server.rb +3 -0
  78. data/test/configs/stress/stress.god +15 -0
  79. data/test/configs/task/logs/.placeholder +0 -0
  80. data/test/configs/task/task.god +26 -0
  81. data/test/configs/test.rb +61 -0
  82. data/test/helper.rb +151 -0
  83. data/test/suite.rb +6 -0
  84. data/test/test_behavior.rb +21 -0
  85. data/test/test_condition.rb +50 -0
  86. data/test/test_conditions_disk_usage.rb +56 -0
  87. data/test/test_conditions_http_response_code.rb +109 -0
  88. data/test/test_conditions_process_running.rb +44 -0
  89. data/test/test_conditions_tries.rb +67 -0
  90. data/test/test_contact.rb +109 -0
  91. data/test/test_dependency_graph.rb +62 -0
  92. data/test/test_driver.rb +11 -0
  93. data/test/test_event_handler.rb +80 -0
  94. data/test/test_god.rb +598 -0
  95. data/test/test_handlers_kqueue_handler.rb +16 -0
  96. data/test/test_logger.rb +63 -0
  97. data/test/test_metric.rb +72 -0
  98. data/test/test_process.rb +246 -0
  99. data/test/test_registry.rb +15 -0
  100. data/test/test_socket.rb +42 -0
  101. data/test/test_sugar.rb +42 -0
  102. data/test/test_system_portable_poller.rb +17 -0
  103. data/test/test_system_process.rb +30 -0
  104. data/test/test_task.rb +262 -0
  105. data/test/test_timeline.rb +37 -0
  106. data/test/test_trigger.rb +59 -0
  107. data/test/test_watch.rb +279 -0
  108. metadata +186 -0
@@ -0,0 +1,42 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSugar < Test::Unit::TestCase
4
+ def test_seconds
5
+ assert_equal 1, 1.seconds
6
+ assert_equal 1, 1.second
7
+ end
8
+
9
+ def test_minutes
10
+ assert_equal 60, 1.minutes
11
+ assert_equal 60, 1.minute
12
+ end
13
+
14
+ def test_hours
15
+ assert_equal 3600, 1.hours
16
+ assert_equal 3600, 1.hour
17
+ end
18
+
19
+ def test_days
20
+ assert_equal 86400, 1.days
21
+ assert_equal 86400, 1.day
22
+ end
23
+
24
+ def test_kilobytes
25
+ assert_equal 1, 1.kilobytes
26
+ assert_equal 1, 1.kilobyte
27
+ end
28
+
29
+ def test_megabytes
30
+ assert_equal 1024, 1.megabytes
31
+ assert_equal 1024, 1.megabyte
32
+ end
33
+
34
+ def test_gigabytes
35
+ assert_equal 1024 ** 2, 1.gigabytes
36
+ assert_equal 1024 ** 2, 1.gigabyte
37
+ end
38
+
39
+ def test_percent
40
+ assert_equal 1, 1.percent
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSystemPortablePoller < Test::Unit::TestCase
4
+ def setup
5
+ pid = Process.pid
6
+ @process = System::PortablePoller.new(pid)
7
+ end
8
+
9
+ def test_time_string_to_seconds
10
+ assert_equal 0, @process.bypass.time_string_to_seconds('0:00:00')
11
+ assert_equal 0, @process.bypass.time_string_to_seconds('0:00:55')
12
+ assert_equal 27, @process.bypass.time_string_to_seconds('0:27:32')
13
+ assert_equal 75, @process.bypass.time_string_to_seconds('1:15:13')
14
+ assert_equal 735, @process.bypass.time_string_to_seconds('12:15:13')
15
+ end
16
+ end
17
+
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSystemProcess < Test::Unit::TestCase
4
+ def setup
5
+ pid = Process.pid
6
+ @process = System::Process.new(pid)
7
+ end
8
+
9
+ def test_exists_should_return_true_for_running_process
10
+ assert_equal true, @process.exists?
11
+ end
12
+
13
+ def test_exists_should_return_false_for_non_existant_process
14
+ assert_equal false, System::Process.new(9999999).exists?
15
+ end
16
+
17
+ def test_memory
18
+ assert_kind_of Integer, @process.memory
19
+ assert @process.memory > 0
20
+ end
21
+
22
+ def test_percent_memory
23
+ assert_kind_of Float, @process.percent_memory
24
+ end
25
+
26
+ def test_percent_cpu
27
+ assert_kind_of Float, @process.percent_cpu
28
+ end
29
+ end
30
+
data/test/test_task.rb ADDED
@@ -0,0 +1,262 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTask < Test::Unit::TestCase
4
+ def setup
5
+ God.internal_init
6
+ @task = Task.new
7
+ @task.name = 'foo'
8
+ @task.valid_states = [:foo, :bar]
9
+ @task.initial_state = :foo
10
+ @task.interval = 5
11
+ @task.prepare
12
+ end
13
+
14
+ # valid?
15
+
16
+ def test_valid_should_return_false_if_no_name
17
+ @task.name = nil
18
+ no_stdout do
19
+ assert !@task.valid?
20
+ end
21
+ end
22
+
23
+ def test_valid_should_return_false_if_no_valid_states
24
+ @task.valid_states = nil
25
+ no_stdout do
26
+ assert !@task.valid?
27
+ end
28
+ end
29
+
30
+ def test_valid_should_return_false_if_no_initial_state
31
+ @task.initial_state = nil
32
+ no_stdout do
33
+ assert !@task.valid?
34
+ end
35
+ end
36
+
37
+ # transition
38
+
39
+ def test_transition_should_be_always_if_no_block_was_given
40
+ @task.transition(:foo, :bar)
41
+
42
+ assert 1, @task.metrics.size
43
+ assert Conditions::Always, @task.metrics.keys.first.class
44
+ end
45
+
46
+ # method_missing
47
+
48
+ def test_method_missing_should_create_accessor_for_states
49
+ assert_nothing_raised do
50
+ @task.foo = 'testing'
51
+ end
52
+ end
53
+
54
+ def test_method_missing_should_raise_for_non_states
55
+ assert_raise NoMethodError do
56
+ @task.baz = 5
57
+ end
58
+ end
59
+
60
+ def test_method_missing_should_raise_for_non_setters
61
+ assert_raise NoMethodError do
62
+ @task.baz
63
+ end
64
+ end
65
+
66
+ # action
67
+
68
+ def test_action_should_send_string_commands_to_system
69
+ @task.foo = 'foo'
70
+ Thread.current.stubs(:==).returns(true)
71
+ @task.expects(:system).with('foo')
72
+ no_stdout { @task.action(:foo, nil) }
73
+ end
74
+
75
+ def test_action_should_call_lambda_commands
76
+ @task.foo = lambda { }
77
+ Thread.current.stubs(:==).returns(true)
78
+ @task.foo.expects(:call)
79
+ no_stdout { @task.action(:foo, nil) }
80
+ end
81
+
82
+ def test_action_should_raise_not_implemented_on_non_string_or_lambda_action
83
+ Thread.current.stubs(:==).returns(true)
84
+ assert_raise NotImplementedError do
85
+ @task.foo = 7
86
+ @task.action(:foo, nil)
87
+ end
88
+ end
89
+
90
+ def test_action_from_outside_driver_should_send_message_to_driver
91
+ @task.foo = 'foo'
92
+ @task.driver.expects(:message).with(:action, [:foo, nil])
93
+ @task.action(:foo, nil)
94
+ end
95
+
96
+ # attach
97
+
98
+ def test_attach_should_schedule_for_poll_condition
99
+ c = Conditions::FakePollCondition.new
100
+ @task.driver.expects(:schedule).with(c, 0)
101
+ @task.attach(c)
102
+ end
103
+
104
+ def test_attach_should_regsiter_for_event_condition
105
+ c = Conditions::FakeEventCondition.new
106
+ c.expects(:register)
107
+ @task.attach(c)
108
+ end
109
+
110
+ # detach
111
+
112
+ def test_detach_should_reset_poll_condition
113
+ c = Conditions::FakePollCondition.new
114
+ c.expects(:reset)
115
+ c.expects(:deregister).never
116
+ @task.detach(c)
117
+ end
118
+
119
+ def test_detach_should_deregister_event_conditions
120
+ c = Conditions::FakeEventCondition.new
121
+ c.expects(:deregister).once
122
+ @task.detach(c)
123
+ end
124
+
125
+ # trigger
126
+
127
+ def test_trigger_should_send_message_to_driver
128
+ c = Conditions::FakePollCondition.new
129
+ @task.driver.expects(:message).with(:handle_event, [c])
130
+ @task.trigger(c)
131
+ end
132
+
133
+ # handle_poll
134
+
135
+ def test_handle_poll_no_change_should_reschedule
136
+ c = Conditions::FakePollCondition.new
137
+ c.watch = @task
138
+ c.interval = 10
139
+
140
+ m = Metric.new(@task, {true => :up})
141
+ @task.directory[c] = m
142
+
143
+ c.expects(:test).returns(false)
144
+ @task.driver.expects(:schedule)
145
+
146
+ no_stdout do
147
+ @task.handle_poll(c)
148
+ end
149
+ end
150
+
151
+ def test_handle_poll_change_should_move
152
+ c = Conditions::FakePollCondition.new
153
+ c.watch = @task
154
+ c.interval = 10
155
+
156
+ m = Metric.new(@task, {true => :up})
157
+ @task.directory[c] = m
158
+
159
+ c.expects(:test).returns(true)
160
+ @task.expects(:move).with(:up)
161
+
162
+ no_stdout do
163
+ @task.handle_poll(c)
164
+ end
165
+ end
166
+
167
+ def test_handle_poll_should_use_overridden_transition
168
+ c = Conditions::Tries.new
169
+ c.watch = @task
170
+ c.times = 1
171
+ c.transition = :start
172
+ c.prepare
173
+
174
+ m = Metric.new(@task, {true => :up})
175
+ @task.directory[c] = m
176
+
177
+ @task.expects(:move).with(:start)
178
+
179
+ no_stdout do
180
+ @task.handle_poll(c)
181
+ end
182
+ end
183
+
184
+ def test_handle_poll_should_notify_if_triggering
185
+ c = Conditions::FakePollCondition.new
186
+ c.watch = @task
187
+ c.interval = 10
188
+ c.notify = 'tom'
189
+
190
+ m = Metric.new(@task, {true => :up})
191
+ @task.directory[c] = m
192
+
193
+ c.expects(:test).returns(true)
194
+ @task.expects(:notify)
195
+
196
+ no_stdout do
197
+ @task.handle_poll(c)
198
+ end
199
+ end
200
+
201
+ def test_handle_poll_should_not_notify_if_not_triggering
202
+ c = Conditions::FakePollCondition.new
203
+ c.watch = @task
204
+ c.interval = 10
205
+ c.notify = 'tom'
206
+
207
+ m = Metric.new(@task, {true => :up})
208
+ @task.directory[c] = m
209
+
210
+ c.expects(:test).returns(false)
211
+ @task.expects(:notify).never
212
+
213
+ no_stdout do
214
+ @task.handle_poll(c)
215
+ end
216
+ end
217
+
218
+ # handle_event
219
+
220
+ def test_handle_event_should_move
221
+ c = Conditions::FakeEventCondition.new
222
+ c.watch = @task
223
+
224
+ m = Metric.new(@task, {true => :up})
225
+ @task.directory[c] = m
226
+
227
+ @task.expects(:move).with(:up)
228
+
229
+ no_stdout do
230
+ @task.handle_event(c)
231
+ end
232
+ end
233
+
234
+ def test_handle_event_should_notify_if_triggering
235
+ c = Conditions::FakeEventCondition.new
236
+ c.watch = @task
237
+ c.notify = 'tom'
238
+
239
+ m = Metric.new(@task, {true => :up})
240
+ @task.directory[c] = m
241
+
242
+ @task.expects(:notify)
243
+
244
+ no_stdout do
245
+ @task.handle_event(c)
246
+ end
247
+ end
248
+
249
+ def test_handle_event_should_not_notify_if_no_notify_set
250
+ c = Conditions::FakeEventCondition.new
251
+ c.watch = @task
252
+
253
+ m = Metric.new(@task, {true => :up})
254
+ @task.directory[c] = m
255
+
256
+ @task.expects(:notify).never
257
+
258
+ no_stdout do
259
+ @task.handle_event(c)
260
+ end
261
+ end
262
+ end
@@ -0,0 +1,37 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTimeline < Test::Unit::TestCase
4
+ def setup
5
+ @timeline = Timeline.new(5)
6
+ end
7
+
8
+ def test_new_should_be_empty
9
+ assert_equal 0, @timeline.size
10
+ end
11
+
12
+ def test_should_not_grow_to_more_than_size
13
+ (1..10).each do |i|
14
+ @timeline.push(i)
15
+ end
16
+
17
+ assert_equal [6, 7, 8, 9, 10], @timeline
18
+ end
19
+
20
+ def test_clear_should_clear_array
21
+ @timeline << 1
22
+ assert_equal [1], @timeline
23
+ assert_equal [], @timeline.clear
24
+ end
25
+
26
+ # def test_benchmark
27
+ # require 'benchmark'
28
+ #
29
+ # count = 1_000_000
30
+ #
31
+ # t = Timeline.new(10)
32
+ #
33
+ # Benchmark.bmbm do |x|
34
+ # x.report("go") { count.times { t.push(5) } }
35
+ # end
36
+ # end
37
+ end
@@ -0,0 +1,59 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTrigger < Test::Unit::TestCase
4
+ def setup
5
+ Trigger.reset
6
+ end
7
+
8
+ # base case
9
+
10
+ def test_should_have_empty_triggers
11
+ assert_equal({}, Trigger.triggers)
12
+ end
13
+
14
+ # register
15
+
16
+ def test_register_should_add_condition_to_triggers
17
+ c = Condition.new
18
+ c.watch = stub(:name => 'foo')
19
+ Trigger.register(c)
20
+
21
+ assert_equal({'foo' => [c]}, Trigger.triggers)
22
+ end
23
+
24
+ def test_register_should_add_condition_to_triggers_twice
25
+ watch = stub(:name => 'foo')
26
+ c = Condition.new
27
+ c.watch = watch
28
+ Trigger.register(c)
29
+
30
+ c2 = Condition.new
31
+ c2.watch = watch
32
+ Trigger.register(c2)
33
+
34
+ assert_equal({'foo' => [c, c2]}, Trigger.triggers)
35
+ end
36
+
37
+ # deregister
38
+
39
+ def test_deregister_should_remove_condition_from_triggers
40
+ c = Condition.new
41
+ c.watch = stub(:name => 'foo')
42
+ Trigger.register(c)
43
+ Trigger.deregister(c)
44
+
45
+ assert_equal({}, Trigger.triggers)
46
+ end
47
+
48
+ # broadcast
49
+
50
+ def test_broadcast_should_call_process_on_each_condition
51
+ c = Condition.new
52
+ c.watch = stub(:name => 'foo')
53
+ Trigger.register(c)
54
+
55
+ c.expects(:process).with(:state_change, [:up, :start])
56
+
57
+ Trigger.broadcast(c.watch, :state_change, [:up, :start])
58
+ end
59
+ end