berkshelf 0.4.0.rc4 → 0.4.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.
- data/.gitignore +2 -0
- data/Guardfile +6 -3
- data/features/default_locations.feature +122 -0
- data/features/install.feature +20 -4
- data/features/lockfile.feature +1 -6
- data/features/update.feature +2 -3
- data/generator_files/Berksfile.erb +2 -0
- data/generator_files/gitignore.erb +6 -0
- data/lib/berkshelf.rb +6 -10
- data/lib/berkshelf/berksfile.rb +203 -14
- data/lib/berkshelf/cached_cookbook.rb +5 -1
- data/lib/berkshelf/cli.rb +4 -0
- data/lib/berkshelf/cookbook_source.rb +49 -91
- data/lib/berkshelf/cookbook_store.rb +2 -0
- data/lib/berkshelf/downloader.rb +71 -51
- data/lib/berkshelf/errors.rb +7 -3
- data/lib/berkshelf/formatters.rb +6 -6
- data/lib/berkshelf/location.rb +171 -0
- data/lib/berkshelf/locations/chef_api_location.rb +252 -0
- data/lib/berkshelf/locations/git_location.rb +76 -0
- data/lib/berkshelf/locations/path_location.rb +38 -0
- data/lib/berkshelf/locations/site_location.rb +150 -0
- data/lib/berkshelf/lockfile.rb +2 -2
- data/lib/berkshelf/resolver.rb +12 -15
- data/lib/berkshelf/uploader.rb +2 -9
- data/lib/berkshelf/version.rb +1 -1
- data/spec/fixtures/lockfile_spec/without_lock/.gitkeep +0 -0
- data/spec/support/chef_api.rb +7 -1
- data/spec/unit/berkshelf/berksfile_spec.rb +157 -12
- data/spec/unit/berkshelf/cached_cookbook_spec.rb +19 -0
- data/spec/unit/berkshelf/cookbook_generator_spec.rb +1 -0
- data/spec/unit/berkshelf/cookbook_source_spec.rb +25 -35
- data/spec/unit/berkshelf/cookbook_store_spec.rb +3 -3
- data/spec/unit/berkshelf/downloader_spec.rb +171 -43
- data/spec/unit/berkshelf/formatters_spec.rb +13 -16
- data/spec/unit/berkshelf/{cookbook_source/location_spec.rb → location_spec.rb} +10 -10
- data/spec/unit/berkshelf/{cookbook_source → locations}/chef_api_location_spec.rb +4 -4
- data/spec/unit/berkshelf/{cookbook_source → locations}/git_location_spec.rb +8 -8
- data/spec/unit/berkshelf/{cookbook_source → locations}/path_location_spec.rb +5 -5
- data/spec/unit/berkshelf/{cookbook_source → locations}/site_location_spec.rb +17 -3
- data/spec/unit/berkshelf/lockfile_spec.rb +26 -17
- data/spec/unit/berkshelf/resolver_spec.rb +6 -5
- data/spec/unit/berkshelf/uploader_spec.rb +6 -4
- metadata +27 -31
- data/lib/berkshelf/cookbook_source/chef_api_location.rb +0 -256
- data/lib/berkshelf/cookbook_source/git_location.rb +0 -78
- data/lib/berkshelf/cookbook_source/location.rb +0 -167
- data/lib/berkshelf/cookbook_source/path_location.rb +0 -40
- data/lib/berkshelf/cookbook_source/site_location.rb +0 -149
- data/lib/berkshelf/dsl.rb +0 -45
- data/lib/berkshelf/tx_result.rb +0 -12
- data/lib/berkshelf/tx_result_set.rb +0 -37
- data/spec/fixtures/lockfile_spec/without_lock/Berksfile.lock +0 -5
- data/spec/unit/berkshelf/dsl_spec.rb +0 -42
- data/spec/unit/berkshelf/tx_result_set_spec.rb +0 -77
- data/spec/unit/berkshelf/tx_result_spec.rb +0 -21
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module Berkshelf
|
4
|
-
describe
|
4
|
+
describe PathLocation do
|
5
5
|
let(:complacent_constraint) { double('comp-vconstraint', satisfies?: true) }
|
6
6
|
let(:path) { fixtures_path.join("cookbooks", "example_cookbook").to_s }
|
7
|
-
subject {
|
7
|
+
subject { PathLocation.new("nginx", complacent_constraint, path: path) }
|
8
8
|
|
9
9
|
describe "#download" do
|
10
10
|
it "returns an instance of CachedCookbook" do
|
@@ -18,7 +18,7 @@ module Berkshelf
|
|
18
18
|
end
|
19
19
|
|
20
20
|
context "given a path that does not exist" do
|
21
|
-
subject {
|
21
|
+
subject { PathLocation.new("doesnot_exist", complacent_constraint, path: tmp_path.join("doesntexist_noway")) }
|
22
22
|
|
23
23
|
it "raises a CookbookNotFound error" do
|
24
24
|
lambda {
|
@@ -28,7 +28,7 @@ module Berkshelf
|
|
28
28
|
end
|
29
29
|
|
30
30
|
context "given a path that does not contain a cookbook" do
|
31
|
-
subject {
|
31
|
+
subject { PathLocation.new("doesnot_exist", complacent_constraint, path: fixtures_path) }
|
32
32
|
|
33
33
|
it "raises a CookbookNotFound error" do
|
34
34
|
lambda {
|
@@ -38,7 +38,7 @@ module Berkshelf
|
|
38
38
|
end
|
39
39
|
|
40
40
|
context "given the content at path does not satisfy the version constraint" do
|
41
|
-
subject {
|
41
|
+
subject { PathLocation.new("nginx", double('constraint', satisfies?: false), path: path) }
|
42
42
|
|
43
43
|
it "raises a ConstraintNotSatisfied error" do
|
44
44
|
lambda {
|
@@ -1,9 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
module Berkshelf
|
4
|
-
describe
|
4
|
+
describe SiteLocation do
|
5
|
+
describe "ClassMethods" do
|
6
|
+
subject { SiteLocation }
|
7
|
+
|
8
|
+
describe "::initialize" do
|
9
|
+
context "given the symbol :opscode for the value of URI" do
|
10
|
+
it "creates a SiteLocation with a URI equal to the default Opscode Community Site API" do
|
11
|
+
result = subject.new("nginx", double('constraint'), site: :opscode)
|
12
|
+
|
13
|
+
result.api_uri.should eql(Location::OPSCODE_COMMUNITY_API)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
5
19
|
let(:complacent_constraint) { double('comp-vconstraint', satisfies?: true) }
|
6
|
-
subject {
|
20
|
+
subject { SiteLocation.new("nginx", complacent_constraint) }
|
7
21
|
|
8
22
|
describe "#download" do
|
9
23
|
before(:each) do
|
@@ -44,7 +58,7 @@ module Berkshelf
|
|
44
58
|
|
45
59
|
context "given an explicit :site location key" do
|
46
60
|
subject do
|
47
|
-
|
61
|
+
SiteLocation.new("nginx",
|
48
62
|
complacent_constraint,
|
49
63
|
site: "http://cookbooks.opscode.com/api/v1/cookbooks"
|
50
64
|
)
|
@@ -1,25 +1,34 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
4
|
-
describe
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
module Berkshelf
|
4
|
+
describe Lockfile do
|
5
|
+
let(:downloader) { Downloader.new(Berkshelf.cookbook_store) }
|
6
|
+
|
7
|
+
describe "without a lockfile in place already" do
|
8
|
+
before(:all) do
|
9
|
+
@old_dir = Dir.pwd
|
10
|
+
Dir.chdir fixtures_path.join("lockfile_spec", "without_lock")
|
11
|
+
end
|
12
|
+
|
13
|
+
after(:all) do
|
14
|
+
FileUtils.rm(fixtures_path.join("lockfile_spec", "without_lock", "Berksfile.lock"))
|
15
|
+
Dir.chdir(@old_dir)
|
16
|
+
end
|
9
17
|
|
10
|
-
|
11
|
-
|
12
|
-
|
18
|
+
it "should be able to write a Berksfile.lock from a list of cookbooks" do
|
19
|
+
resolver = Resolver.new(downloader, sources: CookbookSource.new('nginx', constraint: '= 0.101.0'))
|
20
|
+
resolver.resolve
|
13
21
|
|
14
|
-
|
22
|
+
Lockfile.new(resolver.sources).write
|
15
23
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
24
|
+
File.read('Berksfile.lock').split(/\r?\n/).sort.should == [
|
25
|
+
"cookbook 'bluepill', :locked_version => '1.0.4'",
|
26
|
+
"cookbook 'build-essential', :locked_version => '1.0.2'",
|
27
|
+
"cookbook 'nginx', :locked_version => '0.101.0'",
|
28
|
+
"cookbook 'ohai', :locked_version => '1.0.2'",
|
29
|
+
"cookbook 'runit', :locked_version => '0.15.0'"
|
30
|
+
]
|
31
|
+
end
|
23
32
|
end
|
24
33
|
end
|
25
34
|
end
|
@@ -36,16 +36,16 @@ module Berkshelf
|
|
36
36
|
subject { Resolver }
|
37
37
|
|
38
38
|
describe "::initialize" do
|
39
|
-
let(:downloader) { Berkshelf.
|
39
|
+
let(:downloader) { Downloader.new(Berkshelf.cookbook_store) }
|
40
40
|
|
41
41
|
it "adds the specified sources to the sources hash" do
|
42
|
-
resolver = subject.new(downloader, source)
|
42
|
+
resolver = subject.new(downloader, sources: source)
|
43
43
|
|
44
44
|
resolver.should have_source(source.name)
|
45
45
|
end
|
46
46
|
|
47
47
|
it "adds the dependencies of the source as sources" do
|
48
|
-
resolver = subject.new(downloader, source)
|
48
|
+
resolver = subject.new(downloader, sources: source)
|
49
49
|
|
50
50
|
resolver.should have_source("nginx")
|
51
51
|
resolver.should have_source("artifact")
|
@@ -54,7 +54,7 @@ module Berkshelf
|
|
54
54
|
context "given an array of sources" do
|
55
55
|
it "adds each source to the sources hash" do
|
56
56
|
sources = [source]
|
57
|
-
resolver = subject.new(downloader, sources)
|
57
|
+
resolver = subject.new(downloader, sources: sources)
|
58
58
|
|
59
59
|
resolver.should have_source(sources[0].name)
|
60
60
|
end
|
@@ -62,7 +62,8 @@ module Berkshelf
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
|
65
|
+
let(:downloader) { Downloader.new(Berkshelf.cookbook_store) }
|
66
|
+
subject { Resolver.new(downloader) }
|
66
67
|
|
67
68
|
describe "#add_source" do
|
68
69
|
let(:package_version) { double('package-version', dependencies: Array.new) }
|
@@ -20,16 +20,18 @@ module Berkshelf
|
|
20
20
|
subject.should_receive(:save_cookbook)
|
21
21
|
end
|
22
22
|
|
23
|
-
it "returns
|
24
|
-
subject.upload(cookbook).should
|
23
|
+
it "returns true" do
|
24
|
+
subject.upload(cookbook).should be_true
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
28
|
context "when cookbook is not valid" do
|
29
29
|
before(:each) { cookbook.should_receive(:validate!).and_raise(CookbookSyntaxError) }
|
30
30
|
|
31
|
-
it "
|
32
|
-
|
31
|
+
it "raises a CookbookSyntaxError error" do
|
32
|
+
lambda {
|
33
|
+
subject.upload(cookbook)
|
34
|
+
}.should raise_error(CookbookSyntaxError)
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
metadata
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: berkshelf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.0
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.0
|
5
|
+
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Josiah Kiehl
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2012-
|
15
|
+
date: 2012-09-11 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: solve
|
@@ -371,6 +371,7 @@ files:
|
|
371
371
|
- berkshelf.gemspec
|
372
372
|
- bin/berks
|
373
373
|
- features/cookbook_command.feature
|
374
|
+
- features/default_locations.feature
|
374
375
|
- features/init_command.feature
|
375
376
|
- features/install.feature
|
376
377
|
- features/json_formatter.feature
|
@@ -405,11 +406,6 @@ files:
|
|
405
406
|
- lib/berkshelf/cli.rb
|
406
407
|
- lib/berkshelf/cookbook_generator.rb
|
407
408
|
- lib/berkshelf/cookbook_source.rb
|
408
|
-
- lib/berkshelf/cookbook_source/chef_api_location.rb
|
409
|
-
- lib/berkshelf/cookbook_source/git_location.rb
|
410
|
-
- lib/berkshelf/cookbook_source/location.rb
|
411
|
-
- lib/berkshelf/cookbook_source/path_location.rb
|
412
|
-
- lib/berkshelf/cookbook_source/site_location.rb
|
413
409
|
- lib/berkshelf/cookbook_store.rb
|
414
410
|
- lib/berkshelf/core_ext.rb
|
415
411
|
- lib/berkshelf/core_ext/file.rb
|
@@ -418,18 +414,20 @@ files:
|
|
418
414
|
- lib/berkshelf/core_ext/pathname.rb
|
419
415
|
- lib/berkshelf/core_ext/string.rb
|
420
416
|
- lib/berkshelf/downloader.rb
|
421
|
-
- lib/berkshelf/dsl.rb
|
422
417
|
- lib/berkshelf/errors.rb
|
423
418
|
- lib/berkshelf/formatters.rb
|
424
419
|
- lib/berkshelf/formatters/human_readable.rb
|
425
420
|
- lib/berkshelf/formatters/json.rb
|
426
421
|
- lib/berkshelf/git.rb
|
427
422
|
- lib/berkshelf/init_generator.rb
|
423
|
+
- lib/berkshelf/location.rb
|
424
|
+
- lib/berkshelf/locations/chef_api_location.rb
|
425
|
+
- lib/berkshelf/locations/git_location.rb
|
426
|
+
- lib/berkshelf/locations/path_location.rb
|
427
|
+
- lib/berkshelf/locations/site_location.rb
|
428
428
|
- lib/berkshelf/lockfile.rb
|
429
429
|
- lib/berkshelf/resolver.rb
|
430
430
|
- lib/berkshelf/thor.rb
|
431
|
-
- lib/berkshelf/tx_result.rb
|
432
|
-
- lib/berkshelf/tx_result_set.rb
|
433
431
|
- lib/berkshelf/uploader.rb
|
434
432
|
- lib/berkshelf/version.rb
|
435
433
|
- spec/fixtures/Berksfile
|
@@ -456,7 +454,7 @@ files:
|
|
456
454
|
- spec/fixtures/cookbooks/nginx-0.100.5/templates/default/nginx.pill.erb
|
457
455
|
- spec/fixtures/cookbooks/nginx-0.100.5/templates/default/plugins/nginx.rb.erb
|
458
456
|
- spec/fixtures/lockfile_spec/with_lock/Berksfile
|
459
|
-
- spec/fixtures/lockfile_spec/without_lock
|
457
|
+
- spec/fixtures/lockfile_spec/without_lock/.gitkeep
|
460
458
|
- spec/fixtures/reset.pem
|
461
459
|
- spec/knife.rb.sample
|
462
460
|
- spec/spec_helper.rb
|
@@ -467,23 +465,20 @@ files:
|
|
467
465
|
- spec/unit/berkshelf/berksfile_spec.rb
|
468
466
|
- spec/unit/berkshelf/cached_cookbook_spec.rb
|
469
467
|
- spec/unit/berkshelf/cookbook_generator_spec.rb
|
470
|
-
- spec/unit/berkshelf/cookbook_source/chef_api_location_spec.rb
|
471
|
-
- spec/unit/berkshelf/cookbook_source/git_location_spec.rb
|
472
|
-
- spec/unit/berkshelf/cookbook_source/location_spec.rb
|
473
|
-
- spec/unit/berkshelf/cookbook_source/path_location_spec.rb
|
474
|
-
- spec/unit/berkshelf/cookbook_source/site_location_spec.rb
|
475
468
|
- spec/unit/berkshelf/cookbook_source_spec.rb
|
476
469
|
- spec/unit/berkshelf/cookbook_store_spec.rb
|
477
470
|
- spec/unit/berkshelf/core_ext/fileutils_spec.rb
|
478
471
|
- spec/unit/berkshelf/downloader_spec.rb
|
479
|
-
- spec/unit/berkshelf/dsl_spec.rb
|
480
472
|
- spec/unit/berkshelf/formatters_spec.rb
|
481
473
|
- spec/unit/berkshelf/git_spec.rb
|
482
474
|
- spec/unit/berkshelf/init_generator_spec.rb
|
475
|
+
- spec/unit/berkshelf/location_spec.rb
|
476
|
+
- spec/unit/berkshelf/locations/chef_api_location_spec.rb
|
477
|
+
- spec/unit/berkshelf/locations/git_location_spec.rb
|
478
|
+
- spec/unit/berkshelf/locations/path_location_spec.rb
|
479
|
+
- spec/unit/berkshelf/locations/site_location_spec.rb
|
483
480
|
- spec/unit/berkshelf/lockfile_spec.rb
|
484
481
|
- spec/unit/berkshelf/resolver_spec.rb
|
485
|
-
- spec/unit/berkshelf/tx_result_set_spec.rb
|
486
|
-
- spec/unit/berkshelf/tx_result_spec.rb
|
487
482
|
- spec/unit/berkshelf/uploader_spec.rb
|
488
483
|
- spec/unit/berkshelf_spec.rb
|
489
484
|
homepage: https://github.com/RiotGames/berkshelf
|
@@ -501,9 +496,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
501
496
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
502
497
|
none: false
|
503
498
|
requirements:
|
504
|
-
- - ! '
|
499
|
+
- - ! '>='
|
505
500
|
- !ruby/object:Gem::Version
|
506
|
-
version:
|
501
|
+
version: '0'
|
502
|
+
segments:
|
503
|
+
- 0
|
504
|
+
hash: -718551766010983641
|
507
505
|
requirements: []
|
508
506
|
rubyforge_project:
|
509
507
|
rubygems_version: 1.8.23
|
@@ -512,6 +510,7 @@ specification_version: 3
|
|
512
510
|
summary: Manages a Cookbook's, or an Application's, Cookbook dependencies
|
513
511
|
test_files:
|
514
512
|
- features/cookbook_command.feature
|
513
|
+
- features/default_locations.feature
|
515
514
|
- features/init_command.feature
|
516
515
|
- features/install.feature
|
517
516
|
- features/json_formatter.feature
|
@@ -549,7 +548,7 @@ test_files:
|
|
549
548
|
- spec/fixtures/cookbooks/nginx-0.100.5/templates/default/nginx.pill.erb
|
550
549
|
- spec/fixtures/cookbooks/nginx-0.100.5/templates/default/plugins/nginx.rb.erb
|
551
550
|
- spec/fixtures/lockfile_spec/with_lock/Berksfile
|
552
|
-
- spec/fixtures/lockfile_spec/without_lock
|
551
|
+
- spec/fixtures/lockfile_spec/without_lock/.gitkeep
|
553
552
|
- spec/fixtures/reset.pem
|
554
553
|
- spec/knife.rb.sample
|
555
554
|
- spec/spec_helper.rb
|
@@ -560,23 +559,20 @@ test_files:
|
|
560
559
|
- spec/unit/berkshelf/berksfile_spec.rb
|
561
560
|
- spec/unit/berkshelf/cached_cookbook_spec.rb
|
562
561
|
- spec/unit/berkshelf/cookbook_generator_spec.rb
|
563
|
-
- spec/unit/berkshelf/cookbook_source/chef_api_location_spec.rb
|
564
|
-
- spec/unit/berkshelf/cookbook_source/git_location_spec.rb
|
565
|
-
- spec/unit/berkshelf/cookbook_source/location_spec.rb
|
566
|
-
- spec/unit/berkshelf/cookbook_source/path_location_spec.rb
|
567
|
-
- spec/unit/berkshelf/cookbook_source/site_location_spec.rb
|
568
562
|
- spec/unit/berkshelf/cookbook_source_spec.rb
|
569
563
|
- spec/unit/berkshelf/cookbook_store_spec.rb
|
570
564
|
- spec/unit/berkshelf/core_ext/fileutils_spec.rb
|
571
565
|
- spec/unit/berkshelf/downloader_spec.rb
|
572
|
-
- spec/unit/berkshelf/dsl_spec.rb
|
573
566
|
- spec/unit/berkshelf/formatters_spec.rb
|
574
567
|
- spec/unit/berkshelf/git_spec.rb
|
575
568
|
- spec/unit/berkshelf/init_generator_spec.rb
|
569
|
+
- spec/unit/berkshelf/location_spec.rb
|
570
|
+
- spec/unit/berkshelf/locations/chef_api_location_spec.rb
|
571
|
+
- spec/unit/berkshelf/locations/git_location_spec.rb
|
572
|
+
- spec/unit/berkshelf/locations/path_location_spec.rb
|
573
|
+
- spec/unit/berkshelf/locations/site_location_spec.rb
|
576
574
|
- spec/unit/berkshelf/lockfile_spec.rb
|
577
575
|
- spec/unit/berkshelf/resolver_spec.rb
|
578
|
-
- spec/unit/berkshelf/tx_result_set_spec.rb
|
579
|
-
- spec/unit/berkshelf/tx_result_spec.rb
|
580
576
|
- spec/unit/berkshelf/uploader_spec.rb
|
581
577
|
- spec/unit/berkshelf_spec.rb
|
582
578
|
has_rdoc:
|
@@ -1,256 +0,0 @@
|
|
1
|
-
require 'uri'
|
2
|
-
|
3
|
-
module Berkshelf
|
4
|
-
class CookbookSource
|
5
|
-
# @author Jamie Winsor <jamie@vialstudios.com>
|
6
|
-
class ChefAPILocation
|
7
|
-
class << self
|
8
|
-
# @param [String] node_name
|
9
|
-
#
|
10
|
-
# @return [Boolean]
|
11
|
-
def validate_node_name(node_name)
|
12
|
-
node_name.is_a?(String) && !node_name.empty?
|
13
|
-
end
|
14
|
-
|
15
|
-
# @raise [InvalidChefAPILocation]
|
16
|
-
#
|
17
|
-
# @see validate_node_name
|
18
|
-
def validate_node_name!(node_name)
|
19
|
-
unless validate_node_name(node_name)
|
20
|
-
raise InvalidChefAPILocation
|
21
|
-
end
|
22
|
-
|
23
|
-
true
|
24
|
-
end
|
25
|
-
|
26
|
-
# @param [String] client_key
|
27
|
-
#
|
28
|
-
# @return [Boolean]
|
29
|
-
def validate_client_key(client_key)
|
30
|
-
File.exists?(client_key)
|
31
|
-
end
|
32
|
-
|
33
|
-
# @raise [InvalidChefAPILocation]
|
34
|
-
#
|
35
|
-
# @see validate_client_key
|
36
|
-
def validate_client_key!(client_key)
|
37
|
-
unless validate_client_key(client_key)
|
38
|
-
raise InvalidChefAPILocation
|
39
|
-
end
|
40
|
-
|
41
|
-
true
|
42
|
-
end
|
43
|
-
|
44
|
-
# @param [String] uri
|
45
|
-
#
|
46
|
-
# @return [Boolean]
|
47
|
-
def validate_uri(uri)
|
48
|
-
uri =~ URI.regexp(['http', 'https'])
|
49
|
-
end
|
50
|
-
|
51
|
-
# @raise [InvalidChefAPILocation] if the given object is not a String containing a
|
52
|
-
# valid Chef API URI
|
53
|
-
#
|
54
|
-
# @see validate_uri
|
55
|
-
def validate_uri!(uri)
|
56
|
-
unless validate_uri(uri)
|
57
|
-
raise InvalidChefAPILocation, "'#{uri}' is not a valid Chef API URI."
|
58
|
-
end
|
59
|
-
|
60
|
-
true
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
include Location
|
65
|
-
|
66
|
-
location_key :chef_api
|
67
|
-
valid_options :node_name, :client_key
|
68
|
-
|
69
|
-
attr_reader :uri
|
70
|
-
attr_reader :node_name
|
71
|
-
attr_reader :client_key
|
72
|
-
|
73
|
-
# @param [#to_s] name
|
74
|
-
# @param [Solve::Constraint] version_constraint
|
75
|
-
# @param [Hash] options
|
76
|
-
#
|
77
|
-
# @option options [String, Symbol] :chef_api
|
78
|
-
# a URL to a Chef API. Alternatively the symbol :knife can be provided
|
79
|
-
# which will instantiate this location with the values found in your
|
80
|
-
# knife configuration.
|
81
|
-
# @option options [String] :node_name
|
82
|
-
# the name of the client to use to communicate with the Chef API.
|
83
|
-
# Default: Chef::Config[:node_name]
|
84
|
-
# @option options [String] :client_key
|
85
|
-
# the filepath to the authentication key for the client
|
86
|
-
# Default: Chef::Config[:client_key]
|
87
|
-
def initialize(name, version_constraint, options = {})
|
88
|
-
@name = name
|
89
|
-
@version_constraint = version_constraint
|
90
|
-
@downloaded_status = false
|
91
|
-
|
92
|
-
validate_options!(options)
|
93
|
-
|
94
|
-
if options[:chef_api] == :knife
|
95
|
-
begin
|
96
|
-
Berkshelf.load_config
|
97
|
-
rescue KnifeConfigNotFound => e
|
98
|
-
raise KnifeConfigNotFound, "A Knife config is required when ':knife' is given for the value of a 'chef_api' location. #{e}"
|
99
|
-
end
|
100
|
-
@node_name = Chef::Config[:node_name]
|
101
|
-
@client_key = Chef::Config[:client_key]
|
102
|
-
@uri = Chef::Config[:chef_server_url]
|
103
|
-
else
|
104
|
-
@node_name = options[:node_name]
|
105
|
-
@client_key = options[:client_key]
|
106
|
-
@uri = options[:chef_api]
|
107
|
-
end
|
108
|
-
|
109
|
-
@rest = Chef::REST.new(uri, node_name, client_key)
|
110
|
-
end
|
111
|
-
|
112
|
-
# @param [#to_s] destination
|
113
|
-
#
|
114
|
-
# @return [Berkshelf::CachedCookbook]
|
115
|
-
def download(destination)
|
116
|
-
version, uri = target_version
|
117
|
-
cookbook = rest.get_rest(uri)
|
118
|
-
|
119
|
-
scratch = download_files(cookbook.manifest)
|
120
|
-
|
121
|
-
cb_path = File.join(destination, "#{name}-#{version}")
|
122
|
-
FileUtils.mv(scratch, cb_path, force: true)
|
123
|
-
|
124
|
-
cached = CachedCookbook.from_store_path(cb_path)
|
125
|
-
validate_cached(cached)
|
126
|
-
|
127
|
-
set_downloaded_status(true)
|
128
|
-
cached
|
129
|
-
end
|
130
|
-
|
131
|
-
# Returns a hash representing the cookbook versions on at a Chef API for location's cookbook.
|
132
|
-
# The keys are version strings and the values are URLs to download the cookbook version.
|
133
|
-
#
|
134
|
-
# @example
|
135
|
-
# {
|
136
|
-
# "0.101.2" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.2",
|
137
|
-
# "0.101.5" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.5"
|
138
|
-
# }
|
139
|
-
#
|
140
|
-
# @return [Hash]
|
141
|
-
def versions
|
142
|
-
{}.tap do |versions|
|
143
|
-
rest.get_rest("cookbooks/#{name}").each do |name, data|
|
144
|
-
data["versions"].each do |version_info|
|
145
|
-
versions[version_info["version"]] = version_info["url"]
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
rescue Net::HTTPServerException => e
|
150
|
-
if e.response.code == "404"
|
151
|
-
raise CookbookNotFound, "Cookbook '#{name}' not found at chef_api: '#{uri}'"
|
152
|
-
else
|
153
|
-
raise
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# Returns an array where the first element is a string representing the latest version of
|
158
|
-
# the Cookbook and the second element is the download URL for that version.
|
159
|
-
#
|
160
|
-
# @example
|
161
|
-
# [ "0.101.2" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.2" ]
|
162
|
-
#
|
163
|
-
# @return [Array]
|
164
|
-
def latest_version
|
165
|
-
graph = Solve::Graph.new
|
166
|
-
versions.each do |version, url|
|
167
|
-
graph.artifacts(name, version)
|
168
|
-
end
|
169
|
-
graph.demands(name, ">= 0.0.0")
|
170
|
-
|
171
|
-
version = Solve.it!(graph)[name]
|
172
|
-
|
173
|
-
[ version, versions[version] ]
|
174
|
-
end
|
175
|
-
|
176
|
-
def to_s
|
177
|
-
"chef_api: '#{uri}'"
|
178
|
-
end
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
attr_reader :rest
|
183
|
-
|
184
|
-
# Returns an array containing the version and download URL for the cookbook version that
|
185
|
-
# should be downloaded for this location.
|
186
|
-
#
|
187
|
-
# @example
|
188
|
-
# [ "0.101.2" => "https://api.opscode.com/organizations/vialstudios/cookbooks/nginx/0.101.2" ]
|
189
|
-
#
|
190
|
-
# @return [Array]
|
191
|
-
def target_version
|
192
|
-
if version_constraint
|
193
|
-
solution = self.class.solve_for_constraint(version_constraint, versions)
|
194
|
-
|
195
|
-
unless solution
|
196
|
-
raise NoSolution, "No cookbook version of '#{name}' found at #{self} that would satisfy constraint (#{version_constraint})."
|
197
|
-
end
|
198
|
-
|
199
|
-
solution
|
200
|
-
else
|
201
|
-
latest_version
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
# Download all of the files in the given manifest to the given destination. If no destination
|
206
|
-
# is provided a temporary directory will be created and the files will be downloaded to there.
|
207
|
-
#
|
208
|
-
# @note
|
209
|
-
# the manifest Hash is the same manifest that you get by sending the manifest message to
|
210
|
-
# an instance of Chef::CookbookVersion.
|
211
|
-
#
|
212
|
-
# @param [Hash] manifest
|
213
|
-
# @param [String] destination
|
214
|
-
#
|
215
|
-
# @return [String]
|
216
|
-
# the path to the directory containing the files
|
217
|
-
def download_files(manifest, destination = Dir.mktmpdir)
|
218
|
-
Chef::CookbookVersion::COOKBOOK_SEGMENTS.each do |segment|
|
219
|
-
next unless manifest.has_key?(segment)
|
220
|
-
manifest[segment].each do |segment_file|
|
221
|
-
dest = File.join(destination, segment_file['path'].gsub('/', File::SEPARATOR))
|
222
|
-
FileUtils.mkdir_p(File.dirname(dest))
|
223
|
-
rest.sign_on_redirect = false
|
224
|
-
tempfile = rest.get_rest(segment_file['url'], true)
|
225
|
-
FileUtils.mv(tempfile.path, dest)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
destination
|
230
|
-
end
|
231
|
-
|
232
|
-
# Validates the options hash given to the constructor.
|
233
|
-
#
|
234
|
-
# @param [Hash] options
|
235
|
-
#
|
236
|
-
# @raise [InvalidChefAPILocation] if any of the options are missing or their values do not
|
237
|
-
# pass validation
|
238
|
-
def validate_options!(options)
|
239
|
-
if options[:chef_api] == :knife
|
240
|
-
return true
|
241
|
-
end
|
242
|
-
|
243
|
-
missing_options = [:node_name, :client_key] - options.keys
|
244
|
-
|
245
|
-
unless missing_options.empty?
|
246
|
-
missing_options.collect! { |opt| "'#{opt}'" }
|
247
|
-
raise InvalidChefAPILocation, "Source '#{name}' is a 'chef_api' location with a URL for it's value but is missing options: #{missing_options.join(', ')}."
|
248
|
-
end
|
249
|
-
|
250
|
-
self.class.validate_node_name!(options[:node_name])
|
251
|
-
self.class.validate_client_key!(options[:client_key])
|
252
|
-
self.class.validate_uri!(options[:chef_api])
|
253
|
-
end
|
254
|
-
end
|
255
|
-
end
|
256
|
-
end
|