poise-ruby 2.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.
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