poise-ruby 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.kitchen.travis.yml +9 -0
  4. data/.kitchen.yml +9 -0
  5. data/.travis.yml +20 -0
  6. data/.yardopts +7 -0
  7. data/Berksfile +28 -0
  8. data/Gemfile +33 -0
  9. data/LICENSE +201 -0
  10. data/README.md +290 -0
  11. data/Rakefile +17 -0
  12. data/chef/attributes/default.rb +23 -0
  13. data/chef/recipes/default.rb +19 -0
  14. data/lib/poise_ruby.rb +24 -0
  15. data/lib/poise_ruby/cheftie.rb +18 -0
  16. data/lib/poise_ruby/error.rb +21 -0
  17. data/lib/poise_ruby/resources.rb +29 -0
  18. data/lib/poise_ruby/resources/bundle_install.rb +221 -0
  19. data/lib/poise_ruby/resources/ruby_execute.rb +91 -0
  20. data/lib/poise_ruby/resources/ruby_gem.rb +118 -0
  21. data/lib/poise_ruby/resources/ruby_runtime.rb +87 -0
  22. data/lib/poise_ruby/ruby_command_mixin.rb +59 -0
  23. data/lib/poise_ruby/ruby_providers.rb +32 -0
  24. data/lib/poise_ruby/ruby_providers/base.rb +116 -0
  25. data/lib/poise_ruby/ruby_providers/chef.rb +53 -0
  26. data/lib/poise_ruby/ruby_providers/scl.rb +77 -0
  27. data/lib/poise_ruby/ruby_providers/system.rb +115 -0
  28. data/lib/poise_ruby/version.rb +20 -0
  29. data/poise-ruby.gemspec +41 -0
  30. data/test/cookbooks/poise-ruby_test/metadata.rb +18 -0
  31. data/test/cookbooks/poise-ruby_test/recipes/bundle_install.rb +102 -0
  32. data/test/cookbooks/poise-ruby_test/recipes/default.rb +85 -0
  33. data/test/gemfiles/chef-12.gemfile +19 -0
  34. data/test/gemfiles/master.gemfile +23 -0
  35. data/test/integration/default/serverspec/bundle_install_spec.rb +73 -0
  36. data/test/integration/default/serverspec/default_spec.rb +46 -0
  37. data/test/spec/resources/bundle_install_spec.rb +306 -0
  38. data/test/spec/resources/ruby_execute_spec.rb +78 -0
  39. data/test/spec/ruby_command_mixin_spec.rb +34 -0
  40. data/test/spec/spec_helper.rb +18 -0
  41. metadata +155 -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
+ eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
18
+
19
+ gem 'chef', '~> 12.0'
@@ -0,0 +1,23 @@
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
+ eval_gemfile File.expand_path('../../../Gemfile', __FILE__)
18
+
19
+ gem 'chef', github: 'chef/chef'
20
+ gem 'halite', github: 'poise/halite'
21
+ gem 'poise', github: 'poise/poise'
22
+ gem 'poise-boiler', github: 'poise/poise-boiler'
23
+ gem 'poise-languages', github: 'poise/poise-languages'
@@ -0,0 +1,73 @@
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 'serverspec'
18
+ set :backend, :exec
19
+
20
+ describe 'bundle_install' do
21
+ describe 'system-level install' do
22
+ rake_binary = case os[:family]
23
+ when 'debian', 'ubuntu'
24
+ '/usr/local/bin/rake'
25
+ when 'redhat'
26
+ case os[:release]
27
+ when /^6/
28
+ '/usr/bin/rake'
29
+ else
30
+ '/usr/local/bin/rake'
31
+ end
32
+ end
33
+
34
+ describe file(rake_binary) do
35
+ it { is_expected.to be_a_file }
36
+ end
37
+
38
+ describe command("#{rake_binary} --version") do
39
+ its(:exit_status) { is_expected.to eq 0 }
40
+ end
41
+ end
42
+
43
+ describe 'deployment install' do
44
+ describe file('/opt/bundle2/bin/rake') do
45
+ it { is_expected.to be_a_file }
46
+ end
47
+
48
+ describe command('/opt/bundle2/bin/rake --version') do
49
+ its(:exit_status) { is_expected.to eq 0 }
50
+ its(:stdout) { is_expected.to include('10.4.2') }
51
+ end
52
+
53
+ describe 'notifications' do
54
+ describe file('/opt/bundle2/sentinel1') do
55
+ it { is_expected.to be_a_file }
56
+ end
57
+
58
+ describe file('/opt/bundle2/sentinel2') do
59
+ it { is_expected.to_not be_a_file }
60
+ end
61
+ end
62
+ end
63
+
64
+ describe 'scl provider', if: File.exist?('/opt/bundle3') do
65
+ describe file('/opt/bundle3/bin/rake') do
66
+ it { is_expected.to be_a_file }
67
+ end
68
+
69
+ describe command('/opt/bundle3/bin/rake --version') do
70
+ its(:exit_status) { is_expected.to eq 0 }
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,46 @@
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 'serverspec'
18
+ set :backend, :exec
19
+
20
+ describe 'ruby_runtime' do
21
+ describe file('/root/one') do
22
+ it { is_expected.to be_a_file }
23
+ end
24
+
25
+ describe file('/root/two') do
26
+ it { is_expected.to be_a_file }
27
+ its(:content) { are_expected.to start_with '2.1' }
28
+ end
29
+
30
+ describe file('/root/three') do
31
+ it { is_expected.to be_a_file }
32
+ its(:content) { are_expected.to eq '1.5' }
33
+ end
34
+
35
+ describe 'scl provider', if: File.exist?('/root/scl') do
36
+ describe file('/root/four') do
37
+ it { is_expected.to be_a_file }
38
+ its(:content) { are_expected.to eq '2.2.2' }
39
+ end
40
+
41
+ describe file('/root/five') do
42
+ it { is_expected.to be_a_file }
43
+ its(:content) { are_expected.to eq '1.5' }
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,306 @@
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 PoiseRuby::Resources::BundleInstall do
20
+ describe PoiseRuby::Resources::BundleInstall::Resource do
21
+ recipe do
22
+ bundle_install '/test/Gemfile'
23
+ end
24
+ before do
25
+ allow_any_instance_of(described_class).to receive(:which).with('ruby').and_return('/test/bin/ruby')
26
+ end
27
+
28
+ it { is_expected.to install_bundle_install('/test/Gemfile').with(gem_binary: '/test/bin/gem') }
29
+
30
+ # Just testing this for coverage of the update_bundle_install matcher
31
+ context 'with action :update' do
32
+ recipe do
33
+ bundle_install '/test/Gemfile' do
34
+ action :update
35
+ end
36
+ end
37
+
38
+ it { is_expected.to update_bundle_install('/test/Gemfile') }
39
+ end # /context with action :update
40
+ end # /describe PoiseRuby::Resources::BundleInstall::Resource
41
+
42
+ describe PoiseRuby::Resources::BundleInstall::Provider do
43
+ let(:new_resource) { double('new_resource', parent_ruby: nil, timeout: 900, ruby: '/usr/bin/ruby', user: nil) }
44
+ let(:provider) { described_class.new(new_resource, nil) }
45
+
46
+ describe '#action_install' do
47
+ it do
48
+ expect(provider).to receive(:run_bundler).with('install')
49
+ provider.action_install
50
+ end
51
+ end # /describe #action_install
52
+
53
+ describe '#action_update' do
54
+ it do
55
+ expect(provider).to receive(:run_bundler).with('update')
56
+ provider.action_update
57
+ end
58
+ end # /describe #action_update
59
+
60
+ describe '#run_bundler' do
61
+ let(:bundle_output) { '' }
62
+ subject { provider.send(:run_bundler, nil) }
63
+ before do
64
+ allow(provider).to receive(:bundler_command).and_return(%w{bundle install})
65
+ allow(provider).to receive(:gemfile_path).and_return('Gemfile')
66
+ expect(provider).to receive(:ruby_shell_out!).with(%w{bundle install}, environment: {'BUNDLE_GEMFILE' => 'Gemfile'}, user: nil).and_return(double(stdout: bundle_output))
67
+ end
68
+
69
+ context 'with a new gem' do
70
+ let(:bundle_output) { <<-EOH }
71
+ Fetching gem metadata from https://rubygems.org/.......
72
+ Fetching version metadata from https://rubygems.org/...
73
+ Fetching dependency metadata from https://rubygems.org/..
74
+ Resolving dependencies...
75
+ Using rake 10.4.2
76
+ Using addressable 2.3.7
77
+ Installing launchy 2.4.3
78
+ Using poise 1.1.0 from source at /Users/coderanger/src/poise
79
+ Using poise-application 5.0.0 from source at /Users/coderanger/src/application
80
+ Using poise-service 1.0.0 from source at /Users/coderanger/src/poise-service
81
+ Using poise-application-ruby 4.0.0 from source at .
82
+ Using yard-classmethods 1.0 from source at /Users/coderanger/src/yard-classmethods
83
+ Using poise-boiler 1.0.0 from source at /Users/coderanger/src/poise-boiler
84
+ Bundle complete! 7 Gemfile dependencies, 115 gems now installed.
85
+ Use `bundle show [gemname]` to see where a bundled gem is installed.
86
+ EOH
87
+ it do
88
+ expect(new_resource).to receive(:updated_by_last_action).with(true)
89
+ subject
90
+ end
91
+ end # /context with a new gem
92
+
93
+ context 'with existing gems' do
94
+ let(:bundle_output) { <<-EOH }
95
+ Fetching gem metadata from https://rubygems.org/.......
96
+ Fetching version metadata from https://rubygems.org/...
97
+ Fetching dependency metadata from https://rubygems.org/..
98
+ Resolving dependencies...
99
+ Using rake 10.4.2
100
+ Using addressable 2.3.7
101
+ Using launchy 2.4.3
102
+ Using poise 1.1.0 from source at /Users/coderanger/src/poise
103
+ Using poise-application 5.0.0 from source at /Users/coderanger/src/application
104
+ Using poise-service 1.0.0 from source at /Users/coderanger/src/poise-service
105
+ Using poise-application-ruby 4.0.0 from source at .
106
+ Using yard-classmethods 1.0 from source at /Users/coderanger/src/yard-classmethods
107
+ Using poise-boiler 1.0.0 from source at /Users/coderanger/src/poise-boiler
108
+ Bundle complete! 7 Gemfile dependencies, 115 gems now installed.
109
+ Use `bundle show [gemname]` to see where a bundled gem is installed.
110
+ EOH
111
+ # No-op to ensure #updated_by_last_action is not called.
112
+ it { subject }
113
+ end # /context with existing gems
114
+ end # /describe #run_bundler
115
+
116
+ describe '#gem_bin' do
117
+ let(:new_resource) { double('new_resource', gem_binary: '/usr/local/bin/gem', parent_ruby: nil, timeout: 900, ruby: '/usr/bin/ruby') }
118
+ let(:gem_environment) { '' }
119
+ subject { provider.send(:gem_bindir) }
120
+ before do
121
+ expect(provider).to receive(:ruby_shell_out!).with('/usr/local/bin/gem', 'environment').and_return(double(stdout: gem_environment))
122
+ end
123
+
124
+ context 'with an Ubuntu 14.04 gem environment' do
125
+ let(:gem_environment) { <<-EOH }
126
+ RubyGems Environment:
127
+ - RUBYGEMS VERSION: 1.8.23
128
+ - RUBY VERSION: 1.9.3 (2013-11-22 patchlevel 484) [x86_64-linux]
129
+ - INSTALLATION DIRECTORY: /var/lib/gems/1.9.1
130
+ - RUBY EXECUTABLE: /usr/bin/ruby1.9.1
131
+ - EXECUTABLE DIRECTORY: /usr/local/bin
132
+ - RUBYGEMS PLATFORMS:
133
+ - ruby
134
+ - x86_64-linux
135
+ - GEM PATHS:
136
+ - /var/lib/gems/1.9.1
137
+ - /root/.gem/ruby/1.9.1
138
+ - GEM CONFIGURATION:
139
+ - :update_sources => true
140
+ - :verbose => true
141
+ - :benchmark => false
142
+ - :backtrace => false
143
+ - :bulk_threshold => 1000
144
+ - REMOTE SOURCES:
145
+ - http://rubygems.org/
146
+ EOH
147
+ it { is_expected.to eq '/usr/local/bin' }
148
+ end # /context Ubuntu 14.04 gem environment
149
+
150
+ context 'with an rbenv gem environment' do
151
+ let(:gem_environment) { <<-EOH }
152
+ RubyGems Environment:
153
+ - RUBYGEMS VERSION: 2.2.2
154
+ - RUBY VERSION: 2.1.2 (2014-05-08 patchlevel 95) [x86_64-darwin13.0]
155
+ - INSTALLATION DIRECTORY: /Users/asmithee/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0
156
+ - RUBY EXECUTABLE: /Users/asmithee/.rbenv/versions/2.1.2/bin/ruby
157
+ - EXECUTABLE DIRECTORY: /Users/asmithee/.rbenv/versions/2.1.2/bin
158
+ - SPEC CACHE DIRECTORY: /Users/asmithee/.gem/specs
159
+ - RUBYGEMS PLATFORMS:
160
+ - ruby
161
+ - x86_64-darwin-13
162
+ - GEM PATHS:
163
+ - /Users/asmithee/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0
164
+ - /Users/asmithee/.gem/ruby/2.1.0
165
+ - GEM CONFIGURATION:
166
+ - :update_sources => true
167
+ - :verbose => true
168
+ - :backtrace => false
169
+ - :bulk_threshold => 1000
170
+ - "gem" => "--no-ri --no-rdoc"
171
+ - REMOTE SOURCES:
172
+ - https://rubygems.org/
173
+ - SHELL PATH:
174
+ - /Users/asmithee/.rbenv/versions/2.1.2/bin
175
+ - /usr/local/opt/rbenv/libexec
176
+ - /Users/asmithee/.rbenv/shims
177
+ - /usr/local/opt/rbenv/bin
178
+ - /opt/vagrant/bin
179
+ - /Users/asmithee/.rbcompile/bin
180
+ - /usr/local/share/npm/bin
181
+ - /usr/local/share/python
182
+ - /usr/local/bin
183
+ - /usr/bin
184
+ - /bin
185
+ - /usr/sbin
186
+ - /sbin
187
+ - /usr/local/bin
188
+ - /usr/local/MacGPG2/bin
189
+ - /usr/texbin
190
+ EOH
191
+ it { is_expected.to eq '/Users/asmithee/.rbenv/versions/2.1.2/bin' }
192
+ end # /context rbenv gem environment
193
+
194
+ context 'with no executable directory' do
195
+ it { expect { subject }.to raise_error(PoiseRuby::Error) }
196
+ end # /context with no executable directory
197
+ end # /describe #gem_bin
198
+
199
+ describe '#bundler_options' do
200
+ let(:default_options) { %i{binstubs deployment without jobs retry vendor}.inject({}) {|memo, v| memo[v] = nil; memo } }
201
+ let(:options) { {} }
202
+ let(:new_resource) { double('new_resource', default_options.merge(options)) }
203
+ subject { provider.send(:bundler_options) }
204
+
205
+ context 'with binstubs' do
206
+ let(:options) { {binstubs: true} }
207
+ it { is_expected.to eq %w{--binstubs} }
208
+ end # /context with binstubs
209
+
210
+ context 'with binstubs in a path' do
211
+ let(:options) { {binstubs: 'bin'} }
212
+ it { is_expected.to eq %w{--binstubs=bin} }
213
+ end # /context with binstubs in a path
214
+
215
+ context 'with deployment' do
216
+ let(:options) { {deployment: true} }
217
+ it { is_expected.to eq %w{--deployment} }
218
+ end # /context with deployment
219
+
220
+ context 'with without groups' do
221
+ let(:options) { {without: %w{development test}} }
222
+ it { is_expected.to eq %w{--without development test} }
223
+ end # /context with without groups
224
+
225
+ context 'with jobs' do
226
+ let(:options) { {jobs: 3} }
227
+ it { is_expected.to eq %w{--jobs=3} }
228
+ end # /context with jobs
229
+
230
+ context 'with retry' do
231
+ let(:options) { {retry: 3} }
232
+ it { is_expected.to eq %w{--retry=3} }
233
+ end # /context with jobs
234
+
235
+ context 'with vendor' do
236
+ let(:options) { {vendor: true} }
237
+ it { is_expected.to eq %w{--path=vendor/bundle} }
238
+ end # /context with vendor
239
+
240
+ context 'with vendor in a path' do
241
+ let(:options) { {vendor: 'vendor'} }
242
+ it { is_expected.to eq %w{--path=vendor} }
243
+ end # /context with vendor in a path
244
+
245
+ context 'with several options' do
246
+ let(:options) { {deployment: true, binstubs: 'bin', without: %w{test development}} }
247
+ it { is_expected.to eq %w{--binstubs=bin --deployment --without test development} }
248
+ end # /context with several options
249
+ end # /describe #bundler_options
250
+
251
+ describe '#bundler_command' do
252
+ let(:action) { '' }
253
+ subject { provider.send(:bundler_command, action) }
254
+ before do
255
+ allow(provider).to receive(:gem_bindir).and_return('/test')
256
+ allow(provider).to receive(:bundler_options).and_return(%w{--binstubs --deployment})
257
+ end
258
+
259
+ context 'with action install' do
260
+ let(:action) { 'install' }
261
+ it { is_expected.to eq %w{/test/bundle install --binstubs --deployment} }
262
+ end # /context with action install
263
+
264
+ context 'with action update' do
265
+ let(:action) { 'update' }
266
+ it { is_expected.to eq %w{/test/bundle update --binstubs --deployment} }
267
+ end # /context with action update
268
+ end # /describe #bundler_command
269
+
270
+ describe '#gemfile_path' do
271
+ let(:path) { '' }
272
+ let(:files) { [] }
273
+ let(:new_resource) { double('new_resource', path: path) }
274
+ subject { provider.send(:gemfile_path) }
275
+ before do
276
+ allow(File).to receive(:file?).and_return(false)
277
+ files.each do |file|
278
+ allow(File).to receive(:file?).with(file).and_return(true)
279
+ end
280
+ end
281
+
282
+ context 'with a simple file' do
283
+ let(:path) { '/test/Gemfile' }
284
+ let(:files) { %w{/test/Gemfile} }
285
+ it { is_expected.to eq '/test/Gemfile' }
286
+ end # /context with a simple file
287
+
288
+ context 'with a folder' do
289
+ let(:path) { '/test' }
290
+ let(:files) { %w{/test/Gemfile} }
291
+ it { is_expected.to eq '/test/Gemfile' }
292
+ end # /context with a folder
293
+
294
+ context 'with a parent folder' do
295
+ let(:path) { '/test/inner' }
296
+ let(:files) { %w{/test/Gemfile} }
297
+ it { is_expected.to eq '/test/Gemfile' }
298
+ end # /context with a parent folder
299
+
300
+ context 'with no Gemfile' do
301
+ let(:path) { '/test/Gemfile' }
302
+ it { is_expected.to be_nil }
303
+ end # /context with no Gemfile
304
+ end # /describe #gemfile_path
305
+ end # /describe PoiseRuby::Resources::BundleInstall::Provider
306
+ end