poise-service 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.kitchen.yml +1 -1
- data/CHANGELOG.md +8 -1
- data/README.md +1 -0
- data/chef/templates/default/dummy.json.erb +7 -0
- data/chef/templates/default/sysvinit.sh.erb +31 -24
- data/chef/templates/default/upstart.conf.erb +1 -1
- data/lib/poise_service/resources/poise_service_test.rb +14 -0
- data/lib/poise_service/service_providers/dummy.rb +35 -4
- data/lib/poise_service/service_providers/systemd.rb +21 -1
- data/lib/poise_service/service_providers/upstart.rb +11 -0
- data/lib/poise_service/version.rb +1 -1
- data/test/cookbooks/poise-service_test/recipes/default.rb +7 -3
- data/test/spec/service_providers/sysvinit_spec.rb +7 -4
- data/test/spec/service_providers/upstart_spec.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9083e6c7faa81f26cb75ba512932747ca7d78505
|
4
|
+
data.tar.gz: 1cf6379abe8c39cafb38b7d7b5812db1fa24c9d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 475915c90a841a1f8ebadfbf48074440dc2b202a0902c8b50cd362bf2dd523feec27f60d010d9fdc46d6b60079343b53b4d56aa3f96243c1d4c7806c644f370e
|
7
|
+
data.tar.gz: 8ee09393fc20251559c2c275e7bc7cb56b12dc0d091e85ec66c7f6983f263c9a4490a9c888a1b856dfe7b56e54247846f85565d7ef0d23bd47a6afbd88ce2995
|
data/.kitchen.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
-
# Changelog
|
1
|
+
# Poise-Service Changelog
|
2
|
+
|
3
|
+
## v1.0.3
|
4
|
+
|
5
|
+
* [#10](https://github.com/poise/poise-service/pull/10) Fixes for ensuring services are restarted when their command or user changes.
|
6
|
+
* [#11](https://github.com/poise/poise-service/pull/11) Revamp the `sysvinit` provider for non-Debian platforms to be more stable.
|
7
|
+
* [#12](https://github.com/poise/poise-service/pull/12) Improve the `dummy` provider to handle dropping privs correctly.
|
2
8
|
|
3
9
|
## v1.0.2
|
10
|
+
|
4
11
|
* Fix a potential infinite loop when starting a service with the dummy provider.
|
5
12
|
* [#2](https://github.com/poise/poise-service/pull/2) Remove usage of root
|
6
13
|
default files so uploading with Berkshelf works (for now).
|
data/README.md
CHANGED
@@ -315,6 +315,7 @@ end
|
|
315
315
|
* `user` – Override the service user.
|
316
316
|
* `never_restart` – Never try to restart the service.
|
317
317
|
* `never_reload` – Never try to reload the service.
|
318
|
+
* `auto_reload` – Run `systemctl daemon-reload` after changes to the unit file. *(default: true)*
|
318
319
|
|
319
320
|
## ServiceMixin
|
320
321
|
|
@@ -11,10 +11,6 @@
|
|
11
11
|
# Description: Init script for <%= @name %>
|
12
12
|
### END INIT INFO
|
13
13
|
|
14
|
-
<%- @environment.each do |key, val| -%>
|
15
|
-
export <%= key %>="<%= val %>"
|
16
|
-
<%- end -%>
|
17
|
-
|
18
14
|
<%- if @platform_family == 'debian' -%>
|
19
15
|
. /lib/lsb/init-functions
|
20
16
|
|
@@ -37,32 +33,42 @@ _reload() {
|
|
37
33
|
start-stop-daemon --stop --quiet --pidfile "<%= @pid_file %>" --user "<%= @user %>" --signal "<%= @reload_signal %>"
|
38
34
|
}
|
39
35
|
|
40
|
-
<%-
|
41
|
-
. /etc/rc.d/init.d/functions
|
42
|
-
|
43
|
-
_pid () {
|
44
|
-
pidof -s -o $$ -o $PPID -o %PPID -x "$1" || pidof -s -o $$ -o $PPID -o %PPID -x "${1##*/}"
|
45
|
-
}
|
46
|
-
|
36
|
+
<%- else -%>
|
47
37
|
_start() {
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
38
|
+
<%# Implementing this using RedHat's bash helpers is too painful. Sorry. %>
|
39
|
+
<%# See dummy.rb for a more commented version of this code. %>
|
40
|
+
/opt/chef/embedded/bin/ruby <<EOH
|
41
|
+
pid_file = <%= @pid_file.inspect %>
|
42
|
+
File.unlink(pid_file) if File.exist?(pid_file)
|
43
|
+
if Process.fork
|
44
|
+
sleep(1) until File.exist?(pid_file)
|
45
|
+
else
|
46
|
+
Process.daemon(true)
|
47
|
+
Dir.chdir(<%= @directory.inspect %>)
|
48
|
+
<%- unless @pid_file_external -%>
|
49
|
+
IO.write(pid_file, Process.pid)
|
50
|
+
<%- end -%>
|
51
|
+
Process::UID.change_privilege(<%= @user.inspect %>)
|
52
|
+
Kernel.exec(*<%= Shellwords.split(@command).inspect %>)
|
53
|
+
exit!
|
54
|
+
end
|
55
|
+
EOH
|
54
56
|
}
|
55
57
|
|
56
58
|
_stop() {
|
57
59
|
if [ -r "<%= @pid_file %>" ]; then
|
58
60
|
kill -<%= @stop_signal%> "$(cat "<%= @pid_file %>")"
|
59
61
|
else
|
60
|
-
|
62
|
+
return 0
|
61
63
|
fi
|
62
64
|
}
|
63
65
|
|
64
66
|
_status() {
|
65
|
-
|
67
|
+
if [ -r "<%= @pid_file %>" ]; then
|
68
|
+
kill -0 "$(cat "<%= @pid_file %>")"
|
69
|
+
else
|
70
|
+
return 1
|
71
|
+
fi
|
66
72
|
}
|
67
73
|
|
68
74
|
_reload() {
|
@@ -73,7 +79,7 @@ _reload() {
|
|
73
79
|
fi
|
74
80
|
}
|
75
81
|
|
76
|
-
|
82
|
+
<%# Some functions to match LSB %>
|
77
83
|
|
78
84
|
log_daemon_msg() {
|
79
85
|
echo -n "$1"
|
@@ -93,13 +99,11 @@ log_failure_msg() {
|
|
93
99
|
|
94
100
|
log_end_msg() {
|
95
101
|
if [ "$1" = 0 ]; then
|
96
|
-
|
102
|
+
echo " [ OK ]"
|
97
103
|
else
|
98
|
-
|
104
|
+
echo " [FAILED]"
|
99
105
|
fi
|
100
106
|
}
|
101
|
-
<%- else -%>
|
102
|
-
<%- raise "Platform family #{@platform_family} is not supported" -%>
|
103
107
|
<%- end -%>
|
104
108
|
|
105
109
|
set -e
|
@@ -124,6 +128,9 @@ start() {
|
|
124
128
|
fi
|
125
129
|
}
|
126
130
|
|
131
|
+
<%- @environment.each do |key, val| -%>
|
132
|
+
export <%= key %>="<%= val %>"
|
133
|
+
<%- end -%>
|
127
134
|
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
|
128
135
|
|
129
136
|
case "$1" in
|
@@ -25,7 +25,7 @@ reload signal <%= @reload_signal %>
|
|
25
25
|
<%- if @upstart_features[:setuid] -%>
|
26
26
|
exec <%= @command %>
|
27
27
|
<%- else -%>
|
28
|
-
exec /opt/chef/embedded/bin/ruby -e 'Process.
|
28
|
+
exec /opt/chef/embedded/bin/ruby -e 'Process::UID.change_privilege("<%= @user %>"); ENV["HOME"] = Dir.home("<%= @user %>") rescue nil; exec(*<%= Shellwords.split(@command).inspect %>)'
|
29
29
|
<%- end -%>
|
30
30
|
<%- if !@upstart_features[:kill_signal] && @stop_signal != 'TERM' -%>
|
31
31
|
pre-stop script
|
@@ -187,12 +187,26 @@ EOH
|
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
190
|
+
# Test the #pid accessor.
|
190
191
|
ruby_block "/tmp/poise_test_#{new_resource.name}_pid" do
|
191
192
|
block do
|
192
193
|
pid = resources("poise_service[poise_test_#{new_resource.name}]").pid
|
193
194
|
IO.write("/tmp/poise_test_#{new_resource.name}_pid", pid.to_s)
|
194
195
|
end
|
195
196
|
end
|
197
|
+
|
198
|
+
# Test changing the service definition itself.
|
199
|
+
poise_service "poise_test_#{new_resource.name}_change" do
|
200
|
+
provider new_resource.service_provider if new_resource.service_provider
|
201
|
+
command "/usr/bin/poise_test #{new_resource.base_port + 5}"
|
202
|
+
end
|
203
|
+
|
204
|
+
poise_service "poise_test_#{new_resource.name}_change_second" do
|
205
|
+
service_name "poise_test_#{new_resource.name}_change"
|
206
|
+
provider new_resource.service_provider if new_resource.service_provider
|
207
|
+
command "/usr/bin/poise_test #{new_resource.base_port + 6}"
|
208
|
+
end
|
209
|
+
|
196
210
|
end
|
197
211
|
end
|
198
212
|
end
|
@@ -14,6 +14,8 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
#
|
16
16
|
|
17
|
+
require 'shellwords'
|
18
|
+
|
17
19
|
require 'poise_service/service_providers/base'
|
18
20
|
|
19
21
|
|
@@ -29,9 +31,16 @@ module PoiseService
|
|
29
31
|
::File.unlink(pid_file) if ::File.exist?(pid_file)
|
30
32
|
if Process.fork
|
31
33
|
# Parent, wait for the final child to write the pid file.
|
34
|
+
now = Time.now
|
32
35
|
until ::File.exist?(pid_file)
|
33
36
|
sleep(1)
|
34
|
-
|
37
|
+
# After 30 seconds, show output at a higher level to avoid too much
|
38
|
+
# confusing on failed process launches.
|
39
|
+
if Time.now - now <= 30
|
40
|
+
Chef::Log.debug("[#{new_resource}] Waiting for PID file")
|
41
|
+
else
|
42
|
+
Chef::Log.warning("[#{new_resource}] Waiting for PID file at #{pid_file} to be created")
|
43
|
+
end
|
35
44
|
end
|
36
45
|
else
|
37
46
|
# :nocov:
|
@@ -42,14 +51,17 @@ module PoiseService
|
|
42
51
|
# Daemonized, set up process environment.
|
43
52
|
Dir.chdir(new_resource.directory)
|
44
53
|
Chef::Log.debug("[#{new_resource}] Directory changed to #{new_resource.directory}")
|
54
|
+
ENV['HOME'] = Dir.home(new_resource.user)
|
45
55
|
new_resource.environment.each do |key, val|
|
46
56
|
ENV[key.to_s] = val.to_s
|
47
57
|
end
|
48
|
-
Process.uid = new_resource.user
|
49
58
|
Chef::Log.debug("[#{new_resource}] Process environment configured")
|
50
59
|
IO.write(pid_file, Process.pid)
|
51
|
-
Chef::Log.debug("[#{new_resource}] PID written to #{pid_file}, execing
|
52
|
-
|
60
|
+
Chef::Log.debug("[#{new_resource}] PID written to #{pid_file}, dropping privs and execing")
|
61
|
+
Process::UID.change_privilege(new_resource.user)
|
62
|
+
# Split the command so we don't get an extra sh -c.
|
63
|
+
Chef::Log.debug("[#{new_resource}] Execing #{new_resource.command}")
|
64
|
+
Kernel.exec(*Shellwords.split(new_resource.command))
|
53
65
|
# Just in case, bail out.
|
54
66
|
exit!
|
55
67
|
# :nocov:
|
@@ -94,15 +106,34 @@ module PoiseService
|
|
94
106
|
def enable_service
|
95
107
|
end
|
96
108
|
|
109
|
+
# Write all major service parameters to a file so that if they change, we
|
110
|
+
# can restart the service. This also makes debuggin a bit easier so you
|
111
|
+
# can still see what it thinks it was starting without sifting through
|
112
|
+
# piles of debug output.
|
97
113
|
def create_service
|
114
|
+
service_template(run_file, 'dummy.json.erb')
|
98
115
|
end
|
99
116
|
|
100
117
|
def disable_service
|
101
118
|
end
|
102
119
|
|
120
|
+
# Delete the tracking file.
|
103
121
|
def destroy_service
|
122
|
+
file run_file do
|
123
|
+
action :delete
|
124
|
+
end
|
125
|
+
|
126
|
+
file pid_file do
|
127
|
+
action :delete
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Path to the run parameters tracking file.
|
132
|
+
def run_file
|
133
|
+
"/var/run/#{new_resource.service_name}.json"
|
104
134
|
end
|
105
135
|
|
136
|
+
# Path to the PID file.
|
106
137
|
def pid_file
|
107
138
|
"/var/run/#{new_resource.service_name}.pid"
|
108
139
|
end
|
@@ -25,12 +25,21 @@ module PoiseService
|
|
25
25
|
include Chef::Mixin::ShellOut
|
26
26
|
provides(:systemd)
|
27
27
|
|
28
|
+
# @api private
|
28
29
|
def self.provides_auto?(node, resource)
|
29
30
|
# Don't allow systemd under docker, it won't work in most cases.
|
30
31
|
return false if node['virtualization'] && %w{docker lxc}.include?(node['virtualization']['system'])
|
31
32
|
service_resource_hints.include?(:systemd)
|
32
33
|
end
|
33
34
|
|
35
|
+
# @api private
|
36
|
+
def self.default_inversion_options(node, resource)
|
37
|
+
super.merge({
|
38
|
+
# Automatically reload systemd on changes.
|
39
|
+
auto_reload: true,
|
40
|
+
})
|
41
|
+
end
|
42
|
+
|
34
43
|
def pid
|
35
44
|
cmd = shell_out(%w{systemctl status} + [new_resource.service_name])
|
36
45
|
if !cmd.error? && cmd.stdout.include?('Active: active (running)') && md = cmd.stdout.match(/Main PID: (\d+)/)
|
@@ -48,8 +57,19 @@ module PoiseService
|
|
48
57
|
end
|
49
58
|
end
|
50
59
|
|
60
|
+
def systemctl_daemon_reload
|
61
|
+
execute 'systemctl daemon-reload' do
|
62
|
+
action :nothing
|
63
|
+
user 'root'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
51
67
|
def create_service
|
52
|
-
|
68
|
+
reloader = systemctl_daemon_reload
|
69
|
+
service_template("/etc/systemd/system/#{new_resource.service_name}.service", 'systemd.service.erb') do
|
70
|
+
notifies :run, reloader, :immediately if options['auto_reload']
|
71
|
+
variables.update(auto_reload: options['auto_reload'])
|
72
|
+
end
|
53
73
|
end
|
54
74
|
|
55
75
|
def destroy_service
|
@@ -35,6 +35,17 @@ module PoiseService
|
|
35
35
|
service_resource_hints.include?(:upstart)
|
36
36
|
end
|
37
37
|
|
38
|
+
# True restart in Upstart preserves the original config data, we want the
|
39
|
+
# more obvious behavior like everything else in the world that restart
|
40
|
+
# would re-read the updated config file. Use stop+start to get this
|
41
|
+
# behavior. http://manpages.ubuntu.com/manpages/raring/man8/initctl.8.html
|
42
|
+
def action_restart
|
43
|
+
return if options['never_restart']
|
44
|
+
action_stop
|
45
|
+
action_start
|
46
|
+
end
|
47
|
+
|
48
|
+
# Shim out reload if we have a version that predates reload support.
|
38
49
|
def action_reload
|
39
50
|
return if options['never_reload']
|
40
51
|
if !upstart_features[:reload_signal] && new_resource.reload_signal != 'HUP'
|
@@ -37,9 +37,13 @@ else
|
|
37
37
|
base_port 6000
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
if node['platform_family'] == 'rhel' && node['platform_version'].start_with?('5')
|
41
|
+
file '/no_upstart'
|
42
|
+
else
|
43
|
+
poise_service_test 'upstart' do
|
44
|
+
service_provider :upstart
|
45
|
+
base_port 7000
|
46
|
+
end
|
43
47
|
end
|
44
48
|
end
|
45
49
|
|
@@ -54,9 +54,10 @@ EOH
|
|
54
54
|
let(:chefspec_options) { { platform: 'centos', version: '7.0'} }
|
55
55
|
|
56
56
|
it { is_expected.to render_file('/etc/init.d/test').with_content(<<-EOH) }
|
57
|
-
(
|
58
|
-
|
59
|
-
|
57
|
+
Dir.chdir("/")
|
58
|
+
IO.write(pid_file, Process.pid)
|
59
|
+
Process::UID.change_privilege("root")
|
60
|
+
Kernel.exec(*["myapp", "--serve"])
|
60
61
|
EOH
|
61
62
|
|
62
63
|
context 'with an external PID file' do
|
@@ -66,7 +67,9 @@ EOH
|
|
66
67
|
end
|
67
68
|
|
68
69
|
it { is_expected.to render_file('/etc/init.d/test').with_content(<<-EOH) }
|
69
|
-
(
|
70
|
+
Dir.chdir("/")
|
71
|
+
Process::UID.change_privilege("root")
|
72
|
+
Kernel.exec(*["myapp", "--serve"])
|
70
73
|
EOH
|
71
74
|
end # /context with an external PID file
|
72
75
|
end # /context on CentOS
|
@@ -45,7 +45,7 @@ respawn limit 10 5
|
|
45
45
|
umask 022
|
46
46
|
chdir /
|
47
47
|
|
48
|
-
exec /opt/chef/embedded/bin/ruby -e 'Process.
|
48
|
+
exec /opt/chef/embedded/bin/ruby -e 'Process::UID.change_privilege("root"); ENV["HOME"] = Dir.home("root") rescue nil; exec(*["myapp", "--serve"])'
|
49
49
|
EOH
|
50
50
|
|
51
51
|
context 'with a stop signal' do
|
@@ -69,7 +69,7 @@ respawn limit 10 5
|
|
69
69
|
umask 022
|
70
70
|
chdir /
|
71
71
|
|
72
|
-
exec /opt/chef/embedded/bin/ruby -e 'Process.
|
72
|
+
exec /opt/chef/embedded/bin/ruby -e 'Process::UID.change_privilege("root"); ENV["HOME"] = Dir.home("root") rescue nil; exec(*["myapp", "--serve"])'
|
73
73
|
pre-stop script
|
74
74
|
PID=`initctl status test | sed 's/^.*process \\([0-9]*\\)$/\\1/'`
|
75
75
|
if [ -n "$PID" ]; then
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poise-service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Noah Kantrowitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: halite
|
@@ -85,6 +85,7 @@ files:
|
|
85
85
|
- README.md
|
86
86
|
- Rakefile
|
87
87
|
- chef/attributes/default.rb
|
88
|
+
- chef/templates/default/dummy.json.erb
|
88
89
|
- chef/templates/default/systemd.service.erb
|
89
90
|
- chef/templates/default/sysvinit.sh.erb
|
90
91
|
- chef/templates/default/upstart.conf.erb
|