berkshelf 3.0.0.beta6 → 3.0.0.beta7

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/features/berksfile.feature +2 -0
  3. data/features/commands/apply.feature +1 -1
  4. data/features/commands/contingent.feature +5 -3
  5. data/features/commands/install.feature +40 -40
  6. data/features/commands/list.feature +42 -20
  7. data/features/commands/outdated.feature +60 -16
  8. data/features/commands/show.feature +51 -8
  9. data/features/commands/update.feature +43 -15
  10. data/features/commands/upload.feature +4 -1
  11. data/features/commands/vendor.feature +27 -0
  12. data/features/json_formatter.feature +20 -8
  13. data/features/lockfile.feature +192 -71
  14. data/generator_files/CHANGELOG.md.erb +5 -0
  15. data/lib/berkshelf/berksfile.rb +166 -139
  16. data/lib/berkshelf/cli.rb +33 -30
  17. data/lib/berkshelf/cookbook_generator.rb +1 -0
  18. data/lib/berkshelf/dependency.rb +64 -14
  19. data/lib/berkshelf/downloader.rb +7 -10
  20. data/lib/berkshelf/errors.rb +59 -11
  21. data/lib/berkshelf/formatters/human_readable.rb +23 -36
  22. data/lib/berkshelf/formatters/json.rb +25 -29
  23. data/lib/berkshelf/installer.rb +111 -122
  24. data/lib/berkshelf/locations/git_location.rb +22 -9
  25. data/lib/berkshelf/locations/mercurial_location.rb +20 -5
  26. data/lib/berkshelf/locations/path_location.rb +22 -7
  27. data/lib/berkshelf/lockfile.rb +435 -203
  28. data/lib/berkshelf/resolver.rb +4 -2
  29. data/lib/berkshelf/source.rb +10 -1
  30. data/lib/berkshelf/version.rb +1 -1
  31. data/spec/fixtures/cookbooks/example_cookbook/Berksfile.lock +3 -4
  32. data/spec/fixtures/lockfiles/2.0.lock +17 -0
  33. data/spec/fixtures/lockfiles/blank.lock +0 -0
  34. data/spec/fixtures/lockfiles/default.lock +18 -10
  35. data/spec/fixtures/lockfiles/empty.lock +3 -0
  36. data/spec/unit/berkshelf/berksfile_spec.rb +31 -74
  37. data/spec/unit/berkshelf/cookbook_generator_spec.rb +4 -0
  38. data/spec/unit/berkshelf/installer_spec.rb +4 -7
  39. data/spec/unit/berkshelf/lockfile_parser_spec.rb +124 -0
  40. data/spec/unit/berkshelf/lockfile_spec.rb +140 -163
  41. metadata +11 -6
  42. data/features/licenses.feature +0 -79
  43. data/features/step_definitions/lockfile_steps.rb +0 -57
@@ -71,8 +71,10 @@ module Berkshelf
71
71
  graph.populate(berksfile.sources)
72
72
 
73
73
  Solve.it!(graph, demand_array, ENV['DEBUG_RESOLVER'] ? { ui: Berkshelf.ui } : {}).collect do |name, version|
74
- dependency = get_demand(name) || Dependency.new(berksfile, name, locked_version: version)
75
- [ name, version, dependency ]
74
+ dependency = get_demand(name) || Dependency.new(berksfile, name)
75
+ dependency.locked_version = version
76
+
77
+ dependency
76
78
  end
77
79
  rescue Solve::Errors::NoSolutionError
78
80
  raise Berkshelf::NoSolutionError.new(demands)
@@ -44,6 +44,15 @@ module Berkshelf
44
44
  universe.find { |cookbook| cookbook.name == name && cookbook.version == version }
45
45
  end
46
46
 
47
+ # Determine if this source is a "default" source, as defined in the
48
+ # {Berksfile}.
49
+ #
50
+ # @return [true, false]
51
+ # true if this a default source, false otherwise
52
+ def default?
53
+ uri == Berksfile::DEFAULT_API_URL
54
+ end
55
+
47
56
  # @param [String] name
48
57
  #
49
58
  # @return [APIClient::RemoteCookbook]
@@ -59,7 +68,7 @@ module Berkshelf
59
68
  end
60
69
 
61
70
  def to_s
62
- uri.to_s
71
+ "#{uri}"
63
72
  end
64
73
 
65
74
  def ==(other)
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "3.0.0.beta6"
2
+ VERSION = "3.0.0.beta7"
3
3
  end
@@ -1,4 +1,3 @@
1
- {
2
- "dependencies": {
3
- }
4
- }
1
+ DEPENDENCIES
2
+
3
+ GRAPH
@@ -0,0 +1,17 @@
1
+ {
2
+ "dependencies": {
3
+ "jenkins": {
4
+ "locked_version": "2.0.3",
5
+ "path": "."
6
+ },
7
+ "apt": {
8
+ "locked_version": "2.3.6"
9
+ },
10
+ "runit": {
11
+ "locked_version": "1.5.8"
12
+ },
13
+ "yum": {
14
+ "locked_version": "3.0.6"
15
+ }
16
+ }
17
+ }
File without changes
@@ -1,10 +1,18 @@
1
- {
2
- "dependencies":{
3
- "build-essential":{
4
- "locked_version":"1.1.2"
5
- },
6
- "chef-client":{
7
- "locked_version":"2.1.4"
8
- }
9
- }
10
- }
1
+ DEPENDENCIES
2
+ apt (~> 2.0)
3
+ jenkins (~> 2.0)
4
+
5
+ GRAPH
6
+ apt (2.3.6)
7
+ build-essential (1.4.2)
8
+ jenkins (2.0.3)
9
+ apt (~> 2.0)
10
+ runit (~> 1.5)
11
+ yum (~> 3.0)
12
+ runit (1.5.8)
13
+ build-essential (>= 0.0.0)
14
+ yum (~> 3.0)
15
+ yum-epel (>= 0.0.0)
16
+ yum (3.0.6)
17
+ yum-epel (0.2.0)
18
+ yum (~> 3.0)
@@ -0,0 +1,3 @@
1
+ DEPENDENCIES
2
+
3
+ GRAPH
@@ -2,16 +2,6 @@ require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::Berksfile do
4
4
  describe "ClassMethods" do
5
- describe "::default_sources" do
6
- subject { described_class.default_sources }
7
-
8
- it "returns an array including the default sources" do
9
- expect(subject).to be_a(Array)
10
- expect(subject).to have(1).item
11
- expect(subject.map(&:to_s)).to include("https://api.berkshelf.com")
12
- end
13
- end
14
-
15
5
  describe '::from_file' do
16
6
  let(:content) do
17
7
  <<-EOF.strip
@@ -152,14 +142,6 @@ describe Berkshelf::Berksfile do
152
142
  expect(subject.sources[1].to_s).to_not eq(new_source)
153
143
  end
154
144
 
155
- context "when a source is explicitly specified" do
156
- it "does not include the default sources in the list" do
157
- subject.source(new_source)
158
- expect(subject.sources).to have(1).item
159
- expect(subject.sources).to_not include(described_class.default_sources)
160
- end
161
- end
162
-
163
145
  context "adding an invalid source" do
164
146
  let(:invalid_uri) { ".....$1233...." }
165
147
 
@@ -170,18 +152,26 @@ describe Berkshelf::Berksfile do
170
152
  end
171
153
 
172
154
  describe "#sources" do
173
- it "returns an Array" do
174
- expect(subject.sources).to be_a(Array)
155
+ context "when there are no sources" do
156
+ it "raises an exception" do
157
+ expect {
158
+ subject.sources
159
+ }.to raise_error(Berkshelf::NoAPISourcesDefined)
160
+ end
175
161
  end
176
162
 
177
- it "contains a collection of Berkshelf::Source" do
178
- subject.sources.each do |source|
179
- expect(source).to be_a(Berkshelf::Source)
163
+ context "when there are sources" do
164
+ before { subject.source("https://api.berkshelf.org") }
165
+
166
+ it "returns an Array" do
167
+ expect(subject.sources).to be_a(Array)
180
168
  end
181
- end
182
169
 
183
- it "includes the default sources" do
184
- expect(subject.sources).to include(*described_class.default_sources)
170
+ it "contains a collection of Berkshelf::Source" do
171
+ subject.sources.each do |source|
172
+ expect(source).to be_a(Berkshelf::Source)
173
+ end
174
+ end
185
175
  end
186
176
  end
187
177
 
@@ -213,45 +203,21 @@ describe Berkshelf::Berksfile do
213
203
  expect(subject).to have_dependency(dependency_one.name)
214
204
  expect(subject).to have_dependency(dependency_two.name)
215
205
  end
206
+ end
216
207
 
217
- context 'given the option :except' do
218
- before do
219
- dependency_one.stub(:groups) { [:default, :skarner] }
220
- dependency_two.stub(:groups) { [:default, :nautilus] }
221
- end
222
-
223
- it 'returns all of the dependencies except the ones in the given groups' do
224
- subject.add_dependency(dependency_one.name, nil, group: [:default, :skarner])
225
- subject.add_dependency(dependency_two.name, nil, group: [:default, :nautilus])
226
- filtered = subject.dependencies(except: :nautilus)
227
-
228
- expect(filtered).to have(1).item
229
- expect(filtered.first.name).to eq(dependency_one.name)
230
- end
208
+ describe '#cookbooks' do
209
+ it 'raises an exception if a cookbook is not installed' do
210
+ subject.add_dependency('bacon', nil)
211
+ expect { subject.cookbooks }.to raise_error
231
212
  end
232
213
 
233
- context 'given the option :only' do
234
- before do
235
- dependency_one.stub(:groups) { [:default, :skarner] }
236
- dependency_two.stub(:groups) { [:default, :nautilus] }
237
- end
238
-
239
- it 'returns only the dependencies in the givne groups' do
240
- subject.add_dependency(dependency_one.name, nil, group: [:default, :skarner])
241
- subject.add_dependency(dependency_two.name, nil, group: [:default, :nautilus])
242
- filtered = subject.dependencies(only: :nautilus)
214
+ it 'retrieves the locked (cached) cookbook for each dependency' do
215
+ subject.add_dependency('bacon', nil)
216
+ subject.add_dependency('ham', nil)
217
+ subject.stub(:retrive_locked)
243
218
 
244
- expect(filtered).to have(1).item
245
- expect(filtered.first.name).to eq(dependency_two.name)
246
- end
247
- end
248
-
249
- context 'when a value for :only and :except is given' do
250
- it 'raises an ArgumentError' do
251
- expect {
252
- subject.dependencies(only: [:default], except: [:other])
253
- }.to raise_error(Berkshelf::ArgumentError, "Cannot specify both :except and :only")
254
- end
219
+ expect(subject).to receive(:retrieve_locked).twice
220
+ subject.cookbooks
255
221
  end
256
222
  end
257
223
 
@@ -338,7 +304,7 @@ describe Berkshelf::Berksfile do
338
304
  end
339
305
 
340
306
  describe '#retrieve_locked' do
341
- let(:lockfile) { double('lockfile', find: locked) }
307
+ let(:lockfile) { double('lockfile') }
342
308
  let(:dependency) { double('dependency', name: 'bacon') }
343
309
  let(:locked) { double('locked', cached_cookbook: cached, locked_version: '1.0.0') }
344
310
  let(:cached) { double('cached') }
@@ -347,18 +313,9 @@ describe Berkshelf::Berksfile do
347
313
  subject.stub(:lockfile).and_return(lockfile)
348
314
  end
349
315
 
350
- it 'raises an error when the lockfile does not have the source' do
351
- lockfile.stub(:find)
352
- expect {
353
- subject.retrieve_locked(dependency)
354
- }.to raise_error(Berkshelf::CookbookNotFound)
355
- end
356
-
357
- it 'raises an error when the cookbook is not downloaded' do
358
- locked.stub(:downloaded?).and_return(false)
359
- expect {
360
- subject.retrieve_locked(dependency)
361
- }.to raise_error(Berkshelf::CookbookNotFound)
316
+ it 'delegates to the lockfile' do
317
+ expect(lockfile).to receive(:retrieve).with(dependency)
318
+ subject.retrieve_locked(dependency)
362
319
  end
363
320
  end
364
321
 
@@ -46,6 +46,10 @@ describe Berkshelf::CookbookGenerator do
46
46
  contains ' "recipe[sparkle_motion::default]"'
47
47
  contains 'Author:: YOUR_NAME (<YOUR_EMAIL>)'
48
48
  end
49
+ file 'CHANGELOG.md' do
50
+ contains '# sparkle_motion cookbook CHANGELOG'
51
+ contains "## v0.1.0 (#{Time.now.strftime('%Y-%m-%d')})"
52
+ end
49
53
  file 'metadata.rb' do
50
54
  contains "name 'sparkle_motion'"
51
55
  contains "maintainer 'YOUR_NAME'"
@@ -1,12 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::Installer do
4
- let(:berksfile) { double('berksfile') }
4
+ let(:berksfile) { double('berksfile', lockfile: lockfile) }
5
+ let(:lockfile) { double('lockfile') }
5
6
  subject { described_class.new(berksfile) }
6
7
 
7
8
  describe "#build_universe" do
8
- let(:source_one) { double('one') }
9
- let(:source_two) { double('two') }
9
+ let(:source_one) { double('one', uri: 'https://api.berkshelf.com') }
10
+ let(:source_two) { double('two', uri: 'https://api.chef.org') }
10
11
  let(:sources) { [ source_one, source_two ] }
11
12
 
12
13
  before { berksfile.stub(sources: sources) }
@@ -32,8 +33,4 @@ describe Berkshelf::Installer do
32
33
  pending
33
34
  end
34
35
  end
35
-
36
- describe "#verify_licenses!" do
37
- pending
38
- end
39
36
  end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe Berkshelf::Lockfile do
4
+ before do
5
+ subject.stub(:filepath).and_return(fixture) if defined?(fixture)
6
+ subject.parse
7
+ end
8
+
9
+ context 'with an old 2.0 lockfile format' do
10
+ let(:fixture) { fixtures_path.join('lockfiles/2.0.lock') }
11
+
12
+ it 'does not blow up' do
13
+ expect { subject }.to_not raise_error
14
+ end
15
+
16
+ it 'warns the user' do
17
+ expect(Berkshelf.ui).to receive(:warn)
18
+ subject.parse
19
+ end
20
+
21
+ it 'sets the dependencies' do
22
+ expect(subject).to have_dependency('apt')
23
+ expect(subject).to have_dependency('jenkins')
24
+ expect(subject).to have_dependency('runit')
25
+ expect(subject).to have_dependency('yum')
26
+
27
+ expect(subject.find('apt').version_constraint.to_s).to eq('>= 0.0.0')
28
+ expect(subject.find('jenkins').version_constraint.to_s).to eq('>= 0.0.0')
29
+ expect(subject.find('runit').version_constraint.to_s).to eq('>= 0.0.0')
30
+ expect(subject.find('yum').version_constraint.to_s).to eq('>= 0.0.0')
31
+ end
32
+
33
+ it 'sets the graph' do
34
+ graph = subject.graph
35
+
36
+ expect(graph).to have_lock('apt')
37
+ expect(graph).to have_lock('jenkins')
38
+ expect(graph).to have_lock('runit')
39
+ expect(graph).to have_lock('yum')
40
+
41
+ expect(graph.find('apt').version).to eq('2.3.6')
42
+ expect(graph.find('jenkins').version).to eq('2.0.3')
43
+ expect(graph.find('runit').version).to eq('1.5.8')
44
+ expect(graph.find('yum').version).to eq('3.0.6')
45
+ end
46
+ end
47
+
48
+ context 'with a blank lockfile' do
49
+ let(:fixture) { fixtures_path.join('lockfiles/blank.lock') }
50
+
51
+ it 'warns the user' do
52
+ expect(Berkshelf.ui).to receive(:warn)
53
+ subject.parse
54
+ end
55
+
56
+ it 'sets an empty list of dependencies' do
57
+ expect(subject.dependencies).to be_empty
58
+ end
59
+
60
+ it 'sets an empty graph' do
61
+ expect(subject.graph.locks).to be_empty
62
+ end
63
+ end
64
+
65
+ context 'with an empty lockfile' do
66
+ let(:fixture) { fixtures_path.join('lockfiles/empty.lock') }
67
+
68
+ it 'does not warn the user' do
69
+ expect(Berkshelf.ui).to_not receive(:warn)
70
+ subject.parse
71
+ end
72
+
73
+ it 'sets an empty list of dependencies' do
74
+ expect(subject.dependencies).to be_empty
75
+ end
76
+
77
+ it 'sets an empty graph' do
78
+ expect(subject.graph.locks).to be_empty
79
+ end
80
+ end
81
+
82
+ context 'with real lockfile' do
83
+ let(:fixture) { fixtures_path.join('lockfiles/default.lock') }
84
+
85
+ it 'sets the dependencies' do
86
+ expect(subject).to have_dependency('apt')
87
+ expect(subject).to have_dependency('jenkins')
88
+
89
+ expect(subject.find('apt').version_constraint.to_s).to eq('~> 2.0')
90
+ expect(subject.find('jenkins').version_constraint.to_s).to eq('~> 2.0')
91
+ end
92
+
93
+ it 'sets the graph' do
94
+ graph = subject.graph
95
+
96
+ expect(graph).to have_lock('apt')
97
+ expect(graph).to have_lock('build-essential')
98
+ expect(graph).to have_lock('jenkins')
99
+ expect(graph).to have_lock('runit')
100
+ expect(graph).to have_lock('yum')
101
+ expect(graph).to have_lock('yum-epel')
102
+
103
+ expect(graph.find('apt').version).to eq('2.3.6')
104
+ expect(graph.find('build-essential').version).to eq('1.4.2')
105
+ expect(graph.find('jenkins').version).to eq('2.0.3')
106
+ expect(graph.find('runit').version).to eq('1.5.8')
107
+ expect(graph.find('yum').version).to eq('3.0.6')
108
+ expect(graph.find('yum-epel').version).to eq('0.2.0')
109
+ end
110
+
111
+ it 'sets the graph item dependencies' do
112
+ jenkins = subject.graph.find('jenkins')
113
+ runit = subject.graph.find('runit')
114
+
115
+ expect(jenkins.dependencies).to include('apt' => '~> 2.0')
116
+ expect(jenkins.dependencies).to include('runit' => '~> 1.5')
117
+ expect(jenkins.dependencies).to include('yum' => '~> 3.0')
118
+
119
+ expect(runit.dependencies).to include('build-essential' => '>= 0.0.0')
120
+ expect(runit.dependencies).to include('yum' => '~> 3.0')
121
+ expect(runit.dependencies).to include('yum-epel' => '>= 0.0.0')
122
+ end
123
+ end
124
+ end
@@ -1,234 +1,211 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Berkshelf::Lockfile do
4
- let!(:content) { File.read(fixtures_path.join('lockfiles/default.lock')) }
5
- let(:berksfile) { Berkshelf::Berksfile.new('Berksfile') }
4
+ let(:filepath) { fixtures_path.join('lockfiles/default.lock').to_s }
5
+ subject { Berkshelf::Lockfile.new(filepath: filepath) }
6
6
 
7
- before do
8
- File.stub(:read).and_return(content)
9
- end
7
+ describe '.initialize' do
8
+ subject { described_class.new(filepath: filepath) }
10
9
 
11
- describe '::initialize' do
12
- it 'does not throw an exception' do
13
- expect {
14
- Berkshelf::Lockfile.from_berksfile(berksfile)
15
- }.to_not raise_error
10
+ it 'sets the instance variables' do
11
+ expect(subject.filepath).to eq(filepath)
12
+ expect(subject.dependencies).to be_a(Array)
13
+ expect(subject.graph).to be_a(Berkshelf::Lockfile::Graph)
16
14
  end
17
15
 
18
16
  it 'has the correct dependencies' do
19
- expect(subject).to have_dependency 'build-essential'
20
- expect(subject).to have_dependency 'chef-client'
17
+ expect(subject).to have_dependency('apt')
18
+ expect(subject).to have_dependency('jenkins')
21
19
  end
22
20
  end
23
21
 
24
- subject { Berkshelf::Lockfile.from_berksfile(berksfile) }
25
-
26
- describe "#apply" do
27
- let(:env_name) { 'berkshelf-test' }
28
- let(:server_url) { Berkshelf::RSpec::ChefServer.server_url }
29
- let(:client_name) { 'berkshelf' }
30
- let(:client_key) {
31
- "-----BEGIN RSA PRIVATE KEY-----
32
- MIIEpQIBAAKCAQEAs3u5qfmdEWtzYHvXpbQRyefhUjeTG7nwhn/LaYY6ou19xxW0
33
- I5MKSBqCxUCHqODRc7ox8zSF37x3jMBHbSczOcfbWsSe/qGnmvZZQhHmXCje2zkW
34
- ByaRHmmatzkz1aAqAmZm/wdSuVLXytsbrPXuaj/MiHa6QH3e/ZFaYME7rMkouqfC
35
- pUlSa2tZ9Ko1ZCCwjkiifuP4yQFsS6/G6b8c7F8wdq4byfJ9o6FN34lJHrzfG0ZV
36
- hwS47Bdn6FDBQ6PVxrBsvQNE2n7QlNLfXWi4Tb8OpmQif01FjxleAr5kamx3GD+s
37
- jC7fKHE9bZ0apZ1MVmkz9PhFmOigV5jl9Att+QIDAQABAoIBAQCCG6qXgQ9PVWkq
38
- BBxrToGmr6UzCH5nlv65QWKfeGKBQU/wRdd0Al9trWomu4Sb831iOxOCjgyOB/1R
39
- 1wDwK36C4FIvFmF7jIwHVZWWw4sOO8JxgIxrWpXQShWRxLHCpnxNiRYYwaJCHb+4
40
- meUSGKVf+Ce4tPiHT7eacQfnI6yyr1hWusKu0I8w7NsfeNc+/Rpne6mifLfaB/9u
41
- b9kgfD15HGEsuUaMLZ/y1HFWvw2G2Og1cDrIpBIVtUAhA+DnjjLe/YoETeSmQAxH
42
- ioQpJJ/gSqtTczIoyPXXiwaF5wUTQrsn5zZhTs9mAQy7hcSR92IH2xBSmK3+wlz0
43
- vHZIq9rRAoGBAOeRUTRDgj+f+BlH1qFqf4EfkBN5quVM2808LYBGZWfA5/6o9jSN
44
- AM84VXq3S8Wy5V6UMcSv4mOqEr3tEUYE8or9r/RxzpGahSdi8Ttju9vvpJH5I3xr
45
- xx2ZK/vlrAfr6JHlE4bqqc5unCslUt2/liCWpERQ3cFcPydQb7Imrm+DAoGBAMZr
46
- mcxBeMyQHG6Kcpc7EQXZ5i7a8T6ksPu7FbAZ70Meb9UMtVIYpVBalutCXKhl7D4K
47
- qrCmV2gQryBz+S7AecFZSKvXdb7ueYzf8EcI/v+loNu9v9/4m4YV3bPBkMhW5kcK
48
- xFnVIsYqUlR+dsS8JfjSCpk4lePVSSt7B26eIFfTAoGBAJHPDKSuBWtunNe+RkUp
49
- O9PgPeYlbBgqBxT52WS17tAfxXSyiySXzHSuchRtKgb4GDkvcw73+MLsqhRxG7lN
50
- EDO4fXyb1IgWFdWxFVhh+j4IbUWE7HVBoAThF7Lq8SGjx7Nl3J/NTtKvDyKTw9Pg
51
- +PTYJeLmUFuabCGjIlG4zYllAoGBAIwe5oB4597GEl35xUyI+M+B/myuTtknIpjS
52
- mFFBL1bdwqnYjJ+KKgwhvRwsRBTjzT5O+BVBks45ogKwA5OBdzoUXB6GTG9mJ05V
53
- wm/XqYRNqdgkGsEG5oV9IZBUrHLd80bOErVBr4nzzyo+GI98MvCRG8zySd+X+lEL
54
- U8dJQZvjAoGAWorll+fomfie6t5XbkpwMo8rn60yFUiRE7HWxA2qDj3IpoE6SfNE
55
- eOpsf1Zzx30r8answ9lPnd753ACdgNzE66ScWD+cQeB6OlMZMaW5tVSjddZ7854L
56
- 00znt8b1OLkVY33xfsa89wKH343304BhVHABPMxm5Leua/H21/BqSK0=
57
- -----END RSA PRIVATE KEY-----
58
- "
59
- }
60
- let(:ridley) { Ridley.new(server_url: server_url, client_name: client_name, client_key: client_key) }
22
+ describe '#parse' do
23
+ let(:parser) { double('parser', run: true) }
61
24
 
62
25
  before do
63
- Berkshelf.stub(:ridley_connection).and_yield(ridley)
64
- berksfile.add_dependency('nginx', '>= 0.1.2')
26
+ Berkshelf::Lockfile::LockfileParser.stub(:new).and_return(parser)
65
27
  end
66
28
 
67
- context "when the chef environment exists" do
68
- let(:dependencies) do
69
- [
70
- double(name: 'nginx', locked_version: '1.2.3'),
71
- double(name: 'artifact', locked_version: '1.4.0')
72
- ]
73
- end
74
-
75
- before do
76
- chef_environment(env_name)
77
- subject.stub(:dependencies).and_return(dependencies)
78
- end
79
-
80
- # it "test", focus: true do
81
- # p client_key
82
- # p File.read(client_key)
83
- # # p ridley.environment.find(env_name)
84
- # end
85
-
86
- it "applys the locked_versions of the Lockfile dependencies to the given Chef environment" do
87
- subject.apply(env_name)
88
-
89
- environment = ::JSON.parse(chef_server.data_store.get(['environments', env_name]))
90
- expect(environment['cookbook_versions']).to have(2).items
91
- expect(environment['cookbook_versions']['nginx']).to eq('= 1.2.3')
92
- expect(environment['cookbook_versions']['artifact']).to eq('= 1.4.0')
93
- end
29
+ it 'creates a new parser object' do
30
+ expect(Berkshelf::Lockfile::LockfileParser).to receive(:new).with(subject)
31
+ expect(parser).to receive(:run)
32
+ subject.parse
94
33
  end
95
34
 
96
- context "when the environment does not exist" do
97
- it "raises an EnvironmentNotFound error" do
98
- expect {
99
- subject.apply("not-there")
100
- }.to raise_error(Berkshelf::EnvironmentNotFound)
101
- end
35
+ it 'returns true (always)' do
36
+ expect(subject.parse).to be_true
102
37
  end
103
38
  end
104
39
 
105
- describe '#dependencies' do
106
- it 'returns an array' do
107
- expect(subject.dependencies).to be_a(Array)
40
+ describe '#present?' do
41
+ it 'returns true when the file exists' do
42
+ expect(subject.present?).to be_true
108
43
  end
109
- end
110
44
 
111
- describe '#find' do
112
- it 'returns a matching cookbook' do
113
- expect(subject.find('build-essential').name).to eq 'build-essential'
45
+ it 'returns false when the file does not exist' do
46
+ File.stub(:exists?).and_return(false)
47
+ expect(subject.present?).to be_false
114
48
  end
115
49
 
116
- it 'returns nil for a missing cookbook' do
117
- expect(subject.find('foo')).to be_nil
50
+ it 'returns false when the file is empty' do
51
+ File.stub(:read).and_return('')
52
+ expect(subject.present?).to be_false
118
53
  end
119
54
  end
120
55
 
121
- describe '#has_dependency?' do
122
- it 'returns true if a matching cookbook is found' do
123
- expect(subject.has_dependency?('build-essential')).to be_true
124
- end
56
+ describe '#trusted?' do
57
+ it 'returns true when the lockfile is trusted' do
58
+ apt = double('apt',
59
+ version_constraint: Solve::Constraint.new('>= 0.0.0'),
60
+ version: '1.0.0',
61
+ location: 'api',
62
+ )
63
+ berksfile = double('berksfile', dependencies: [apt])
64
+ subject.instance_variable_set(:@berksfile, berksfile)
65
+ subject.stub(:find).with(apt).and_return(apt)
66
+ subject.graph.stub(:find).with(apt).and_return(apt)
125
67
 
126
- it 'returns false if no matching cookbook is found' do
127
- expect(subject.has_dependency?('foo')).to be_false
68
+ expect(subject.trusted?).to be_true
128
69
  end
129
- end
130
70
 
131
- describe '#update' do
132
- it 'resets the dependencies' do
133
- subject.should_receive(:reset_dependencies!).once
134
- subject.update([])
135
- end
71
+ it 'returns false if the dependency is not in the lockfile' do
72
+ apt = double('apt', version_constraint: nil)
73
+ berksfile = double('berksfile', dependencies: [apt])
74
+ subject.instance_variable_set(:@berksfile, berksfile)
136
75
 
137
- it 'appends each of the dependencies' do
138
- dependency = double('dependency')
139
- subject.should_receive(:append).with(dependency).once
140
- subject.update([dependency])
76
+ expect(subject.trusted?).to be_false
141
77
  end
142
78
 
143
- it 'saves the file' do
144
- subject.should_receive(:save).once
145
- subject.update([])
79
+ it 'returns false if the dependency is not in the graph' do
80
+ apt = double('apt', version_constraint: nil)
81
+ berksfile = double('berksfile', dependencies: [apt])
82
+ subject.instance_variable_set(:@berksfile, berksfile)
83
+ subject.stub(:find).with(apt).and_return(true)
84
+ subject.graph.stub(:find).with(apt).and_return(false)
85
+
86
+ expect(subject.trusted?).to be_false
146
87
  end
147
- end
148
88
 
149
- describe '#add' do
150
- let(:dependency) { double('dependency', name: 'build-essential') }
89
+ it 'returns false if the constraint is not satisfied' do
90
+ apt = double('apt',
91
+ version_constraint: Solve::Constraint.new('< 1.0.0'),
92
+ version: '1.0.0',
93
+ location: 'api'
94
+ )
95
+ berksfile = double('berksfile', dependencies: [apt])
96
+ subject.instance_variable_set(:@berksfile, berksfile)
97
+ subject.stub(:find).with(apt).and_return(apt)
98
+ subject.graph.stub(:find).with(apt).and_return(apt)
151
99
 
152
- it 'adds the new dependency to the @dependencies instance variable' do
153
- subject.add(dependency)
154
- expect(subject).to have_dependency(dependency)
100
+ expect(subject.trusted?).to be_false
155
101
  end
156
102
 
157
- it 'does not add duplicate dependencies' do
158
- 5.times { subject.add(dependency) }
159
- expect(subject).to have_dependency(dependency)
103
+ it 'returns false if the locations are different' do
104
+ apt = double('apt',
105
+ version_constraint: Solve::Constraint.new('< 1.0.0'),
106
+ version: '1.0.0',
107
+ location: 'api'
108
+ )
109
+ apt_master = apt.dup
110
+ apt_master.stub(location: 'github')
111
+ berksfile = double('berksfile', dependencies: [apt])
112
+ subject.instance_variable_set(:@berksfile, berksfile)
113
+ subject.stub(:find).with(apt).and_return(apt_master)
114
+ subject.graph.stub(:find).with(apt).and_return(apt)
115
+
116
+ expect(subject.trusted?).to be_false
160
117
  end
161
118
  end
162
119
 
163
- describe '#remove' do
164
- let(:dependency) { double('dependency', name: 'build-essential') }
120
+ describe '#apply' do
121
+ let(:connection) { double('connection') }
165
122
 
166
123
  before do
167
- subject.add(dependency)
124
+ Berkshelf.stub(:ridley_connection).and_yield(connection)
168
125
  end
169
126
 
170
- it 'removes the dependency' do
171
- subject.remove(dependency)
172
- expect(subject).to_not have_dependency(dependency)
127
+ context 'when the Chef environment does not exist' do
128
+ it 'raises an exception' do
129
+ connection.stub(:environment).and_return(double(find: nil))
130
+ expect {
131
+ subject.apply('production')
132
+ }.to raise_error(Berkshelf::EnvironmentNotFound)
133
+ end
173
134
  end
174
135
 
175
- it 'raises an except if the dependency does not exist' do
176
- expect {
177
- subject.remove(nil)
178
- }.to raise_error Berkshelf::CookbookNotFound
136
+ it 'locks the environment cookbook versions' do
137
+ apt = double(name: 'apt', locked_version: '1.0.0')
138
+ jenkins = double(name: 'jenkins', locked_version: '1.4.5')
139
+ subject.graph.stub(:locks).and_return('apt' => apt, 'jenkins' => jenkins)
140
+
141
+ environment = double('environment', :cookbook_versions= => nil, save: true)
142
+ connection.stub(:environment).and_return(double(find: environment))
143
+
144
+ expect(environment).to receive(:cookbook_versions=).with(
145
+ 'apt' => '= 1.0.0',
146
+ 'jenkins' => '= 1.4.5',
147
+ )
148
+
149
+ subject.apply('production')
179
150
  end
180
151
  end
181
152
 
182
- describe '#to_hash' do
183
- let(:hash) { subject.to_hash }
184
-
185
- it 'has the `:dependencies` key' do
186
- expect(hash).to have_key(:dependencies)
153
+ describe '#dependencies' do
154
+ it 'returns an array' do
155
+ expect(subject.dependencies).to be_a(Array)
187
156
  end
188
157
  end
189
158
 
190
- describe '#to_json' do
191
- it 'dumps the #to_hash to JSON' do
192
- JSON.should_receive(:pretty_generate).with(subject.to_hash, {})
193
- subject.to_json
159
+ describe '#find' do
160
+ it 'returns a matching cookbook' do
161
+ expect(subject.find('apt').name).to eq('apt')
162
+ end
163
+
164
+ it 'returns nil for a missing cookbook' do
165
+ expect(subject.find('foo')).to be_nil
194
166
  end
195
167
  end
196
168
 
197
- describe '#save' do
198
- before { Berkshelf::Lockfile.send(:public, :save) }
199
- let(:file) { double('file') }
169
+ describe '#has_dependency?' do
170
+ it 'returns true if a matching cookbook is found' do
171
+ expect(subject).to have_dependency('apt')
172
+ end
200
173
 
201
- before(:each) do
202
- File.stub(:open).with('Berksfile.lock', 'w')
174
+ it 'returns false if no matching cookbook is found' do
175
+ expect(subject).to_not have_dependency('foo')
203
176
  end
177
+ end
204
178
 
205
- it 'saves itself to a file on disk' do
206
- File.should_receive(:open).with(/(.+)\/Berksfile\.lock/, 'w').and_yield(file)
207
- file.should_receive(:write).once
208
- subject.save
179
+ describe '#add' do
180
+ it 'adds the dependency to the lockfile' do
181
+ subject.add('apache2')
182
+ expect(subject).to have_dependency('apache2')
209
183
  end
210
184
  end
211
185
 
212
- describe '#reset_dependencies!' do
213
- before { Berkshelf::Lockfile.send(:public, :reset_dependencies!) }
186
+ describe '#update' do
187
+ it 'resets the dependencies' do
188
+ subject.update([])
189
+ expect(subject.dependencies).to be_empty
190
+ end
214
191
 
215
- it 'sets the dependencies to an empty hash' do
216
- expect {
217
- subject.reset_dependencies!
218
- }.to change { subject.dependencies }.to([])
192
+ it 'appends each of the dependencies' do
193
+ subject.update(['apache2'])
194
+ expect(subject).to have_dependency('apache2')
219
195
  end
220
196
  end
221
197
 
222
- describe '#cookbook_name' do
223
- before { Berkshelf::Lockfile.send(:public, :cookbook_name) }
224
-
225
- it 'accepts a cookbook dependency' do
226
- dependency = double('dependency', name: 'build-essential', is_a?: true)
227
- expect(subject.cookbook_name(dependency)).to eq 'build-essential'
198
+ describe '#unlock' do
199
+ it 'raises an exception when the dependency does not exist' do
200
+ expect {
201
+ subject.unlock('foo')
202
+ }.to raise_error(Berkshelf::CookbookNotFound)
228
203
  end
229
204
 
230
- it 'accepts a string' do
231
- expect(subject.cookbook_name('build-essential')).to eq 'build-essential'
205
+ it 'removes the dependency from the graph' do
206
+ subject.add('apache2')
207
+ subject.unlock('apache2')
208
+ expect(subject).to_not have_dependency('apache2')
232
209
  end
233
210
  end
234
211
  end