berkshelf 2.0.18 → 3.0.0.beta1

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 (128) hide show
  1. data/.ruby-version +1 -1
  2. data/.travis.yml +4 -1
  3. data/CHANGELOG.md +2 -26
  4. data/Gemfile +12 -2
  5. data/README.md +9 -1
  6. data/berkshelf.gemspec +9 -18
  7. data/bin/berks +3 -13
  8. data/features/apply_command.feature +11 -9
  9. data/features/berksfile.feature +8 -10
  10. data/features/config.feature +1 -2
  11. data/features/configure_command.feature +13 -14
  12. data/features/contingent_command.feature +13 -1
  13. data/features/cookbook_command.feature +2 -4
  14. data/features/groups_install.feature +10 -2
  15. data/features/help.feature +1 -1
  16. data/features/init_command.feature +5 -7
  17. data/features/install_command.feature +157 -228
  18. data/features/json_formatter.feature +27 -15
  19. data/features/licenses.feature +18 -12
  20. data/features/list_command.feature +6 -1
  21. data/features/lockfile.feature +116 -72
  22. data/features/outdated_command.feature +3 -47
  23. data/features/package_command.feature +10 -7
  24. data/features/shelf/show.feature +2 -2
  25. data/features/shelf/uninstall.feature +2 -2
  26. data/features/show_command.feature +10 -3
  27. data/features/step_definitions/chef/config_steps.rb +12 -0
  28. data/features/step_definitions/chef_server_steps.rb +16 -16
  29. data/features/step_definitions/cli_steps.rb +3 -79
  30. data/features/step_definitions/config_steps.rb +43 -0
  31. data/features/step_definitions/environment_steps.rb +7 -0
  32. data/features/step_definitions/filesystem_steps.rb +12 -57
  33. data/features/step_definitions/gem_steps.rb +1 -2
  34. data/features/step_definitions/json_steps.rb +3 -1
  35. data/features/step_definitions/lockfile_steps.rb +4 -0
  36. data/features/step_definitions/utility_steps.rb +0 -19
  37. data/features/support/aruba.rb +12 -0
  38. data/features/support/env.rb +52 -57
  39. data/features/update_command.feature +37 -23
  40. data/features/upload_command.feature +96 -160
  41. data/generator_files/Berksfile.erb +2 -1
  42. data/generator_files/Vagrantfile.erb +3 -0
  43. data/generator_files/default_test.rb.erb +1 -1
  44. data/generator_files/helpers.rb.erb +1 -1
  45. data/lib/berkshelf.rb +43 -24
  46. data/lib/berkshelf/api_client.rb +67 -0
  47. data/lib/berkshelf/api_client/remote_cookbook.rb +42 -0
  48. data/lib/berkshelf/berksfile.rb +232 -420
  49. data/lib/berkshelf/cached_cookbook.rb +22 -10
  50. data/lib/berkshelf/chef/config.rb +1 -0
  51. data/lib/berkshelf/cli.rb +66 -68
  52. data/lib/berkshelf/commands/shelf.rb +1 -1
  53. data/lib/berkshelf/community_rest.rb +10 -17
  54. data/lib/berkshelf/config.rb +23 -27
  55. data/lib/berkshelf/cookbook_generator.rb +3 -4
  56. data/lib/berkshelf/cookbook_store.rb +74 -17
  57. data/lib/berkshelf/core_ext/file.rb +2 -2
  58. data/lib/berkshelf/core_ext/pathname.rb +7 -5
  59. data/lib/berkshelf/{cookbook_source.rb → dependency.rb} +47 -67
  60. data/lib/berkshelf/downloader.rb +49 -106
  61. data/lib/berkshelf/errors.rb +64 -71
  62. data/lib/berkshelf/formatters.rb +11 -9
  63. data/lib/berkshelf/formatters/human_readable.rb +9 -9
  64. data/lib/berkshelf/formatters/json.rb +14 -4
  65. data/lib/berkshelf/init_generator.rb +3 -3
  66. data/lib/berkshelf/installer.rb +136 -0
  67. data/lib/berkshelf/location.rb +91 -131
  68. data/lib/berkshelf/locations/git_location.rb +9 -11
  69. data/lib/berkshelf/locations/github_location.rb +1 -1
  70. data/lib/berkshelf/locations/path_location.rb +10 -27
  71. data/lib/berkshelf/lockfile.rb +92 -70
  72. data/lib/berkshelf/logger.rb +4 -7
  73. data/lib/berkshelf/mixin/config.rb +21 -4
  74. data/lib/berkshelf/resolver.rb +60 -150
  75. data/lib/berkshelf/resolver/graph.rb +44 -0
  76. data/lib/berkshelf/source.rb +55 -0
  77. data/lib/berkshelf/source_uri.rb +38 -0
  78. data/lib/berkshelf/version.rb +1 -1
  79. data/spec/config/knife.rb +1 -1
  80. data/spec/fixtures/cassettes/Berkshelf_Resolver/_initialize/adds_the_dependencies_of_the_dependency_as_dependencies.yml +3694 -0
  81. data/spec/fixtures/cookbooks/example_cookbook/Berksfile.lock +1 -1
  82. data/spec/fixtures/lockfiles/default.lock +1 -1
  83. data/spec/spec_helper.rb +20 -121
  84. data/spec/support/chef_api.rb +3 -4
  85. data/spec/support/chef_server.rb +20 -11
  86. data/spec/support/git.rb +127 -0
  87. data/spec/support/kitchen.rb +12 -0
  88. data/spec/support/path_helpers.rb +69 -0
  89. data/spec/unit/berkshelf/api_client/remote_cookbook_spec.rb +23 -0
  90. data/spec/unit/berkshelf/api_client_spec.rb +57 -0
  91. data/spec/unit/berkshelf/berksfile_spec.rb +206 -324
  92. data/spec/unit/berkshelf/cached_cookbook_spec.rb +73 -38
  93. data/spec/unit/berkshelf/community_rest_spec.rb +30 -71
  94. data/spec/unit/berkshelf/config_spec.rb +3 -14
  95. data/spec/unit/berkshelf/cookbook_generator_spec.rb +1 -2
  96. data/spec/unit/berkshelf/cookbook_store_spec.rb +12 -7
  97. data/spec/unit/berkshelf/dependency_spec.rb +285 -0
  98. data/spec/unit/berkshelf/downloader_spec.rb +4 -183
  99. data/spec/unit/berkshelf/formatters/null_spec.rb +1 -1
  100. data/spec/unit/berkshelf/formatters_spec.rb +4 -2
  101. data/spec/unit/berkshelf/git_spec.rb +15 -15
  102. data/spec/unit/berkshelf/installer_spec.rb +39 -0
  103. data/spec/unit/berkshelf/location_spec.rb +87 -114
  104. data/spec/unit/berkshelf/locations/git_location_spec.rb +41 -53
  105. data/spec/unit/berkshelf/locations/path_location_spec.rb +13 -23
  106. data/spec/unit/berkshelf/lockfile_spec.rb +38 -40
  107. data/spec/unit/berkshelf/resolver/graph_spec.rb +44 -0
  108. data/spec/unit/berkshelf/resolver_spec.rb +34 -83
  109. data/spec/unit/berkshelf/source_spec.rb +23 -0
  110. data/spec/unit/berkshelf/source_uri_spec.rb +29 -0
  111. metadata +149 -188
  112. checksums.yaml +0 -7
  113. data/features/default_locations.feature +0 -127
  114. data/features/step_definitions/berksfile_steps.rb +0 -8
  115. data/features/step_definitions/configure_cli_steps.rb +0 -19
  116. data/features/vendor_install.feature +0 -19
  117. data/lib/berkshelf/core_ext/openuri.rb +0 -36
  118. data/lib/berkshelf/core_ext/rbzip2.rb +0 -8
  119. data/lib/berkshelf/locations/chef_api_location.rb +0 -228
  120. data/lib/berkshelf/locations/site_location.rb +0 -92
  121. data/lib/berkshelf/test.rb +0 -35
  122. data/spec/knife.rb.sample +0 -12
  123. data/spec/support/test_generators.rb +0 -27
  124. data/spec/unit/berkshelf/cli_spec.rb +0 -16
  125. data/spec/unit/berkshelf/cookbook_source_spec.rb +0 -358
  126. data/spec/unit/berkshelf/core_ext/pathname_spec.rb +0 -46
  127. data/spec/unit/berkshelf/locations/chef_api_location_spec.rb +0 -139
  128. data/spec/unit/berkshelf/locations/site_location_spec.rb +0 -19
@@ -1,70 +1,63 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::CachedCookbook do
4
- describe '.from_store_path' do
5
- let(:path) { fixtures_path.join('cookbooks', 'example_cookbook-0.5.0') }
6
- let(:cached) { Berkshelf::CachedCookbook.from_path(path) }
4
+ describe "ClassMethods" do
5
+ describe '::from_store_path' do
6
+ let(:path) { fixtures_path.join('cookbooks', 'example_cookbook-0.5.0') }
7
+ let(:cached) { described_class.from_path(path) }
7
8
 
8
- it 'returns a CachedCookbook' do
9
- expect(cached).to be_a(Berkshelf::CachedCookbook)
10
- end
11
-
12
- it 'sets a version number' do
13
- expect(cached.version).to eq('0.5.0')
14
- end
15
-
16
- it 'sets the metadata.name value to the cookbook_name' do
17
- expect(cached.metadata.name).to eq('example_cookbook')
18
- end
9
+ it 'returns a CachedCookbook' do
10
+ expect(cached).to be_a(described_class)
11
+ end
19
12
 
20
- context 'given a path that does not contain a cookbook' do
21
- it 'returns nil' do
22
- expect(Berkshelf::CachedCookbook.from_store_path(tmp_path)).to be_nil
13
+ it 'sets a version number' do
14
+ expect(cached.version).to eq('0.5.0')
23
15
  end
24
- end
25
16
 
26
- context 'given a path that does not match the CachedCookbook dirname format' do
27
- it 'returns nil' do
28
- path = fixtures_path.join('cookbooks', 'example_cookbook')
29
- expect(Berkshelf::CachedCookbook.from_store_path(path)).to be_nil
17
+ it 'sets the metadata.name value to the cookbook_name' do
18
+ expect(cached.metadata.name).to eq('example_cookbook')
30
19
  end
31
20
 
32
- context 'given an already cached cookbook' do
33
- let!(:cached) { described_class.from_store_path(path) }
21
+ context 'given a path that does not contain a cookbook' do
22
+ it 'returns nil' do
23
+ expect(described_class.from_store_path(tmp_path)).to be_nil
24
+ end
25
+ end
34
26
 
35
- it 'returns the cached cookbook instance' do
36
- expect(described_class.from_store_path(path)).to eq(cached)
27
+ context 'given a path that does not match the CachedCookbook dirname format' do
28
+ it 'returns nil' do
29
+ path = fixtures_path.join('cookbooks', 'example_cookbook')
30
+ expect(described_class.from_store_path(path)).to be_nil
37
31
  end
38
32
  end
39
33
  end
40
34
 
41
- describe '#checksum' do
35
+ describe '::checksum' do
42
36
  it 'returns a checksum of the given filepath' do
43
37
  path = fixtures_path.join('cookbooks', 'example_cookbook-0.5.0', 'README.md')
44
- expect(Berkshelf::CachedCookbook.checksum(path)).to eq('6e21094b7a920e374e7261f50e9c4eef')
38
+ expect(described_class.checksum(path)).to eq('6e21094b7a920e374e7261f50e9c4eef')
45
39
  end
46
40
 
47
41
  context 'given path does not exist' do
48
42
  it 'raises an Errno::ENOENT error' do
49
43
  expect {
50
- Berkshelf::CachedCookbook.checksum(fixtures_path.join('notexisting.file'))
44
+ described_class.checksum(fixtures_path.join('notexisting.file'))
51
45
  }.to raise_error(Errno::ENOENT)
52
46
  end
53
47
  end
54
48
  end
55
49
  end
56
50
 
51
+ let(:dependencies) { { 'mysql' => '= 1.2.0', 'ntp' => '>= 0.0.0' } }
52
+ let(:recommendations) { { 'database' => '>= 0.0.0' } }
53
+ let(:path) do
54
+ generate_cookbook(Berkshelf.cookbook_store.storage_path,
55
+ 'sparkle', '0.1.0', dependencies: dependencies, recommendations: recommendations)
56
+ end
57
57
 
58
- describe '#dependencies' do
59
- let(:dependencies) { { 'mysql' => '= 1.2.0', 'ntp' => '>= 0.0.0' } }
60
- let(:recommendations) { { 'database' => '>= 0.0.0' } }
61
-
62
- let(:path) do
63
- generate_cookbook(Berkshelf.cookbook_store.storage_path, 'sparkle', '0.1.0', dependencies: dependencies, recommendations: recommendations)
64
- end
65
-
66
- subject { Berkshelf::CachedCookbook.from_store_path(path) }
58
+ subject { Berkshelf::CachedCookbook.from_store_path(path) }
67
59
 
60
+ describe '#dependencies' do
68
61
  it 'contains depends from the cookbook metadata' do
69
62
  expect(subject.dependencies).to include(dependencies)
70
63
  end
@@ -72,5 +65,47 @@ describe Berkshelf::CachedCookbook do
72
65
  it 'contains recommendations from the cookbook metadata' do
73
66
  expect(subject.dependencies).to include(recommendations)
74
67
  end
68
+
69
+ it 'returns a hash' do
70
+ expect(subject.dependencies).to be_a(Hash)
71
+ end
72
+ end
73
+
74
+ describe '#pretty_hash' do
75
+ shared_examples 'a pretty_hash cookbook attribute' do |attribute, key|
76
+ it "is not present when the `#{attribute}` attribute is nil" do
77
+ subject.stub(attribute.to_sym).and_return(nil)
78
+ expect(subject.pretty_hash).to_not have_key((key || attribute).to_sym)
79
+ end
80
+
81
+ it "is not present when the `#{attribute}` attribute is an empty string" do
82
+ subject.stub(attribute.to_sym).and_return('')
83
+ expect(subject.pretty_hash).to_not have_key((key || attribute).to_sym)
84
+ end
85
+
86
+ it "is not present when the `#{attribute}` attribute is an empty array" do
87
+ subject.stub(attribute.to_sym).and_return([])
88
+ expect(subject.pretty_hash).to_not have_key((key || attribute).to_sym)
89
+ end
90
+
91
+ it "is not present when the `#{attribute}` attribute is an empty hash" do
92
+ subject.stub(attribute.to_sym).and_return([])
93
+ expect(subject.pretty_hash).to_not have_key((key || attribute).to_sym)
94
+ end
95
+
96
+ it "is present when the `#{attribute}` attribute has a Hash value" do
97
+ subject.stub(attribute.to_sym).and_return(foo: 'bar')
98
+ expect(subject.pretty_hash).to have_key((key || attribute).to_sym)
99
+ end
100
+ end
101
+
102
+ it_behaves_like 'a pretty_hash cookbook attribute', 'cookbook_name', 'name'
103
+ it_behaves_like 'a pretty_hash cookbook attribute', 'version'
104
+ it_behaves_like 'a pretty_hash cookbook attribute', 'description'
105
+ it_behaves_like 'a pretty_hash cookbook attribute', 'maintainer', 'author'
106
+ it_behaves_like 'a pretty_hash cookbook attribute', 'maintainer_email', 'email'
107
+ it_behaves_like 'a pretty_hash cookbook attribute', 'license'
108
+ it_behaves_like 'a pretty_hash cookbook attribute', 'platforms'
109
+ it_behaves_like 'a pretty_hash cookbook attribute', 'dependencies'
75
110
  end
76
111
  end
@@ -1,12 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::CommunityREST, vcr: { record: :new_episodes, serialize_with: :json } do
4
- describe '.unpack' do
5
- let(:target) { '/foo/bar' }
6
- let(:destination) { '/destination/bar' }
7
- let(:file) { double('file') }
8
-
9
- describe 'a tar.gz file' do
4
+ describe "ClassMethods" do
5
+ describe "::unpack" do
6
+ let(:target) { '/foo/bar' }
7
+ let(:destination) { '/destination/bar' }
8
+ let(:file) { double('file') }
10
9
  let(:gzip_reader) { double('gzip_reader') }
11
10
 
12
11
  before do
@@ -15,7 +14,7 @@ describe Berkshelf::CommunityREST, vcr: { record: :new_episodes, serialize_with:
15
14
  Archive::Tar::Minitar.stub(:unpack).with(gzip_reader, destination)
16
15
  end
17
16
 
18
- it 'unpacks the file' do
17
+ it 'unpacks the tar' do
19
18
  File.should_receive(:open).with(target, 'rb')
20
19
  ::IO.should_receive(:binread).with(target, 2).and_return([0x1F, 0x8B].pack("C*"))
21
20
  Zlib::GzipReader.should_receive(:new).with(file)
@@ -25,85 +24,45 @@ describe Berkshelf::CommunityREST, vcr: { record: :new_episodes, serialize_with:
25
24
  end
26
25
  end
27
26
 
28
- describe 'a tar file' do
29
- before do
30
- File.stub(:open).with(target, 'rb').and_return(file)
31
- Archive::Tar::Minitar.stub(:unpack).with(target, destination)
27
+ describe "::uri_escape_version" do
28
+ it 'returns a string' do
29
+ expect(Berkshelf::CommunityREST.uri_escape_version(nil)).to be_a(String)
32
30
  end
33
31
 
34
- it 'unpacks the file' do
35
- ::IO.should_receive(:binread).once
36
- ::IO.should_receive(:binread).with(target, 8, 257).and_return("ustar\x0000")
37
- Archive::Tar::Minitar.should_receive(:unpack).with(target, destination)
38
-
39
- expect(Berkshelf::CommunityREST.unpack(target, destination)).to eq(destination)
32
+ it 'converts a version to it\'s underscored version' do
33
+ expect(Berkshelf::CommunityREST.uri_escape_version('1.1.2')).to eq('1_1_2')
40
34
  end
41
- end
42
-
43
- describe 'a tar.bz2 file' do
44
- let(:bzip2_reader) { double('bzip2_reader') }
45
35
 
46
- before do
47
- File.stub(:open).with(target, 'rb').and_return(file)
48
- RBzip2::Decompressor.stub(:new).with(file).and_return(bzip2_reader)
49
- Archive::Tar::Minitar.stub(:unpack).with(bzip2_reader, destination)
36
+ it 'works when the version has more than three points' do
37
+ expect(Berkshelf::CommunityREST.uri_escape_version('1.1.1.2')).to eq('1_1_1_2')
50
38
  end
51
39
 
52
- it 'unpacks the file' do
53
- File.should_receive(:open).with(target, 'rb')
54
- ::IO.should_receive(:binread).twice
55
- ::IO.should_receive(:binread).with(target, 3).and_return('BZh')
56
- RBzip2::Decompressor.should_receive(:new).with(file)
57
- Archive::Tar::Minitar.should_receive(:unpack).with(bzip2_reader, destination)
58
-
59
- expect(Berkshelf::CommunityREST.unpack(target, destination)).to eq(destination)
40
+ it 'works when the version has less than three points' do
41
+ expect(Berkshelf::CommunityREST.uri_escape_version('1.2')).to eq('1_2')
60
42
  end
61
43
  end
62
- end
63
-
64
- describe '.uri_escape_version' do
65
- it 'returns a string' do
66
- expect(Berkshelf::CommunityREST.uri_escape_version(nil)).to be_a(String)
67
- end
68
-
69
- it 'converts a version to it\'s underscored version' do
70
- expect(Berkshelf::CommunityREST.uri_escape_version('1.1.2')).to eq('1_1_2')
71
- end
72
44
 
73
- it 'works when the version has more than three points' do
74
- expect(Berkshelf::CommunityREST.uri_escape_version('1.1.1.2')).to eq('1_1_1_2')
75
- end
76
-
77
- it 'works when the version has less than three points' do
78
- expect(Berkshelf::CommunityREST.uri_escape_version('1.2')).to eq('1_2')
79
- end
80
- end
81
-
82
- describe '.version_from_uri' do
83
- it 'returns a string' do
84
- expect(Berkshelf::CommunityREST.version_from_uri(nil)).to be_a(String)
85
- end
45
+ describe "::version_from_uri" do
46
+ it 'returns a string' do
47
+ expect(Berkshelf::CommunityREST.version_from_uri(nil)).to be_a(String)
48
+ end
86
49
 
87
- it 'extracts the version from the URL' do
88
- expect(Berkshelf::CommunityREST.version_from_uri('/api/v1/cookbooks/nginx/versions/1_1_2')).to eq('1.1.2')
89
- end
50
+ it 'extracts the version from the URL' do
51
+ expect(Berkshelf::CommunityREST.version_from_uri('/api/v1/cookbooks/nginx/versions/1_1_2')).to eq('1.1.2')
52
+ end
90
53
 
91
- it 'works when the version has more than three points' do
92
- expect(Berkshelf::CommunityREST.version_from_uri('/api/v1/cookbooks/nginx/versions/1_1_1_2')).to eq('1.1.1.2')
93
- end
54
+ it 'works when the version has more than three points' do
55
+ expect(Berkshelf::CommunityREST.version_from_uri('/api/v1/cookbooks/nginx/versions/1_1_1_2')).to eq('1.1.1.2')
56
+ end
94
57
 
95
- it 'works when the version has less than three points' do
96
- expect(Berkshelf::CommunityREST.version_from_uri('/api/v1/cookbooks/nginx/versions/1_2')).to eq('1.2')
58
+ it 'works when the version has less than three points' do
59
+ expect(Berkshelf::CommunityREST.version_from_uri('/api/v1/cookbooks/nginx/versions/1_2')).to eq('1.2')
60
+ end
97
61
  end
98
62
  end
99
63
 
100
-
101
-
102
64
  let(:api_uri) { Berkshelf::CommunityREST::V1_API }
103
-
104
- subject do
105
- Berkshelf::CommunityREST.new(api_uri)
106
- end
65
+ subject { Berkshelf::CommunityREST.new(api_uri) }
107
66
 
108
67
  describe '#download' do
109
68
  let(:archive) { double('archive', path: '/foo/bar', unlink: true) }
@@ -114,7 +73,7 @@ describe Berkshelf::CommunityREST, vcr: { record: :new_episodes, serialize_with:
114
73
  end
115
74
 
116
75
  it 'unpacks the archive' do
117
- Berkshelf::CommunityREST.should_receive(:unpack).with('/foo/bar').once
76
+ Berkshelf::CommunityREST.should_receive(:unpack).with('/foo/bar').once.and_return('/foo/nginx')
118
77
  archive.should_receive(:unlink).once
119
78
 
120
79
  subject.download('nginx', '1.4.0')
@@ -30,21 +30,10 @@ describe Berkshelf::Config do
30
30
  Berkshelf::Config.instance_variable_set(:@path, nil)
31
31
  end
32
32
 
33
- Berkshelf::Config::LOCATIONS.each do |location|
34
- context "with '#{location}' as the config file" do
35
- let(:path) { File.expand_path(location) }
36
- before { File.stub(:exists?).with(path).and_return(true) }
37
-
38
- it "returns '#{location}' as the path" do
39
- expect(Berkshelf::Config.path).to eq(path)
40
- end
41
- end
42
- end
43
-
44
- context "when ENV['BERKSHELF_PATH'] is used" do
33
+ context "when ENV['BERKSHELF_CONFIG'] is used" do
45
34
  before do
46
- ENV.stub(:[]).with('BERKSHELF_PATH').and_return('/tmp')
47
- File.stub(:exists?).with('/tmp').and_return(true)
35
+ ENV.stub(:[]).with('BERKSHELF_CONFIG').and_return('/tmp/config.json')
36
+ File.stub(:exists?).with('/tmp/config.json').and_return(true)
48
37
  end
49
38
 
50
39
  it "points to a location within it" do
@@ -17,7 +17,6 @@ describe Berkshelf::CookbookGenerator do
17
17
  specify do
18
18
  expect(target).to have_structure {
19
19
  directory 'attributes'
20
- directory 'definitions'
21
20
  directory 'files' do
22
21
  directory 'default'
23
22
  end
@@ -51,7 +50,7 @@ describe Berkshelf::CookbookGenerator do
51
50
  contains "description 'Installs/Configures sparkle_motion'"
52
51
  end
53
52
  file 'Berksfile' do
54
- contains 'site :opscode'
53
+ contains 'source "http://api.berkshelf.com"'
55
54
  contains 'metadata'
56
55
  end
57
56
  file 'Gemfile'
@@ -1,17 +1,20 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::CookbookStore do
4
- describe '#initialize' do
5
- it 'creates the storage_path' do
6
- storage_path = tmp_path.join('random_storage')
7
- Berkshelf::CookbookStore.new(storage_path)
4
+ describe "ClassMethods" do
5
+ describe "::instance"
6
+ describe "::import"
8
7
 
9
- expect(storage_path).to exist
8
+ describe "::new" do
9
+ it 'creates the storage_path' do
10
+ storage_path = tmp_path.join('random_storage')
11
+ Berkshelf::CookbookStore.new(storage_path)
12
+
13
+ expect(storage_path).to exist
14
+ end
10
15
  end
11
16
  end
12
17
 
13
-
14
-
15
18
  subject { Berkshelf::CookbookStore.new(tmp_path.join("cbstore_rspec")) }
16
19
 
17
20
  describe '#cookbook_path' do
@@ -104,4 +107,6 @@ describe Berkshelf::CookbookStore do
104
107
  end
105
108
  end
106
109
  end
110
+
111
+ describe "#import"
107
112
  end
@@ -0,0 +1,285 @@
1
+ require 'spec_helper'
2
+
3
+ describe Berkshelf::Dependency do
4
+ let(:cookbook_name) { 'nginx' }
5
+ let(:berksfile) { double('berksfile', filepath: fixtures_path.join('Berksfile').to_s) }
6
+
7
+ describe "ClassMethods" do
8
+ describe "::new" do
9
+ let(:source) { described_class.new(berksfile, cookbook_name) }
10
+
11
+ context 'given no location key (i.e. :git, :path, :site)' do
12
+ it 'sets a nil valie for location' do
13
+ expect(source.location).to be_nil
14
+ end
15
+ end
16
+
17
+ context 'given no value for :locked_version' do
18
+ it 'returns a wildcard match for any version' do
19
+ expect(source.locked_version).to be_nil
20
+ end
21
+ end
22
+
23
+ context 'given no value for :constraint' do
24
+ it 'returns a wildcard match for any version' do
25
+ expect(source.version_constraint.to_s).to eq('>= 0.0.0')
26
+ end
27
+ end
28
+
29
+ context 'given a value for :constraint' do
30
+ let(:source) { described_class.new(berksfile, cookbook_name, constraint: '~> 1.0.84') }
31
+
32
+ it 'returns a Solve::Constraint for the given version for version_constraint' do
33
+ expect(source.version_constraint.to_s).to eq('~> 1.0.84')
34
+ end
35
+ end
36
+
37
+ context 'given a location key :git' do
38
+ let(:url) { 'git://url_to_git' }
39
+ let(:source) { described_class.new(berksfile, cookbook_name, git: url) }
40
+
41
+ it 'initializes a GitLocation for location' do
42
+ expect(source.location).to be_a(Berkshelf::GitLocation)
43
+ end
44
+
45
+ it 'points to the given Git URL' do
46
+ expect(source.location.uri).to eq(url)
47
+ end
48
+ end
49
+
50
+ context 'given a location key :path' do
51
+ context 'given a value for path that contains a cookbook' do
52
+ let(:path) { fixtures_path.join('cookbooks', 'example_cookbook').to_s }
53
+ let(:location) { described_class.new(berksfile, cookbook_name, path: path).location }
54
+
55
+ it 'initializes a PathLocation for location' do
56
+ expect(location).to be_a(Berkshelf::PathLocation)
57
+ end
58
+
59
+ it 'points to the specified path' do
60
+ expect(location.path).to eq(path)
61
+ end
62
+ end
63
+
64
+ context 'given an invalid option' do
65
+ it 'raises BerkshelfError with a friendly message' do
66
+ expect {
67
+ described_class.new(berksfile, cookbook_name, invalid_opt: 'thisisnotvalid')
68
+ }.to raise_error(Berkshelf::BerkshelfError, "Invalid options for dependency: 'invalid_opt'.")
69
+ end
70
+
71
+ it 'raises BerkshelfError with a messaging containing all of the invalid options' do
72
+ expect {
73
+ described_class.new(berksfile, cookbook_name, invalid_one: 'one', invalid_two: 'two')
74
+ }.to raise_error(Berkshelf::BerkshelfError, "Invalid options for dependency: 'invalid_one', 'invalid_two'.")
75
+ end
76
+ end
77
+
78
+ context 'given multiple location options' do
79
+ it 'raises with an Berkshelf::BerkshelfError' do
80
+ expect {
81
+ described_class.new(berksfile, cookbook_name, path: '/something', git: 'something')
82
+ }.to raise_error(Berkshelf::BerkshelfError)
83
+ end
84
+ end
85
+
86
+ context 'given a group option containing a single group' do
87
+ let(:group) { :production }
88
+ let(:source) { described_class.new(berksfile, cookbook_name, group: group) }
89
+
90
+ it 'assigns the single group to the groups attribute' do
91
+ expect(source.groups).to include(group)
92
+ end
93
+ end
94
+
95
+ context 'given a group option containing an array of groups' do
96
+ let(:groups) { [ :development, :test ] }
97
+ let(:source) { described_class.new(berksfile, cookbook_name, group: groups) }
98
+
99
+ it 'assigns all the groups to the group attribute' do
100
+ expect(source.groups).to eq(groups)
101
+ end
102
+ end
103
+
104
+ context 'given no group option' do
105
+ let(:source) { described_class.new(berksfile, cookbook_name) }
106
+
107
+ it 'has the default group assigned' do
108
+ expect(source.groups).to include(:default)
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ describe "::add_valid_option" do
115
+ before do
116
+ @original = described_class.class_variable_get :@@valid_options
117
+ described_class.class_variable_set :@@valid_options, []
118
+ end
119
+
120
+ after do
121
+ described_class.class_variable_set :@@valid_options, @original
122
+ end
123
+
124
+ it 'adds an option to the list of valid options' do
125
+ described_class.add_valid_option(:one)
126
+
127
+ expect(described_class.valid_options).to have(1).item
128
+ expect(described_class.valid_options).to include(:one)
129
+ end
130
+
131
+ it 'does not add duplicate options to the list of valid options' do
132
+ described_class.add_valid_option(:one)
133
+ described_class.add_valid_option(:one)
134
+
135
+ expect(described_class.valid_options).to have(1).item
136
+ end
137
+ end
138
+
139
+ describe "::add_location_key" do
140
+ before do
141
+ @original = described_class.class_variable_get :@@location_keys
142
+ described_class.class_variable_set :@@location_keys, {}
143
+ end
144
+
145
+ after do
146
+ described_class.class_variable_set :@@location_keys, @original
147
+ end
148
+
149
+ it 'adds a location key and the associated class to the list of valid locations' do
150
+ described_class.add_location_key(:git, described_class)
151
+
152
+ expect(described_class.location_keys).to have(1).item
153
+ expect(described_class.location_keys).to include(:git)
154
+ expect(described_class.location_keys[:git]).to eq(described_class)
155
+ end
156
+
157
+ it 'does not add duplicate location keys to the list of location keys' do
158
+ described_class.add_location_key(:git, described_class)
159
+ described_class.add_location_key(:git, described_class)
160
+
161
+ expect(described_class.location_keys).to have(1).item
162
+ expect(described_class.location_keys).to include(:git)
163
+ end
164
+ end
165
+ end
166
+
167
+ subject { described_class.new(berksfile, cookbook_name) }
168
+
169
+ describe '#add_group' do
170
+ it 'stores strings as symbols' do
171
+ subject.add_group 'foo'
172
+ expect(subject.groups).to eq([:default, :foo])
173
+ end
174
+
175
+ it 'does not store duplicate groups' do
176
+ subject.add_group 'bar'
177
+ subject.add_group 'bar'
178
+ subject.add_group :bar
179
+ expect(subject.groups).to eq([:default, :bar])
180
+ end
181
+
182
+ it 'adds multiple groups' do
183
+ subject.add_group 'baz', 'quux'
184
+ expect(subject.groups).to eq([:default, :baz, :quux])
185
+ end
186
+
187
+ it 'handles multiple groups as an array' do
188
+ subject.add_group ['baz', 'quux']
189
+ expect(subject.groups).to eq([:default, :baz, :quux])
190
+ end
191
+ end
192
+
193
+ describe "#cached_cookbook"
194
+ describe "#download"
195
+
196
+ describe '#downloaded?' do
197
+ it 'returns true if self.cached_cookbook is not nil' do
198
+ subject.stub(:cached_cookbook) { double('cb') }
199
+ expect(subject.downloaded?).to be_true
200
+ end
201
+
202
+ it 'returns false if self.cached_cookbook is nil' do
203
+ subject.stub(:cached_cookbook) { nil }
204
+ expect(subject.downloaded?).to be_false
205
+ end
206
+ end
207
+
208
+ describe '#to_hash' do
209
+ let(:hash) { subject.to_hash }
210
+
211
+ it 'does not include default values' do
212
+ [:constraint, :locked_version, :site, :git, :ref, :path].each do |key|
213
+ expect(hash).to_not have_key(key)
214
+ end
215
+ end
216
+
217
+ it 'includes the constraint' do
218
+ subject.version_constraint = '~> 1.0.0'
219
+
220
+ expect(hash).to have_key(:constraint)
221
+ expect(hash[:constraint]).to eq('~> 1.0.0')
222
+ end
223
+
224
+ it 'includes the locked version' do
225
+ subject.stub(cached_cookbook: double('cached', version: '1.2.3'))
226
+
227
+ expect(hash).to have_key(:locked_version)
228
+ expect(hash[:locked_version]).to eq('1.2.3')
229
+ end
230
+
231
+ it 'includes the git url and ref' do
232
+ location = double('git', uri: 'git://github.com/foo/bar.git', ref: 'abcd1234', rel: nil, download: nil)
233
+ location.stub(:kind_of?).and_return(false)
234
+ location.stub(:kind_of?).with(Berkshelf::GitLocation).and_return(true)
235
+ subject.stub(:location).and_return(location)
236
+
237
+ expect(hash).to have_key(:git)
238
+ expect(hash[:git]).to eq('git://github.com/foo/bar.git')
239
+ expect(hash).to have_key(:ref)
240
+ expect(hash[:ref]).to eq('abcd1234')
241
+ end
242
+
243
+ it 'includes the git url and rel' do
244
+ location = double('git', uri: 'git://github.com/foo/bar.git', ref: nil, rel: 'cookbooks/foo', download: nil)
245
+ location.stub(:kind_of?).and_return(false)
246
+ location.stub(:kind_of?).with(Berkshelf::GitLocation).and_return(true)
247
+ subject.stub(:location).and_return(location)
248
+
249
+ expect(hash).to have_key(:git)
250
+ expect(hash[:git]).to eq('git://github.com/foo/bar.git')
251
+ expect(hash).to have_key(:rel)
252
+ expect(hash[:rel]).to eq('cookbooks/foo')
253
+ end
254
+
255
+ it 'includes a relative path' do
256
+ location = double('path', relative_path: '../dev/foo')
257
+ location.stub(:kind_of?).and_return(false)
258
+ location.stub(:kind_of?).with(Berkshelf::PathLocation).and_return(true)
259
+ subject.stub(:location).and_return(location)
260
+
261
+ expect(hash).to have_key(:path)
262
+ expect(hash[:path]).to eq('../dev/foo')
263
+ end
264
+ end
265
+
266
+ describe "#scm_location?" do
267
+ let(:options) { Hash.new }
268
+ subject { described_class.new(berksfile, cookbook_name, options).scm_location? }
269
+
270
+ context "when the location is a GitLocation" do
271
+ let(:options) { { git: "git@github.com:RiotGames/berkshelf.git" } }
272
+ it { should be_true }
273
+ end
274
+
275
+ context "when the location is a GithubLocation" do
276
+ let(:options) { { github: "RiotGames/berkshelf" } }
277
+ it { should be_true }
278
+ end
279
+
280
+ context "when the location is a PathLocation" do
281
+ let(:options) { { path: fixtures_path.join('cookbooks', 'example_cookbook') } }
282
+ it { should be_false }
283
+ end
284
+ end
285
+ end