cognizant 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +17 -0
  4. data/Gemfile +4 -1
  5. data/{LICENSE → License.md} +4 -2
  6. data/Rakefile +5 -0
  7. data/Readme.md +95 -0
  8. data/bin/cognizant +76 -122
  9. data/bin/cognizantd +28 -61
  10. data/cognizant.gemspec +8 -4
  11. data/examples/apps/redis-server.cz +42 -0
  12. data/examples/apps/redis-server.yml +29 -0
  13. data/examples/apps/redis-server_dsl.cz +54 -0
  14. data/examples/apps/resque.cz +17 -0
  15. data/examples/apps/thin.cz +32 -0
  16. data/examples/apps/thin.yml +48 -0
  17. data/examples/cognizantd.yml +18 -47
  18. data/features/child_process.feature +62 -0
  19. data/features/commands.feature +65 -0
  20. data/features/cpu_usage.feature +45 -0
  21. data/features/daemon.feature +12 -0
  22. data/features/flapping.feature +39 -0
  23. data/features/memory_usage.feature +45 -0
  24. data/features/shell.feature +30 -0
  25. data/features/step_definitions/common_steps.rb +14 -0
  26. data/features/step_definitions/daemon_steps.rb +25 -0
  27. data/features/step_definitions/shell_steps.rb +96 -0
  28. data/features/support/env.rb +54 -0
  29. data/lib/cognizant.rb +1 -5
  30. data/lib/cognizant/application.rb +122 -0
  31. data/lib/cognizant/application/dsl_proxy.rb +23 -0
  32. data/lib/cognizant/client.rb +61 -0
  33. data/lib/cognizant/commands.rb +164 -0
  34. data/lib/cognizant/commands/actions.rb +30 -0
  35. data/lib/cognizant/commands/help.rb +10 -0
  36. data/lib/cognizant/commands/load.rb +10 -0
  37. data/lib/cognizant/commands/shutdown.rb +7 -0
  38. data/lib/cognizant/commands/status.rb +11 -0
  39. data/lib/cognizant/commands/use.rb +15 -0
  40. data/lib/cognizant/controller.rb +17 -0
  41. data/lib/cognizant/daemon.rb +279 -0
  42. data/lib/cognizant/interface.rb +17 -0
  43. data/lib/cognizant/log.rb +25 -0
  44. data/lib/cognizant/process.rb +138 -94
  45. data/lib/cognizant/process/actions.rb +30 -41
  46. data/lib/cognizant/process/actions/restart.rb +73 -17
  47. data/lib/cognizant/process/actions/start.rb +35 -12
  48. data/lib/cognizant/process/actions/stop.rb +38 -17
  49. data/lib/cognizant/process/attributes.rb +41 -10
  50. data/lib/cognizant/process/children.rb +36 -0
  51. data/lib/cognizant/process/{condition_check.rb → condition_delegate.rb} +11 -13
  52. data/lib/cognizant/process/conditions.rb +7 -4
  53. data/lib/cognizant/process/conditions/cpu_usage.rb +5 -6
  54. data/lib/cognizant/process/conditions/memory_usage.rb +2 -6
  55. data/lib/cognizant/process/dsl_proxy.rb +23 -0
  56. data/lib/cognizant/process/execution.rb +16 -9
  57. data/lib/cognizant/process/pid.rb +16 -6
  58. data/lib/cognizant/process/status.rb +14 -2
  59. data/lib/cognizant/process/trigger_delegate.rb +57 -0
  60. data/lib/cognizant/process/triggers.rb +19 -0
  61. data/lib/cognizant/process/triggers/flapping.rb +68 -0
  62. data/lib/cognizant/process/triggers/transition.rb +22 -0
  63. data/lib/cognizant/process/triggers/trigger.rb +15 -0
  64. data/lib/cognizant/shell.rb +142 -0
  65. data/lib/cognizant/system.rb +16 -0
  66. data/lib/cognizant/system/ps.rb +1 -1
  67. data/lib/cognizant/system/signal.rb +2 -2
  68. data/lib/cognizant/util/dsl_proxy_methods_handler.rb +25 -0
  69. data/lib/cognizant/util/fixnum_percent.rb +5 -0
  70. data/lib/cognizant/util/transform_hash_keys.rb +33 -0
  71. data/lib/cognizant/validations.rb +142 -142
  72. data/lib/cognizant/version.rb +1 -1
  73. metadata +131 -71
  74. data/README.md +0 -221
  75. data/examples/redis-server.rb +0 -28
  76. data/examples/resque.rb +0 -10
  77. data/images/logo-small.png +0 -0
  78. data/images/logo.png +0 -0
  79. data/images/logo.pxm +0 -0
  80. data/lib/cognizant/logging.rb +0 -33
  81. data/lib/cognizant/process/conditions/flapping.rb +0 -57
  82. data/lib/cognizant/process/conditions/trigger_condition.rb +0 -52
  83. data/lib/cognizant/server.rb +0 -14
  84. data/lib/cognizant/server/commands.rb +0 -80
  85. data/lib/cognizant/server/daemon.rb +0 -277
  86. data/lib/cognizant/server/interface.rb +0 -86
  87. data/lib/cognizant/util/symbolize_hash_keys.rb +0 -19
@@ -4,9 +4,10 @@ require File.expand_path('../lib/cognizant/version', __FILE__)
4
4
  Gem::Specification.new do |gem|
5
5
  gem.authors = ["Gurpartap Singh"]
6
6
  gem.email = ["contact@gurpartap.com"]
7
- gem.description = "Cognizant is a process management system utility that supervises your processes, ensuring their state based on a flexible criteria."
8
- gem.summary = "Cognizant is a process management system utility that supervises your processes, ensuring their state based on a flexible criteria."
7
+ gem.description = "Cognizant is a process management framework inspired from God and Bluepill. It supervises your processes, ensuring their state based on a flexible criteria."
8
+ gem.summary = "Cognizant is a process management framework inspired from God and Bluepill. It supervises your processes, ensuring their state based on a flexible criteria."
9
9
  gem.homepage = "http://github.com/Gurpartap/cognizant"
10
+ gem.license = "MIT"
10
11
 
11
12
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
12
13
  gem.files = `git ls-files`.split("\n")
@@ -16,15 +17,18 @@ Gem::Specification.new do |gem|
16
17
  gem.version = Cognizant::VERSION
17
18
 
18
19
  gem.add_development_dependency "rake"
19
- gem.add_development_dependency "redcarpet"
20
+ gem.add_development_dependency "ruby-graphviz"
20
21
  gem.add_development_dependency "yard"
22
+ gem.add_development_dependency "kramdown"
23
+ gem.add_development_dependency "aruba"
21
24
 
22
25
  # cognizantd
23
26
  gem.add_dependency "eventmachine"
24
27
  gem.add_dependency "state_machine"
25
28
  gem.add_dependency "activesupport"
29
+ gem.add_dependency "logging"
26
30
 
27
31
  # cognizant
28
- gem.add_dependency "gli"
32
+ gem.add_dependency "commander"
29
33
  gem.add_dependency "formatador"
30
34
  end
@@ -0,0 +1,42 @@
1
+ Cognizant.application("redis-example") do |app|
2
+ app.pids_dir = "~/.cognizant/redis-example/pids/"
3
+ app.logs_dir = "~/.cognizant/redis-example/logs/"
4
+
5
+ # 2 slave instances to master at port 6000.
6
+ 3.times do |i|
7
+ app.monitor("redis-server-600#{i}") do |process|
8
+ process.autostart = true
9
+ # process.name = "redis-server-600#{i}" # Same thing as above.
10
+ process.group = "redis"
11
+ # process.uid = "redis"
12
+ # process.gid = "redis"
13
+ process.start_command = "redis-server -"
14
+ process.ping_command = "redis-cli -p 600#{i} PING"
15
+
16
+ process.daemonize!
17
+ slaveof = i == 0 ? "" : "slaveof 127.0.0.1 6000"
18
+ process.start_with_input = <<-heredoc
19
+ daemonize no
20
+ port 600#{i}
21
+ #{slaveof}
22
+ heredoc
23
+
24
+ # process.check(:always_true, :every => 2.seconds, :times => 3) do |p|
25
+ # `say "Boom!"`
26
+ # end
27
+
28
+ process.check(:transition, :from => :running, :to => :stopped) do |p|
29
+ `say --rate 250 "A process has stopped!"`
30
+ end
31
+
32
+ # :retry_after => 0 means do not retry.
33
+ process.check(:flapping, :times => 5, :within => 30.seconds, :retry_after => 7.seconds)
34
+
35
+ process.check(:cpu_usage, :every => 5.seconds, :above => 60.percent, :times => [3, 5], :do => :restart)
36
+ process.check(:memory_usage, :every => 5.seconds, :above => 100.megabytes, :times => [3, 5]) do |p|
37
+ # Send email or something.
38
+ p.restart # Restart is the default anyways.
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ defaults: &defaults
2
+ autostart: false
3
+ group: redis
4
+ start_command: /usr/local/bin/redis-server -
5
+ stop_signals: [TERM, INT]
6
+ checks:
7
+ cpu_usage:
8
+ every: 3
9
+ above: 60
10
+ times: 3
11
+ do: restart
12
+ memory_usage:
13
+ every: 5 # Seconds.
14
+ above: 1220608 # Bytes.
15
+ times: [3, 5] # Three out of five times.
16
+ do: stop # Defaults to restart.
17
+
18
+ applications:
19
+ example:
20
+ monitor:
21
+ redis-server-6666:
22
+ <<: *defaults
23
+ start_with_input: "daemonize no\nport 6666"
24
+ ping_command: redis-cli -p 6666 PING
25
+ redis-server-7777:
26
+ <<: *defaults
27
+ start_with_input: "daemonize no\nport 7777"
28
+ ping_command: redis-cli -p 7777 PING
29
+ stop_command: redis-cli -p 7777 SHUTDOWN
@@ -0,0 +1,54 @@
1
+ # Cognizant.application "redis-example-dsl" do
2
+ # pids_dir "~/.cognizant/redis-example-dsl/pids/"
3
+ # logs_dir "~/.cognizant/redis-example-dsl/logs/"
4
+ #
5
+ # monitor "redis-server-7000" do
6
+ # autostart!
7
+ # group "redis"
8
+ # start_command "/usr/local/bin/redis-server -"
9
+ # start_with_input "daemonize no\nport 6666"
10
+ # ping_command "redis-cli -p 6666 PING"
11
+ # end
12
+ # end
13
+
14
+ # Not using dsl for app to use some Ruby in the immediate block.
15
+ Cognizant.application "redis-example-dsl" do |app|
16
+ app.pids_dir = "~/.cognizant/redis-example-dsl/pids/"
17
+ app.logs_dir = "~/.cognizant/redis-example-dsl/logs/"
18
+
19
+ # 2 slave instances to master at port 7000.
20
+ 3.times do |i|
21
+ slaveof = i == 0 ? "" : "slaveof 127.0.0.1 7000" # Any custom code has to be outside the monitor block.
22
+
23
+ app.monitor do
24
+ autostart!
25
+ name "redis-server-700#{i}"
26
+ group "redis"
27
+ start_command "redis-server -"
28
+ ping_command "redis-cli -p 700#{i} PING"
29
+
30
+ daemonize!
31
+ start_with_input <<-heredoc
32
+ daemonize no
33
+ port 700#{i}
34
+ #{slaveof}
35
+ heredoc
36
+
37
+ # check :always_true, :every => 2.seconds, :times => 3 do |p|
38
+ # `say "Boom!"`
39
+ # end
40
+
41
+ check :transition, :from => :running, :to => :stopped do
42
+ `say --rate 250 "A process has stopped!"`
43
+ end
44
+
45
+ check :flapping, :times => 5, :within => 30.seconds, :retry_after => 7.seconds
46
+
47
+ check :cpu_usage, :every => 3.seconds, :above => 60.percent, :times => 3, :do => :restart
48
+ check :memory_usage, :every => 5.seconds, :above => 100.megabytes, :times => [3, 5] do |p|
49
+ # Send email or something.
50
+ p.restart # Restart is the default anyways.
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ Cognizant.application("my-web-app") do |app|
2
+ 5.times do |i|
3
+ app.monitor "resque-worker-#{i}" do |process|
4
+ process.group = "resque"
5
+ process.uid = "deploy"
6
+ process.gid = "deploy"
7
+ process.chdir = "/apps/example/current/"
8
+ process.env = { "QUEUE" => "*", "RACK_ENV" => "production" }
9
+ process.start_command = "bundle exec rake resque:work"
10
+
11
+ process.monitor_children do
12
+ check :memory_usage, :every => 5.seconds, :above => 100.megabytes, :times => [2, 3], :do => :stop
13
+ stop_signals ["TERM", "INT", "KILL"]
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,32 @@
1
+ app_root = "/apps/acmecorp.com"
2
+ servers = 5
3
+ port = 4000
4
+
5
+ Cognizant.application "acmecorp.com" do |app|
6
+ servers.times do |n|
7
+ app.monitor "thin-#{n}" do
8
+ # autostart!
9
+ group "thin"
10
+ uid "www-data"
11
+ gid "www-data"
12
+
13
+ env RACK_ENV: "production"
14
+ chdir "#{app_root}/current"
15
+
16
+ daemonize false
17
+ pidfile "#{app_root}/shared/tmp/pids/thin.400#{n}.pid"
18
+
19
+ start_command "bundle exec thin start --only #{n} --servers #{servers} --port #{port}"
20
+ stop_command "bundle exec thin stop --only #{n} --servers #{servers} --port #{port}"
21
+ restart_command "bundle exec thin restart --only #{n} --servers #{servers} --port #{port}"
22
+
23
+ check :flapping, times: 3, within: 1.minute, retry_after: 15.seconds, retries: 10
24
+ check :transition, from: :running, to: :stopped do |process|
25
+ `say a thin server has stopped` # send an email, etc.
26
+ end
27
+
28
+ check :cpu_usage, above: 50.percent, every: 5.seconds, times: 5, do: :restart
29
+ check :memory_usage, above: 300.megabytes, every: 5.seconds, times: [3, 5], do: :restart
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,48 @@
1
+ thin: &thin
2
+ # autostart: true
3
+ group: thin
4
+ uid: www-data
5
+ gid: www-data
6
+ env:
7
+ RACK_ENV: production
8
+ chdir: /apps/acmecorp.com/current
9
+ daemonize: false
10
+ checks:
11
+ flapping:
12
+ times: 3
13
+ within: 1
14
+ retry_after: 15
15
+ retries: 10
16
+ # transition trigger is not useful in YAML config as blocks are not possible
17
+ cpu_usage:
18
+ above: 50
19
+ every: 5
20
+ times: 5
21
+ do: stop
22
+ memory_usage:
23
+ above: 314572800 # 300 megabytes in bytes
24
+ every: 5
25
+ times: [3, 5]
26
+ do: stop
27
+
28
+ applications:
29
+ acmecorp.com:
30
+ monitor:
31
+ thin-0:
32
+ <<: *thin
33
+ start_command: bundle exec thin start --only 0 --servers 3 --port 5000
34
+ stop_command: bundle exec thin stop --only 0 --servers 3 --port 5000
35
+ restart_command: bundle exec thin restart --only 0 --servers 3 --port 5000
36
+ pidfile: /apps/acmecorp.com/shared/tmp/pids/thin.5000.pid
37
+ thin-1:
38
+ <<: *thin
39
+ start_command: bundle exec thin start --only 1 --servers 3 --port 5000
40
+ stop_command: bundle exec thin stop --only 1 --servers 3 --port 5000
41
+ restart_command: bundle exec thin restart --only 1 --servers 3 --port 5000
42
+ pidfile: /apps/acmecorp.com/shared/tmp/pids/thin.5001.pid
43
+ thin-2:
44
+ <<: *thin
45
+ start_command: bundle exec thin start --only 2 --servers 3 --port 5000
46
+ stop_command: bundle exec thin stop --only 2 --servers 3 --port 5000
47
+ restart_command: bundle exec thin restart --only 2 --servers 3 --port 5000
48
+ pidfile: /apps/acmecorp.com/shared/tmp/pids/thin.5002.pid
@@ -1,50 +1,21 @@
1
1
  ---
2
2
  daemonize: false
3
- pidfile: ~/.cognizant/cognizantd.pid
4
- logfile: ~/.cognizant/cognizantd.log
5
- socket: ~/.cognizant/cognizantd.sock
6
- pids_dir: ~/.cognizant/pids/
7
- logs_dir: ~/.cognizant/logs/
3
+ loglevel: debug
8
4
 
9
- monitor: {
10
- redis-server-1: {
11
- autostart: false,
12
- group: redis,
13
- start_command: /usr/local/bin/redis-server -,
14
- start_with_input: "daemonize no\nport 6666",
15
- ping_command: redis-cli -p 6666 PING,
16
- stop_signals: [TERM, INT],
17
- checks: {
18
- cpu_usage: {
19
- every: 3,
20
- above: 60,
21
- times: 3,
22
- do: restart
23
- },
24
- memory_usage: {
25
- every: 5, # Seconds.
26
- above: 1220608, # Bytes.
27
- times: [3, 5], # Three out of five times.
28
- do: stop # Defaults to restart.
29
- }
30
- }
31
- },
32
- redis-server-2: {
33
- autostart: false,
34
- group: redis,
35
- start_command: /usr/local/bin/redis-server -,
36
- start_with_input: "daemonize no\nport 7777",
37
- ping_command: redis-cli -p 7777 PING,
38
- stop_command: redis-cli -p 7777 SHUTDOWN
39
- },
40
- sleep: {
41
- start_command: sleep 3,
42
- checks: {
43
- flapping: {
44
- times: 4,
45
- within: 15, # Seconds.
46
- retry_after: 30 # Seconds.
47
- }
48
- }
49
- }
50
- }
5
+ load:
6
+ - ./examples/apps/*.cz
7
+ - ./examples/apps/*.yml
8
+
9
+ applications:
10
+ sleep-example:
11
+ monitor:
12
+ sleep:
13
+ autostart: false
14
+ start_command: sleep 3
15
+ uid: nobody
16
+ gid: nobody
17
+ checks:
18
+ flapping:
19
+ times: 4
20
+ within: 15 # seconds.
21
+ retry_after: 30 # seconds.
@@ -0,0 +1,62 @@
1
+ Feature: Child Process
2
+
3
+ Forks (children) of a process can be checked for conditions and triggers
4
+ similar to their parent process.
5
+
6
+ Background:
7
+ Given a file named "fork_machine.rb" with:
8
+ """ruby
9
+ require 'timeout'
10
+ $0 = File.basename(__FILE__) # Useful identification when debugging.
11
+ children = []
12
+ Signal.trap('TERM') do
13
+ children.each do |child|
14
+ Process.kill('INT', child)
15
+ end
16
+ end
17
+ children << fork do
18
+ Signal.trap 'INT' do
19
+ exit
20
+ end
21
+ data = ''
22
+ Timeout::timeout(60) do
23
+ loop do
24
+ data += '*' * 100
25
+ end
26
+ end
27
+ data = nil
28
+ end
29
+ Process.waitall
30
+ """
31
+ Given a file named "monitor.cz" with:
32
+ """ruby
33
+ Cognizant.application 'child_process_app' do
34
+ pids_dir './cognizant/pids/'
35
+ logs_dir './cognizant/logs/'
36
+ monitor 'fork_machine' do
37
+ autostart false
38
+ daemonize!
39
+ start_command 'ruby ./fork_machine.rb'
40
+ stop_signals ['TERM']
41
+ monitor_children do
42
+ check :memory_usage, :every => 2.seconds, :above => 10.megabytes, :times => 3, :do => :stop
43
+ stop_signals ['INT']
44
+ end
45
+ end
46
+ end
47
+ """
48
+
49
+ @daemon
50
+ @shell
51
+ Scenario: Check child process memory usage
52
+ Given the daemon is running
53
+ And the shell is running
54
+
55
+ When I run "load monitor.cz" successfully in the shell
56
+ And I run "use child_process_app" successfully in the shell
57
+ Then the status of "fork_machine" should be "stopped"
58
+
59
+ When I run "start fork_machine" successfully in the shell
60
+ Then the status of "fork_machine" should be "running"
61
+
62
+ And the status of "fork_machine" should be "stopped"
@@ -0,0 +1,65 @@
1
+ Feature: Commands
2
+
3
+ Cognizant provides a number of commands to maually change the state of a
4
+ process as a part of its maintenance.
5
+
6
+ Background:
7
+ Given a file named "sleep_process.cz" with:
8
+ """ruby
9
+ Cognizant.application 'sleep_app' do
10
+ pids_dir './cognizant/pids/'
11
+ logs_dir './cognizant/logs/'
12
+ monitor 'sleep_process' do
13
+ autostart false
14
+ daemonize!
15
+ start_command 'sleep 60'
16
+ end
17
+ end
18
+ """
19
+
20
+ @daemon
21
+ @shell
22
+ Scenario: Run all maintenance commands for a sample sleep process
23
+ Given the daemon is running
24
+ And the shell is running
25
+
26
+ When I run "load sleep_process.cz" successfully in the shell
27
+ And I run "use sleep_app" successfully in the shell
28
+ Then the status of "sleep_process" is "stopped"
29
+
30
+ When I run "start sleep_process" successfully in the shell
31
+ Then the status of "sleep_process" should be "running"
32
+
33
+ When I run "stop sleep_process" successfully in the shell
34
+ Then the status of "sleep_process" should be "stopped"
35
+
36
+ When I run "restart sleep_process" successfully in the shell
37
+ Then the status of "sleep_process" should be "running"
38
+
39
+ When I run "unmonitor sleep_process" successfully in the shell
40
+ Then the status of "sleep_process" should be "unmonitored"
41
+
42
+ When I run "monitor sleep_process" successfully in the shell
43
+ Then the status of "sleep_process" should be "running"
44
+
45
+ When I run "stop sleep_process" successfully in the shell
46
+ Then the status of "sleep_process" should be "stopped"
47
+
48
+ @daemon
49
+ @shell
50
+ Scenario: Run the help command
51
+ Given the daemon is running
52
+ And the shell is running
53
+
54
+ When I run "help" in the shell
55
+ Then I should see "You can run the following commands" in the shell
56
+
57
+ @daemon
58
+ @shell
59
+ Scenario: Shut down the daemon via command
60
+ Given the daemon is running
61
+ And the shell is running
62
+
63
+ When I run "shutdown" in the shell
64
+ Then I should see "The daemon has been shutdown successfuly." in the shell
65
+ And a process named "cognizantd" should not be running