poise-service 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.kitchen.travis.yml +4 -0
- data/.kitchen.yml +9 -0
- data/.travis.yml +23 -0
- data/.yardopts +6 -0
- data/Berksfile +27 -0
- data/Gemfile +33 -0
- data/LICENSE +201 -0
- data/README.md +381 -0
- data/Rakefile +17 -0
- data/chef/attributes/default.rb +19 -0
- data/chef/templates/systemd.service.erb +13 -0
- data/chef/templates/sysvinit.sh.erb +177 -0
- data/chef/templates/upstart.conf.erb +37 -0
- data/lib/poise_service.rb +25 -0
- data/lib/poise_service/cheftie.rb +18 -0
- data/lib/poise_service/error.rb +20 -0
- data/lib/poise_service/resources.rb +28 -0
- data/lib/poise_service/resources/poise_service.rb +161 -0
- data/lib/poise_service/resources/poise_service_test.rb +200 -0
- data/lib/poise_service/resources/poise_service_user.rb +136 -0
- data/lib/poise_service/service_mixin.rb +192 -0
- data/lib/poise_service/service_providers.rb +37 -0
- data/lib/poise_service/service_providers/base.rb +193 -0
- data/lib/poise_service/service_providers/dummy.rb +100 -0
- data/lib/poise_service/service_providers/systemd.rb +63 -0
- data/lib/poise_service/service_providers/sysvinit.rb +86 -0
- data/lib/poise_service/service_providers/upstart.rb +117 -0
- data/lib/poise_service/utils.rb +45 -0
- data/lib/poise_service/version.rb +19 -0
- data/poise-service.gemspec +41 -0
- data/test/cookbooks/poise-service_test/metadata.rb +18 -0
- data/test/cookbooks/poise-service_test/providers/mixin.rb +43 -0
- data/test/cookbooks/poise-service_test/recipes/default.rb +47 -0
- data/test/cookbooks/poise-service_test/recipes/mixin.rb +34 -0
- data/test/cookbooks/poise-service_test/resources/mixin.rb +26 -0
- data/test/gemfiles/chef-12.gemfile +19 -0
- data/test/gemfiles/master.gemfile +22 -0
- data/test/integration/default/serverspec/Gemfile +19 -0
- data/test/integration/default/serverspec/default_spec.rb +45 -0
- data/test/integration/default/serverspec/mixin_spec.rb +37 -0
- data/test/spec/resources/poise_service_spec.rb +235 -0
- data/test/spec/resources/poise_service_user_spec.rb +119 -0
- data/test/spec/service_mixin_spec.rb +164 -0
- data/test/spec/service_providers/base_spec.rb +231 -0
- data/test/spec/service_providers/dummy_spec.rb +91 -0
- data/test/spec/service_providers/systemd_spec.rb +98 -0
- data/test/spec/service_providers/sysvinit_spec.rb +96 -0
- data/test/spec/service_providers/upstart_spec.rb +300 -0
- data/test/spec/spec_helper.rb +50 -0
- data/test/spec/utils_spec.rb +44 -0
- metadata +172 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
source 'https://rubygems.org/'
|
18
|
+
|
19
|
+
gem 'poise-service-spechelper'
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'poise_service/spec_helper'
|
18
|
+
|
19
|
+
# CentOS 6 doesn't show upstart services in chkconfig, which is how specinfra
|
20
|
+
# checkes what is enabled.
|
21
|
+
old_upstart = os[:family] == 'redhat' && os[:release].start_with?('6')
|
22
|
+
|
23
|
+
describe 'default provider' do
|
24
|
+
it_should_behave_like 'a poise_service_test', 'default', 5000, !old_upstart
|
25
|
+
|
26
|
+
describe process('ruby /usr/bin/poise_test') do
|
27
|
+
it { is_expected.to be_running }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'sysvinit provider', unless: File.exists?('/no_sysvinit') do
|
32
|
+
it_should_behave_like 'a poise_service_test', 'sysvinit', 6000
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'upstart provider', unless: File.exists?('/no_upstart') do
|
36
|
+
it_should_behave_like 'a poise_service_test', 'upstart', 7000, !old_upstart
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'systemd provider', unless: File.exists?('/no_systemd') do
|
40
|
+
it_should_behave_like 'a poise_service_test', 'systemd', 8000
|
41
|
+
end
|
42
|
+
|
43
|
+
describe 'dummy provider' do
|
44
|
+
it_should_behave_like 'a poise_service_test', 'dummy', 9000, false
|
45
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'net/http'
|
18
|
+
require 'uri'
|
19
|
+
|
20
|
+
require 'serverspec'
|
21
|
+
set :backend, :exec
|
22
|
+
|
23
|
+
describe 'poise_service_test_mixin' do
|
24
|
+
let(:port) { }
|
25
|
+
let(:url) { "http://localhost:#{port}/" }
|
26
|
+
subject { Net::HTTP.get(URI(url)) }
|
27
|
+
|
28
|
+
describe 'default' do
|
29
|
+
let(:port) { 4000 }
|
30
|
+
it { is_expected.to eq 'Hello world!'}
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'update' do
|
34
|
+
let(:port) { 4001 }
|
35
|
+
it { is_expected.to eq 'second' }
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'spec_helper'
|
18
|
+
|
19
|
+
describe PoiseService::Resources::PoiseService::Resource do
|
20
|
+
service_provider('auto')
|
21
|
+
service_resource_hints(%i{debian redhat upstart systemd})
|
22
|
+
|
23
|
+
describe 'provider lookup' do
|
24
|
+
recipe(subject: false) do
|
25
|
+
poise_service 'test'
|
26
|
+
end
|
27
|
+
subject do
|
28
|
+
chef_run.find_resource(:poise_service, 'test').provider_for_action(:enable).class.provides
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'auto on debian' do
|
32
|
+
service_resource_hints(:debian)
|
33
|
+
it { is_expected.to eq :sysvinit }
|
34
|
+
end # /context auto on debian
|
35
|
+
|
36
|
+
context 'auto on redhat' do
|
37
|
+
service_resource_hints(:redhat)
|
38
|
+
it { is_expected.to eq :sysvinit }
|
39
|
+
end # /context auto on redhat
|
40
|
+
|
41
|
+
context 'auto on upstart' do
|
42
|
+
service_resource_hints(:upstart)
|
43
|
+
it { is_expected.to eq :upstart }
|
44
|
+
end # /context auto on upstart
|
45
|
+
|
46
|
+
context 'auto on systemd' do
|
47
|
+
service_resource_hints(:systemd)
|
48
|
+
it { is_expected.to eq :systemd }
|
49
|
+
end # /context auto on systemd
|
50
|
+
|
51
|
+
context 'auto on multiple systems' do
|
52
|
+
service_resource_hints(%i{debian invokerd upstart})
|
53
|
+
it { is_expected.to eq :upstart }
|
54
|
+
end # /context auto on multiple systems
|
55
|
+
|
56
|
+
context 'global override' do
|
57
|
+
service_provider('sysvinit')
|
58
|
+
it { is_expected.to eq :sysvinit }
|
59
|
+
end # /context global override
|
60
|
+
|
61
|
+
context 'per-service override' do
|
62
|
+
service_provider('test', 'sysvinit')
|
63
|
+
it { is_expected.to eq :sysvinit }
|
64
|
+
end # /context global override
|
65
|
+
|
66
|
+
context 'per-service override for a different service' do
|
67
|
+
service_provider('other', 'sysvinit')
|
68
|
+
it { is_expected.to eq :systemd }
|
69
|
+
end # /context global override for a different service
|
70
|
+
|
71
|
+
context 'recipe DSL override' do
|
72
|
+
recipe(subject: false) do
|
73
|
+
poise_service 'test' do
|
74
|
+
provider :sysvinit
|
75
|
+
end
|
76
|
+
end
|
77
|
+
it { is_expected.to eq :sysvinit }
|
78
|
+
end # /context recipe DSL override
|
79
|
+
end # /describe provider lookup
|
80
|
+
|
81
|
+
describe '#clean_signal' do
|
82
|
+
let(:signal) { }
|
83
|
+
subject do
|
84
|
+
described_class.new(nil, nil).send(:clean_signal, signal)
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'with a short string' do
|
88
|
+
let(:signal) { 'term' }
|
89
|
+
it { is_expected.to eq 'TERM' }
|
90
|
+
end # /context with a short string
|
91
|
+
|
92
|
+
context 'with a long string' do
|
93
|
+
let(:signal) { 'sigterm' }
|
94
|
+
it { is_expected.to eq 'TERM' }
|
95
|
+
end # /context with a long string
|
96
|
+
|
97
|
+
context 'with a short string in caps' do
|
98
|
+
let(:signal) { 'TERM' }
|
99
|
+
it { is_expected.to eq 'TERM' }
|
100
|
+
end # /context with a short string in caps
|
101
|
+
|
102
|
+
context 'with a long string in caps' do
|
103
|
+
let(:signal) { 'SIGTERM' }
|
104
|
+
it { is_expected.to eq 'TERM' }
|
105
|
+
end # /context with a long string in caps
|
106
|
+
|
107
|
+
context 'with a number' do
|
108
|
+
let(:signal) { 15 }
|
109
|
+
it { is_expected.to eq 'TERM' }
|
110
|
+
end # /context with a number
|
111
|
+
|
112
|
+
context 'with a symbol' do
|
113
|
+
let(:signal) { :term }
|
114
|
+
it { is_expected.to eq 'TERM' }
|
115
|
+
end # /context with a symbol
|
116
|
+
|
117
|
+
context 'with an invalid string' do
|
118
|
+
let(:signal) { 'nope' }
|
119
|
+
it { expect { subject }.to raise_error PoiseService::Error }
|
120
|
+
end # /context with an invalid string
|
121
|
+
|
122
|
+
context 'with an invalid number' do
|
123
|
+
let(:signal) { 100 }
|
124
|
+
it { expect { subject }.to raise_error PoiseService::Error }
|
125
|
+
end # /context with an invalid number
|
126
|
+
end # /describe #clean_stop_signal
|
127
|
+
|
128
|
+
describe '#options' do
|
129
|
+
subject { chef_run.find_resource('poise_service', 'test') }
|
130
|
+
recipe(subject: false) do
|
131
|
+
poise_service 'test' do
|
132
|
+
options template: 'source.erb'
|
133
|
+
options :sysvinit, template: 'override.erb'
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
its(:options) { are_expected.to eq({'template' => 'source.erb'}) }
|
138
|
+
it { expect(subject.options(:sysvinit)).to eq({'template' => 'override.erb'}) }
|
139
|
+
end # /describe #options
|
140
|
+
|
141
|
+
describe '#default_directory' do
|
142
|
+
let(:user) { 'root' }
|
143
|
+
subject do
|
144
|
+
described_class.new('test', chef_run.run_context).tap {|r| r.user(user) }.send(:default_directory)
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'with root' do
|
148
|
+
context 'on Linux' do
|
149
|
+
let(:chefspec_options) { {platform: 'ubuntu', version: '14.04'} }
|
150
|
+
it { is_expected.to eq '/' }
|
151
|
+
end # /context 'on Linux
|
152
|
+
|
153
|
+
context 'on Windows' do
|
154
|
+
let(:chefspec_options) { {platform: 'windows', version: '2012R2'} }
|
155
|
+
it { is_expected.to eq 'C:\\' }
|
156
|
+
end # /context on Windows
|
157
|
+
end # /context with root
|
158
|
+
|
159
|
+
context 'with a normal user' do
|
160
|
+
let(:user) { 'poise' }
|
161
|
+
before do
|
162
|
+
expect(Dir).to receive(:home).with('poise').and_return('/home/poise')
|
163
|
+
end
|
164
|
+
|
165
|
+
it { is_expected.to eq '/home/poise' }
|
166
|
+
end # /context with a normal user
|
167
|
+
|
168
|
+
context 'with an invalid user' do
|
169
|
+
let(:user) { 'poise' }
|
170
|
+
before do
|
171
|
+
expect(Dir).to receive(:home).with('poise').and_raise(ArgumentError)
|
172
|
+
end
|
173
|
+
|
174
|
+
it { is_expected.to eq '/' }
|
175
|
+
end # /context with an invalid user
|
176
|
+
end # /describe #default_directory
|
177
|
+
|
178
|
+
describe '#restart_on_update' do
|
179
|
+
service_provider('sysvinit')
|
180
|
+
step_into(:poise_service)
|
181
|
+
before do
|
182
|
+
allow(File).to receive(:exists?).and_call_original
|
183
|
+
allow(File).to receive(:exists?).with('/etc/init.d/test').and_return(true)
|
184
|
+
end
|
185
|
+
subject { chef_run.template('/etc/init.d/test') }
|
186
|
+
|
187
|
+
context 'with true' do
|
188
|
+
recipe(subject: false) do
|
189
|
+
poise_service 'test' do
|
190
|
+
command 'myapp --serve'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
it { is_expected.to notify('poise_service[test]').to(:restart) }
|
194
|
+
end # /context with true
|
195
|
+
|
196
|
+
context 'with false' do
|
197
|
+
recipe(subject: false) do
|
198
|
+
poise_service 'test' do
|
199
|
+
command 'myapp --serve'
|
200
|
+
restart_on_update false
|
201
|
+
end
|
202
|
+
end
|
203
|
+
it { is_expected.to_not notify('poise_service[test]').to(:restart) }
|
204
|
+
end # /context with false
|
205
|
+
|
206
|
+
context 'with immediately' do
|
207
|
+
recipe(subject: false) do
|
208
|
+
poise_service 'test' do
|
209
|
+
command 'myapp --serve'
|
210
|
+
restart_on_update 'immediately'
|
211
|
+
end
|
212
|
+
end
|
213
|
+
it { is_expected.to notify('poise_service[test]').to(:restart).immediately }
|
214
|
+
end # /context with immediately
|
215
|
+
|
216
|
+
context 'with :immediately' do
|
217
|
+
recipe(subject: false) do
|
218
|
+
poise_service 'test' do
|
219
|
+
command 'myapp --serve'
|
220
|
+
restart_on_update :immediately
|
221
|
+
end
|
222
|
+
end
|
223
|
+
it { is_expected.to notify('poise_service[test]').to(:restart).immediately }
|
224
|
+
end # /context with :immediately
|
225
|
+
end # /describe #restart_on_update
|
226
|
+
|
227
|
+
describe '#pid' do
|
228
|
+
subject { described_class.new(nil, nil) }
|
229
|
+
it do
|
230
|
+
fake_pid = double('pid')
|
231
|
+
expect(subject).to receive(:provider_for_action).with(:pid).and_return(double(pid: fake_pid))
|
232
|
+
expect(subject.pid).to eq fake_pid
|
233
|
+
end
|
234
|
+
end # /describe #pid
|
235
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2015, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'spec_helper'
|
18
|
+
|
19
|
+
describe PoiseService::Resources::PoiseServiceUser do
|
20
|
+
step_into(:poise_service_user)
|
21
|
+
recipe do
|
22
|
+
poise_service_user 'poise'
|
23
|
+
end
|
24
|
+
|
25
|
+
it { is_expected.to create_group('poise').with(gid: nil, system: true) }
|
26
|
+
it { is_expected.to create_user('poise').with(gid: 'poise', home: nil, system: true, uid: nil) }
|
27
|
+
|
28
|
+
context 'with an explicit user and group name' do
|
29
|
+
recipe do
|
30
|
+
poise_service_user 'poise' do
|
31
|
+
user 'poise_user'
|
32
|
+
group 'poise_group'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it { is_expected.to create_group('poise_group').with(gid: nil, system: true) }
|
37
|
+
it { is_expected.to create_user('poise_user').with(gid: 'poise_group', home: nil, system: true, uid: nil) }
|
38
|
+
end # /context with an explicit user and group name
|
39
|
+
|
40
|
+
context 'with no group' do
|
41
|
+
recipe do
|
42
|
+
poise_service_user 'poise' do
|
43
|
+
group false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it { is_expected.to_not create_group('poise') }
|
48
|
+
it { is_expected.to create_user('poise').with(gid: nil, home: nil, system: true, uid: nil) }
|
49
|
+
end # /context with no group
|
50
|
+
|
51
|
+
context 'with explicit uid' do
|
52
|
+
recipe do
|
53
|
+
poise_service_user 'poise' do
|
54
|
+
uid 100
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it { is_expected.to create_group('poise').with(gid: nil, system: true) }
|
59
|
+
it { is_expected.to create_user('poise').with(gid: 'poise', home: nil, system: true, uid: 100) }
|
60
|
+
end # /context with explicit uid
|
61
|
+
|
62
|
+
context 'with explicit gid' do
|
63
|
+
recipe do
|
64
|
+
poise_service_user 'poise' do
|
65
|
+
gid 100
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
it { is_expected.to create_group('poise').with(gid: 100, system: true) }
|
70
|
+
it { is_expected.to create_user('poise').with(gid: 'poise', home: nil, system: true, uid: nil) }
|
71
|
+
end # /context with explicit gid
|
72
|
+
|
73
|
+
context 'with home directory' do
|
74
|
+
recipe do
|
75
|
+
poise_service_user 'poise' do
|
76
|
+
home '/home/poise'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it { is_expected.to create_group('poise').with(gid: nil, system: true) }
|
81
|
+
it { is_expected.to create_user('poise').with(gid: 'poise', home: '/home/poise', system: true, uid: nil) }
|
82
|
+
end # /context with home directory
|
83
|
+
|
84
|
+
context 'with action :remove' do
|
85
|
+
recipe do
|
86
|
+
poise_service_user 'poise' do
|
87
|
+
action :remove
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
it { is_expected.to remove_group('poise') }
|
92
|
+
it { is_expected.to remove_user('poise') }
|
93
|
+
|
94
|
+
context 'with an explicit user and group name' do
|
95
|
+
recipe do
|
96
|
+
poise_service_user 'poise' do
|
97
|
+
action :remove
|
98
|
+
user 'poise_user'
|
99
|
+
group 'poise_group'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it { is_expected.to remove_group('poise_group') }
|
104
|
+
it { is_expected.to remove_user('poise_user') }
|
105
|
+
end # /context with an explicit user and group name
|
106
|
+
|
107
|
+
context 'with no group' do
|
108
|
+
recipe do
|
109
|
+
poise_service_user 'poise' do
|
110
|
+
action :remove
|
111
|
+
group false
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it { is_expected.to_not remove_group('poise') }
|
116
|
+
it { is_expected.to remove_user('poise') }
|
117
|
+
end # /context with no group
|
118
|
+
end # context with action :remove
|
119
|
+
end
|