Cookbook : monit_wrapper
monit_wrapper
This cookbook simplifies setting up services using Monit.
Examples
Custom Monit configuration template
Create a configuration template in your cookbook my_cookbook/templates/default/monit/my_service.conf.erb
:
check process <%= @service_name %>
matching '<%= @cmd_line_pattern %>'
every 1 cycles
start program "/bin/bash -c 'exec <%= @cmd_line %>'"
as uid <%= @user %> as gid <%= @user %>
stop program "/usr/bin/pkill -u <%= @user %> -f '<%= @cmd_line_pattern %>'"
as uid <%= @user %> as gid <%= @user %>
In my_cookbook/recipes/default.rb
:
my_service_name = '...'
command_line = '/usr/local/bin/my_service_executable --port 3456'
monit_wrapper_monitor my_service_name do
template_cookbook 'my_cookbook'
template_source 'monit/my_service.conf.erb'
variables cmd_line: command_line,
cmd_line_pattern: command_line,
user: user
end
monit_wrapper_notify_if_not_running monit_service_name
monit_wrapper_service my_service_name do
subscribes :restart, "monit_wrapper_monitor[#{my_service_name}]", :delayed
subscribes :restart, "monit_wrapper_notify_if_not_running[#{my_service_name}]", :delayed
subscribes :restart, "package[#{my_service_name}]", :delayed
end
Launching and monitoring a process with an existing init
If you have a service with an existing /etc/init.d
script, you can use this cookbook to create
a Monit configuration file to monitor that service. This makes use of the default Monit
configuration template
this cookbook provides.
my_sevice_name = 'my-service'
monit_wrapper_monitor my_service_name do
action :create
pattern '...'
end
monit_wrapper_notify_if_not_running my_service_name do
monit_wrapper_service service_name do
subscribes :restart, "package[#{service_name}]", :delayed
subscribes :restart, "monit_wrapper_monitor[#{service_name}]", :delayed
subscribes :restart, "monit_wrapper_notify_if_not_running[#{service_name}]",
:delayed
end
License
Apache License 2.0
https://www.apache.org/licenses/LICENSE-2.0
Cookbook Documentation
Recipes Summary
Lightweight Resources
Actions
Action |
Description |
create |
Creates a Monit service configuration file |
delete |
Deletes a Monit service configuration file |
Attributes
Attribute |
Description |
pid_file |
Specifies the pid_file parameter of our default Monit service configuration template. |
pattern |
Specifies the pattern parameter (the command line regular expression) of our default Monit service
configuration template. |
java_class |
If this is specified, the command line regular expression is constructed automatically that
matches Java processes running the given class. |
variables |
Additional variables to be used with the Monit service configuration template. |
template_source |
The source file of the Monit configuration template. A default template is provided by this
cookbook. |
template_cookbook |
The cookbook to look for the Monit configuration template in. |
wait_for_host_port |
Wait for the given host:port combination to become available over TCP before proceeding with
Monit service configuration file creation. |
Actions
Action |
Description |
start |
Starts the given Monit service. |
stop |
Stops the given Monit service. |
restart |
Restarts the given Monit service. |
nothing |
Does not do anything. |
Attributes
Attribute |
Description |
fallback_to_regular_service |
If this is specified and the service is not registered with Monit, it will be started as a
regular service using the standard "service" resource. |
wait_for_host_port |
A host:port combination of another service. If this is specified, we wait for this the given host
to start listening on the given TCP port before attempting to start or restart the service. This
could be used for handling dependencies on remote services. |
Actions
Action |
Description |
reload_and_wait |
Reloads Monit configuration and waits for Monit to start showing the given service in the list of
services it knows about. This is invoked by the monit_wrapper_monitor LWRP after creating a new
monit service configuration file. |
Actions
Action |
Description |
run |
Notifies other resources that subscribe to this resource if the specified Monit service is not
running. |
Providers
Actions Summary
-
create
Creates a configuration file for a new Monit-monitored service.
-
delete
Actions Summary
-
start
Start the given Monit service.
-
stop
Stop the given Monit service.
-
restart
Restart the given Monit service.
Actions Summary
-
reload_and_wait
Reload Monit configuration and wait for it to become aware of the given service.
Actions Summary
-
run
Notifies subscribing resources if the given Monit service is not running.
Recipe Details
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# File 'recipes/default.rb', line 1
if platform_family?('rhel') && node['monit']['install_method'] != 'source'
Chef::Log.warn(
"Setting node['monit']['install_method'] to 'source' on a RedHat-based system because " \
"the monit_wrapper cookbook requires a Monit version of 5.2 or later to utilize the " \
"'matching' feature. Please note that this won't help if the monit-ng default recipe " \
"is included in the run list before the monit_wrapper recipe."
)
node.override['monit']['install_method'] = 'source'
node.default['monit']['executable'] = '/usr/local/bin/monit'
else
node.default['monit']['executable'] = '/usr/bin/monit'
end
include_recipe 'monit-ng'
ruby_block 'monit_wrapper_start_monit_service' do
block { ensure_monit_daemon_is_running }
end
chef_gem 'waitutil'
template '/usr/local/bin/start_stop_service_from_monit.sh' do
source 'start_stop_service_from_monit.sh.erb'
owner 'root'
group 'root'
mode '0744'
variables timeout_sec: node['monit_wrapper']['start_stop_timeout_sec']
end
template '/usr/local/bin/monit_service_ctl.sh' do
source 'monit_service_ctl.sh.erb'
owner 'root'
group 'root'
mode '0755'
variables monit_executable: node['monit']['executable']
end
directory '/var/monit' do
owner 'root'
group 'root'
mode '0777'
end
|
Action Details
Creates a configuration file for a new Monit-monitored service.
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
# File 'providers/monitor.rb', line 28
action :create do
notifying_action_wrapper(
allow_updates_from: "template[#{service_conf_path}]",
verbose: true
) do
wait_for_host_port(new_resource.wait_for_host_port)
variables = (new_resource.variables || {}).to_hash.clone
variables[:service_name] = new_resource.name
variables[:pid_file] = new_resource.pid_file if new_resource.pid_file
variables[:pattern] = new_resource.pattern if new_resource.pattern
if new_resource.java_class
variables[:pattern] = "^[^ ]*java .* #{new_resource.java_class}($| .*)"
end
if [new_resource.pid_file,
new_resource.pattern,
new_resource.java_class].compact.size > 1
raise 'No more than one of pid file, pattern, or Java class can be specified. ' +
"Variables: #{variables.inspect}"
end
Chef::Log.info(
"Creating Monit configuration file #{service_conf_path} " \
"for service #{new_resource.name}"
)
file deprecated_service_conf_path do
action :delete
end
template service_conf_path do
owner 'root'
group 'root'
mode '0644'
source new_resource.template_source || 'service_wrapper.conf.erb'
cookbook new_resource.template_cookbook || 'monit_wrapper'
variables variables
action :create
end
Chef::Log.info("Reloading Monit configuration and waiting for service #{new_resource.name}")
monit_wrapper_reload_and_wait new_resource.name
end
end
|
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
# File 'providers/monitor.rb', line 77
action :delete do
if ::File.exists?(service_conf_path)
file service_conf_path do
action :delete
end
file deprecated_service_conf_path do
action :delete
end
bash "monit-reload-after-removing-#{new_resource.name}" do
code 'monit reload'
end
new_resource.updated_by_last_action(true)
end
end
|
Start the given Monit service.
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
# File 'providers/service.rb', line 19
action :start do service_name = new_resource.name
if monit_service_running?(service_name)
Chef::Log.info("Service #{service_name} is already running, skipping start action")
elsif monit_service_registered?(service_name)
wait_for_host_port(new_resource.wait_for_host_port)
unless monit_service_running?(service_name, verbose: true)
start_monit_service(service_name)
end
elsif new_resource.fallback_to_regular_service
wait_for_host_port(new_resource.wait_for_host_port)
Chef::Log.info(
"No Monit service #{service_name} registered, failling back to starting a regular service")
service service_name do
action :start
end
else
raise "Monit does not know about #{service_name} and fallback_to_regular_service is disabled"
end
end
|
Stop the given Monit service.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
# File 'providers/service.rb', line 42
action :stop do service_name = new_resource.name
if monit_service_registered?(service_name)
stop_monit_service(service_name)
elsif new_resource.fallback_to_regular_service
Chef::Log.info(
"No Monit service #{service_name} registered, failling back to stopping a regular service")
service service_name do
action :stop
end
else
raise "Monit does not know about #{service_name} and fallback_to_regular_service is disabled"
end
end
|
Restart the given Monit service.
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
# File 'providers/service.rb', line 59
action :restart do if monit_service_running?(new_resource.name, verbose: true)
command = 'restart'
else
command = 'start'
end
wait_for_host_port(new_resource.wait_for_host_port)
bash "monit-#{command}-#{new_resource.name}" do
user 'root'
code "#{node['monit']['executable']} #{command} #{new_resource.name}"
action :run
end
end
|
Reload Monit configuration and wait for it to become aware of the given service.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
# File 'providers/reload_and_wait.rb', line 18
action :reload_and_wait do
service_name = new_resource.name
script 'monit-reload' do
interpreter 'bash'
user 'root'
code "#{node['monit']['executable']} reload"
end
ruby_block "ensure-monit-is-running-after-reloading-for-#{service_name}" do
block { ensure_monit_daemon_is_running }
end
ruby_block "wait-for-monit-reload-#{new_resource.name}" do
block { wait_for_monit_service_to_exist(new_resource.name) }
end
new_resource.updated_by_last_action(true)
end
|
Notifies subscribing resources if the given Monit service is not running.
16
17
18
19
20
21
22
23
|
# File 'providers/notify_if_not_running.rb', line 16
action :run do
if monit_service_running?(new_resource.name, verbose: true)
Chef::Log.info("Service #{new_resource.name} is running, not sending notification")
else
Chef::Log.info("Service #{new_resource.name} is not running, sending notification")
new_resource.updated_by_last_action(true)
end
end
|