berkshelf 4.0.1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.travis.yml +41 -6
  4. data/CHANGELOG.md +15 -0
  5. data/CONTRIBUTING.md +10 -0
  6. data/Gemfile.lock +332 -0
  7. data/berkshelf.gemspec +8 -6
  8. data/features/commands/install.feature +105 -8
  9. data/features/json_formatter.feature +2 -2
  10. data/features/step_definitions/chef/config_steps.rb +1 -1
  11. data/features/step_definitions/chef_server_steps.rb +2 -2
  12. data/features/step_definitions/cli_steps.rb +1 -1
  13. data/features/step_definitions/config_steps.rb +1 -1
  14. data/features/step_definitions/environment_steps.rb +2 -2
  15. data/features/step_definitions/filesystem_steps.rb +3 -5
  16. data/features/step_definitions/json_steps.rb +1 -1
  17. data/features/support/env.rb +8 -8
  18. data/generator_files/Gemfile.erb +0 -14
  19. data/lib/berkshelf/berksfile.rb +47 -0
  20. data/lib/berkshelf/downloader.rb +7 -6
  21. data/lib/berkshelf/lockfile.rb +22 -11
  22. data/lib/berkshelf/resolver.rb +27 -0
  23. data/lib/berkshelf/thor_ext/hash_with_indifferent_access.rb +5 -1
  24. data/lib/berkshelf/version.rb +1 -1
  25. data/spec/fixtures/berksfiles/default +4 -0
  26. data/spec/fixtures/cookbook-path/jenkins-config/metadata.rb +4 -0
  27. data/spec/fixtures/cookbook-store/jenkins-2.0.3/metadata.rb +6 -0
  28. data/spec/fixtures/cookbook-store/jenkins-2.0.4/metadata.rb +5 -0
  29. data/spec/fixtures/lockfiles/default.lock +5 -0
  30. data/spec/fixtures/lockfiles/orphans.lock +21 -0
  31. data/spec/support/chef_server.rb +3 -3
  32. data/spec/unit/berkshelf/berksfile_spec.rb +27 -1
  33. data/spec/unit/berkshelf/init_generator_spec.rb +2 -4
  34. data/spec/unit/berkshelf/lockfile_spec.rb +37 -0
  35. data/spec/unit/berkshelf/resolver_spec.rb +28 -1
  36. metadata +54 -15
@@ -1,5 +1,6 @@
1
1
  module Berkshelf
2
2
  class Resolver
3
+
3
4
  require_relative 'resolver/graph'
4
5
 
5
6
  extend Forwardable
@@ -23,6 +24,7 @@ module Berkshelf
23
24
  @demands = Array.new
24
25
 
25
26
  Array(demands).each { |demand| add_demand(demand) }
27
+ compute_solver_engine(berksfile)
26
28
  end
27
29
 
28
30
  # Add the given dependency to the collection of demands
@@ -102,5 +104,30 @@ module Berkshelf
102
104
  def has_demand?(demand)
103
105
  !get_demand(demand).nil?
104
106
  end
107
+
108
+ # Look at berksfile's solvers, and ask Solve#engine= for the right one,
109
+ # swallowing any exceptions if it's preferred but not required
110
+ #
111
+ # @param [Berksfile] berksfile
112
+ def compute_solver_engine(berksfile)
113
+ if berksfile.required_solver
114
+ begin
115
+ Solve.engine = berksfile.required_solver
116
+ rescue Solve::Errors::InvalidEngine => e
117
+ raise ArgumentError, e.message
118
+ end
119
+ elsif berksfile.preferred_solver
120
+ begin
121
+ Solve.engine = berksfile.preferred_solver
122
+ rescue
123
+ # We should log this, but Berkshelf.log.warn and Berkshelf.formatter.warn
124
+ # both seem inappropriate here.
125
+ # " Preferred solver ':#{berksfile.preferred_solver}' unavailable"
126
+ end
127
+ end
128
+ # We should log this, but Berkshelf.log.info and Berkshelf.formatter.msg
129
+ # both seem inappropriate here.
130
+ # " Selected dependency solver engine ':#{Solve.engine}'"
131
+ end
105
132
  end
106
133
  end
@@ -6,7 +6,11 @@ class Thor
6
6
  end
7
7
 
8
8
  def fetch(key, default = nil)
9
- super(convert_key(key), default)
9
+ if default
10
+ super(convert_key(key), default)
11
+ else
12
+ super(convert_key(key))
13
+ end
10
14
  end
11
15
  end
12
16
  end
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "4.0.1"
2
+ VERSION = "4.1.0"
3
3
  end
@@ -0,0 +1,4 @@
1
+ source 'https://supermarket.chef.io'
2
+ cookbook 'apt', '~> 2.0'
3
+ cookbook 'jenkins', '~> 2.0'
4
+ cookbook 'jenkins-config', path: '../cookbook-path/jenkins-config'
@@ -0,0 +1,4 @@
1
+ name 'jenkins-config'
2
+ version '0.1.0'
3
+
4
+ depends 'jenkins', '~> 2.0'
@@ -0,0 +1,6 @@
1
+ name 'jenkins'
2
+ version '2.0.3'
3
+
4
+ depends 'apt', '~> 2.0'
5
+ depends 'runit', '~> 1.5'
6
+ depends 'yum', '~> 3.0'
@@ -0,0 +1,5 @@
1
+ name 'jenkins'
2
+ version '2.0.4'
3
+
4
+ depends 'apt', '~> 2.0'
5
+ depends 'runit', '~> 1.5'
@@ -1,6 +1,8 @@
1
1
  DEPENDENCIES
2
2
  apt (~> 2.0)
3
3
  jenkins (~> 2.0)
4
+ jenkins-config
5
+ path: ../cookbook-path/jenkins-config
4
6
 
5
7
  GRAPH
6
8
  apt (2.3.6)
@@ -9,6 +11,9 @@ GRAPH
9
11
  apt (~> 2.0)
10
12
  runit (~> 1.5)
11
13
  yum (~> 3.0)
14
+ jenkins-config (0.1.0)
15
+ jenkins (~> 2.0)
16
+ yum (~> 3.0)
12
17
  runit (1.5.8)
13
18
  build-essential (>= 0.0.0)
14
19
  yum (~> 3.0)
@@ -0,0 +1,21 @@
1
+ DEPENDENCIES
2
+ apt (~> 2.0)
3
+ jenkins (~> 2.0)
4
+ jenkins-config
5
+ path: ../cookbook-path/jenkins-config
6
+
7
+ GRAPH
8
+ apt (2.3.6)
9
+ build-essential (1.4.2)
10
+ jenkins (2.0.3)
11
+ apt (~> 2.0)
12
+ runit (~> 1.5)
13
+ jenkins-config (0.1.0)
14
+ jenkins (~> 2.0)
15
+ runit (1.5.8)
16
+ build-essential (>= 0.0.0)
17
+ yum (3.0.6)
18
+ yum-epel (0.2.0)
19
+ yum (~> 3.0)
20
+ zum-foo (0.1.0)
21
+ yum (~> 3.0)
@@ -62,8 +62,8 @@ module Berkshelf::RSpec
62
62
  end
63
63
 
64
64
  def chef_cookbooks
65
- chef_server.data_store.list(['cookbooks']).inject({}) do |hash, name|
66
- hash[name] = chef_server.data_store.list(['cookbooks', name])
65
+ chef_server.data_store.list(['organizations', 'chef', 'cookbooks']).inject({}) do |hash, name|
66
+ hash[name] = chef_server.data_store.list(['organizations', 'chef', 'cookbooks', name])
67
67
  hash
68
68
  end
69
69
  end
@@ -77,7 +77,7 @@ module Berkshelf::RSpec
77
77
  end
78
78
 
79
79
  def chef_environment_locks(name)
80
- JSON.parse(chef_server.data_store.get(['environments', name]))['cookbook_versions']
80
+ JSON.parse(chef_server.data_store.get(['organizations', 'chef', 'environments', name]))['cookbook_versions']
81
81
  rescue ChefZero::DataStore::DataNotFoundError
82
82
  {}
83
83
  end
@@ -9,6 +9,7 @@ describe Berkshelf::Berksfile do
9
9
  cookbook 'mysql'
10
10
  cookbook 'nginx', '< 0.101.2'
11
11
  cookbook 'ssh_known_hosts2', :git => 'https://github.com/erikh/chef-ssh_known_hosts2.git'
12
+ solver :foo, :required
12
13
  EOF
13
14
  end
14
15
  let(:berksfile) { tmp_path.join('Berksfile') }
@@ -238,7 +239,7 @@ describe Berkshelf::Berksfile do
238
239
  describe '#cookbooks' do
239
240
  it 'raises an exception if a cookbook is not installed' do
240
241
  subject.add_dependency('bacon', nil)
241
- expect { subject.cookbooks }.to raise_error
242
+ expect { subject.cookbooks }.to raise_error(Berkshelf::DependencyNotFound)
242
243
  end
243
244
 
244
245
  it 'retrieves the locked (cached) cookbook for each dependency' do
@@ -406,4 +407,29 @@ describe Berkshelf::Berksfile do
406
407
  expect(excludes[:exclude].any? { |exclude| File.fnmatch?(exclude, 'my_cookbook/metadata.rb', File::FNM_DOTMATCH) }).to be(true)
407
408
  end
408
409
  end
410
+
411
+ describe '#solver' do
412
+
413
+ let(:solver_precedence) { :please_dont_exist }
414
+
415
+ it "defaults to nil required solver and :gecode preferred solver" do
416
+ expect(subject.preferred_solver).to equal(:gecode)
417
+ expect(subject.required_solver).to equal(nil)
418
+ end
419
+
420
+ it "adds preferred and required solvers" do
421
+ subject.solver(:a, :preferred)
422
+ subject.solver(:b, :required)
423
+ expect(subject.preferred_solver).to equal(:a)
424
+ expect(subject.required_solver).to equal(:b)
425
+ end
426
+
427
+ it "raises an exception with a bad precedence" do
428
+ expect { subject.solver(:foo, :bar) }.to raise_error(/Invalid solver precedence ':bar'/)
429
+ end
430
+
431
+ it "is a DSL method" do
432
+ expect(subject).to have_exposed_method(:solver)
433
+ end
434
+ end
409
435
  end
@@ -24,9 +24,7 @@ describe Berkshelf::InitGenerator do
24
24
  expect(target).to have_structure {
25
25
  file '.gitignore'
26
26
  file 'Berksfile'
27
- file 'Gemfile' do
28
- contains %(gem 'berkshelf')
29
- end
27
+ file 'Gemfile'
30
28
  file 'Vagrantfile' do
31
29
  contains %(recipe[some_cookbook::default])
32
30
  contains %(config.omnibus.chef_version = 'latest')
@@ -57,7 +55,7 @@ describe Berkshelf::InitGenerator do
57
55
  FileUtils.rm(File.join(target, 'metadata.rb'))
58
56
  expect {
59
57
  Berkshelf::InitGenerator.new([target]).invoke_all
60
- }.to raise_error(Berkshelf::NotACookbook)
58
+ }.to raise_error(Berkshelf::NotACookbook)
61
59
  end
62
60
  end
63
61
 
@@ -292,6 +292,43 @@ describe Berkshelf::Lockfile do
292
292
  expect(subject).to_not have_dependency('apache2')
293
293
  end
294
294
  end
295
+
296
+ describe '#reduce!' do
297
+ let(:berksfile_path) { fixtures_path.join('berksfiles/default').to_s }
298
+ let(:berksfile) { Berkshelf::Berksfile.from_file(berksfile_path) }
299
+
300
+ describe 'with some orphan dependencies' do
301
+ let(:orphans_lock) { fixtures_path.join('lockfiles/orphans.lock').to_s }
302
+ subject { Berkshelf::Lockfile.new(filepath: orphans_lock, berksfile: berksfile) }
303
+
304
+ it 'removes orphan dependencies' do
305
+ graph = subject.graph.instance_variable_get(:@graph)
306
+ expect(graph).to receive(:delete).with('yum-epel').and_call_original
307
+ expect(graph).to receive(:delete).with('zum-foo').and_call_original
308
+ expect(graph).to receive(:delete).with('yum').and_call_original
309
+ subject.reduce!
310
+ end
311
+ end
312
+
313
+ describe 'minimizes updates' do
314
+ subject { Berkshelf::Lockfile.new(filepath: filepath, berksfile: berksfile) }
315
+
316
+ before(:each) do
317
+ cs = fixtures_path.join('cookbook-store')
318
+ allow(Berkshelf::CookbookStore.instance).to receive(:storage_path).and_return(cs)
319
+ end
320
+
321
+ it 'uses the cookbook version specified in the lockfile' do
322
+ subject.reduce!
323
+ expect(subject.berksfile.dependencies[1].cached_cookbook.version).to eq('2.0.3')
324
+ end
325
+
326
+ it 'does not remove locks unnecessarily' do
327
+ expect(subject).to_not receive(:unlock)
328
+ subject.reduce!
329
+ end
330
+ end
331
+ end
295
332
  end
296
333
 
297
334
  describe Berkshelf::Lockfile::Graph do
@@ -4,6 +4,11 @@ describe Berkshelf::Resolver do
4
4
  let(:berksfile) { double('berksfile') }
5
5
  let(:demand) { Berkshelf::Dependency.new(berksfile, "mysql", constraint: "= 1.2.4") }
6
6
 
7
+ before(:each) do
8
+ allow(berksfile).to receive(:required_solver).and_return(nil)
9
+ allow(berksfile).to receive(:preferred_solver).and_return(nil)
10
+ end
11
+
7
12
  describe "ClassMethods" do
8
13
  describe "::initialize" do
9
14
  it 'adds the specified dependencies to the dependencies hash' do
@@ -58,5 +63,27 @@ describe Berkshelf::Resolver do
58
63
  end
59
64
  end
60
65
 
61
- describe "#resolve"
66
+ describe "#resolve" do
67
+ describe 'given a missing required solver' do
68
+ before do
69
+ allow(berksfile).to receive(:required_solver).and_return(:xyzzy)
70
+ allow(berksfile).to receive(:preferred_solver).and_return(nil)
71
+ end
72
+
73
+ it 'should raise an exception about missing required resolver :xyzzy' do
74
+ expect { subject.compute_solver_engine(berksfile) }.to raise_error(/Engine `xyzzy` is not supported/)
75
+ end
76
+ end
77
+
78
+ describe 'given a missing preferred solver' do
79
+ before do
80
+ allow(berksfile).to receive(:required_solver).and_return(nil)
81
+ allow(berksfile).to receive(:preferred_solver).and_return(:xyzzy)
82
+ end
83
+
84
+ it 'should not raise an exception about missing preferred resolver :xyzzy' do
85
+ expect { subject.compute_solver_engine(berksfile) }.not_to raise_error
86
+ end
87
+ end
88
+ end
62
89
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkshelf
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Winsor
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-10-07 00:00:00.000000000 Z
15
+ date: 2016-02-04 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: addressable
@@ -174,14 +174,14 @@ dependencies:
174
174
  requirements:
175
175
  - - "~>"
176
176
  - !ruby/object:Gem::Version
177
- version: '1.1'
177
+ version: '2.0'
178
178
  type: :runtime
179
179
  prerelease: false
180
180
  version_requirements: !ruby/object:Gem::Requirement
181
181
  requirements:
182
182
  - - "~>"
183
183
  - !ruby/object:Gem::Version
184
- version: '1.1'
184
+ version: '2.0'
185
185
  - !ruby/object:Gem::Dependency
186
186
  name: thor
187
187
  requirement: !ruby/object:Gem::Requirement
@@ -202,14 +202,14 @@ dependencies:
202
202
  requirements:
203
203
  - - "~>"
204
204
  - !ruby/object:Gem::Version
205
- version: '3.0'
205
+ version: '4.0'
206
206
  type: :runtime
207
207
  prerelease: false
208
208
  version_requirements: !ruby/object:Gem::Requirement
209
209
  requirements:
210
210
  - - "~>"
211
211
  - !ruby/object:Gem::Version
212
- version: '3.0'
212
+ version: '4.0'
213
213
  - !ruby/object:Gem::Dependency
214
214
  name: celluloid
215
215
  requirement: !ruby/object:Gem::Requirement
@@ -244,56 +244,70 @@ dependencies:
244
244
  requirements:
245
245
  - - "~>"
246
246
  - !ruby/object:Gem::Version
247
- version: '0.6'
247
+ version: 0.10.0
248
248
  type: :development
249
249
  prerelease: false
250
250
  version_requirements: !ruby/object:Gem::Requirement
251
251
  requirements:
252
252
  - - "~>"
253
253
  - !ruby/object:Gem::Version
254
- version: '0.6'
254
+ version: 0.10.0
255
255
  - !ruby/object:Gem::Dependency
256
256
  name: chef-zero
257
257
  requirement: !ruby/object:Gem::Requirement
258
258
  requirements:
259
259
  - - "~>"
260
260
  - !ruby/object:Gem::Version
261
- version: 1.5.0
261
+ version: '4.0'
262
+ type: :development
263
+ prerelease: false
264
+ version_requirements: !ruby/object:Gem::Requirement
265
+ requirements:
266
+ - - "~>"
267
+ - !ruby/object:Gem::Version
268
+ version: '4.0'
269
+ - !ruby/object:Gem::Dependency
270
+ name: dep_selector
271
+ requirement: !ruby/object:Gem::Requirement
272
+ requirements:
273
+ - - "~>"
274
+ - !ruby/object:Gem::Version
275
+ version: '1.0'
262
276
  type: :development
263
277
  prerelease: false
264
278
  version_requirements: !ruby/object:Gem::Requirement
265
279
  requirements:
266
280
  - - "~>"
267
281
  - !ruby/object:Gem::Version
268
- version: 1.5.0
282
+ version: '1.0'
269
283
  - !ruby/object:Gem::Dependency
270
284
  name: fuubar
271
285
  requirement: !ruby/object:Gem::Requirement
272
286
  requirements:
273
287
  - - "~>"
274
288
  - !ruby/object:Gem::Version
275
- version: '1.1'
289
+ version: '2.0'
276
290
  type: :development
277
291
  prerelease: false
278
292
  version_requirements: !ruby/object:Gem::Requirement
279
293
  requirements:
280
294
  - - "~>"
281
295
  - !ruby/object:Gem::Version
282
- version: '1.1'
296
+ version: '2.0'
283
297
  - !ruby/object:Gem::Dependency
284
298
  name: rake
285
299
  requirement: !ruby/object:Gem::Requirement
286
300
  requirements:
287
301
  - - "~>"
288
302
  - !ruby/object:Gem::Version
289
- version: '0.9'
303
+ version: '10.1'
290
304
  type: :development
291
305
  prerelease: false
292
306
  version_requirements: !ruby/object:Gem::Requirement
293
307
  requirements:
294
308
  - - "~>"
295
309
  - !ruby/object:Gem::Version
296
- version: '0.9'
310
+ version: '10.1'
297
311
  - !ruby/object:Gem::Dependency
298
312
  name: rspec
299
313
  requirement: !ruby/object:Gem::Requirement
@@ -364,6 +378,20 @@ dependencies:
364
378
  - - "~>"
365
379
  - !ruby/object:Gem::Version
366
380
  version: '0.8'
381
+ - !ruby/object:Gem::Dependency
382
+ name: http
383
+ requirement: !ruby/object:Gem::Requirement
384
+ requirements:
385
+ - - "~>"
386
+ - !ruby/object:Gem::Version
387
+ version: 0.9.8
388
+ type: :development
389
+ prerelease: false
390
+ version_requirements: !ruby/object:Gem::Requirement
391
+ requirements:
392
+ - - "~>"
393
+ - !ruby/object:Gem::Version
394
+ version: 0.9.8
367
395
  description: Manages a Cookbook's, or an Application's, Cookbook dependencies
368
396
  email:
369
397
  - jamie@vialstudios.com
@@ -381,6 +409,7 @@ files:
381
409
  - CHANGELOG.md
382
410
  - CONTRIBUTING.md
383
411
  - Gemfile
412
+ - Gemfile.lock
384
413
  - Guardfile
385
414
  - LICENSE
386
415
  - PLUGINS.md
@@ -496,6 +525,10 @@ files:
496
525
  - spec/config/knife.rb
497
526
  - spec/config/validator.pem
498
527
  - spec/fixtures/Berksfile
528
+ - spec/fixtures/berksfiles/default
529
+ - spec/fixtures/cookbook-path/jenkins-config/metadata.rb
530
+ - spec/fixtures/cookbook-store/jenkins-2.0.3/metadata.rb
531
+ - spec/fixtures/cookbook-store/jenkins-2.0.4/metadata.rb
499
532
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md
500
533
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb
501
534
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb
@@ -510,6 +543,7 @@ files:
510
543
  - spec/fixtures/lockfiles/blank.lock
511
544
  - spec/fixtures/lockfiles/default.lock
512
545
  - spec/fixtures/lockfiles/empty.lock
546
+ - spec/fixtures/lockfiles/orphans.lock
513
547
  - spec/spec_helper.rb
514
548
  - spec/support/chef_api.rb
515
549
  - spec/support/chef_server.rb
@@ -576,7 +610,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
576
610
  version: 1.8.0
577
611
  requirements: []
578
612
  rubyforge_project:
579
- rubygems_version: 2.2.2
613
+ rubygems_version: 2.4.7
580
614
  signing_key:
581
615
  specification_version: 4
582
616
  summary: Manages a Cookbook's, or an Application's, Cookbook dependencies
@@ -623,6 +657,10 @@ test_files:
623
657
  - spec/config/knife.rb
624
658
  - spec/config/validator.pem
625
659
  - spec/fixtures/Berksfile
660
+ - spec/fixtures/berksfiles/default
661
+ - spec/fixtures/cookbook-path/jenkins-config/metadata.rb
662
+ - spec/fixtures/cookbook-store/jenkins-2.0.3/metadata.rb
663
+ - spec/fixtures/cookbook-store/jenkins-2.0.4/metadata.rb
626
664
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/README.md
627
665
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/metadata.rb
628
666
  - spec/fixtures/cookbooks/example_cookbook-0.5.0/recipes/default.rb
@@ -637,6 +675,7 @@ test_files:
637
675
  - spec/fixtures/lockfiles/blank.lock
638
676
  - spec/fixtures/lockfiles/default.lock
639
677
  - spec/fixtures/lockfiles/empty.lock
678
+ - spec/fixtures/lockfiles/orphans.lock
640
679
  - spec/spec_helper.rb
641
680
  - spec/support/chef_api.rb
642
681
  - spec/support/chef_server.rb