cookbook-omnifetch 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,87 +0,0 @@
1
- require "spec_helper"
2
- require "cookbook-omnifetch/exceptions"
3
-
4
- module CookbookOmnifetch
5
- describe "Exceptions" do
6
-
7
- describe NotACookbook do
8
-
9
- subject(:exception) do
10
- described_class.new("/path/to/cookbook")
11
- end
12
-
13
- let(:message) do
14
- "The resource at '/path/to/cookbook' does not appear to be a valid cookbook. Does it have a metadata.rb?"
15
- end
16
-
17
- it "creates an informative error in #message" do
18
- expect(exception.message).to eq(message)
19
- end
20
-
21
- it "creates an informative error in #to_s" do
22
- expect(exception.to_s).to eq(message)
23
- end
24
-
25
- end
26
-
27
- describe CookbookValidationFailure do
28
-
29
- let(:dependency) { instance_double("ChefDK::Policyfile::CookbookLocationSpecification", to_s: "apt ~> 1.2.3") }
30
-
31
- # The exception class itself doesn't use this
32
- let(:cached_cookbook) { Object.new }
33
-
34
- subject(:exception) do
35
- described_class.new(dependency, cached_cookbook)
36
- end
37
-
38
- let(:message) do
39
- "The cookbook downloaded for apt ~> 1.2.3 did not satisfy the constraint."
40
- end
41
-
42
- it "creates an informative error in #message" do
43
- expect(exception.message).to eq(message)
44
- end
45
-
46
- it "creates an informative error in #to_s" do
47
- expect(exception.to_s).to eq(message)
48
- end
49
-
50
- end
51
-
52
- describe MismatchedCookbookName do
53
-
54
- let(:dependency) { instance_double("ChefDK::Policyfile::CookbookLocationSpecification", name: "apt") }
55
-
56
- let(:cached_cookbook) { instance_double("Chef::Cookbook", cookbook_name: "apt") }
57
-
58
- subject(:exception) do
59
- described_class.new(dependency, cached_cookbook)
60
- end
61
-
62
- let(:message) do
63
- <<-EOM
64
- In your Berksfile, you have:
65
-
66
- cookbook 'apt'
67
-
68
- But that cookbook is actually named 'apt'
69
-
70
- This can cause potentially unwanted side-effects in the future.
71
-
72
- NOTE: If you do not explicitly set the 'name' attribute in the metadata, the name of the directory will be used instead. This is often a cause of confusion for dependency solving.
73
- EOM
74
- end
75
-
76
- it "creates an informative error in #message" do
77
- expect(exception.message).to eq(message)
78
- end
79
-
80
- it "creates an informative error in #to_s" do
81
- expect(exception.to_s).to eq(message)
82
- end
83
-
84
- end
85
-
86
- end
87
- end
@@ -1,290 +0,0 @@
1
- require "spec_helper"
2
- require "cookbook-omnifetch/git"
3
-
4
- module CookbookOmnifetch
5
- describe GitLocation do
6
- let(:dependency) { double(name: "bacon") }
7
-
8
- subject do
9
- described_class.new(dependency, git: "https://repo.com", branch: "ham",
10
- tag: "v1.2.3", ref: "abc123", revision: "defjkl123456", rel: "hi")
11
- end
12
-
13
- describe ".initialize" do
14
- it "sets the uri" do
15
- instance = described_class.new(dependency, git: "https://repo.com")
16
- expect(instance.uri).to eq("https://repo.com")
17
- end
18
-
19
- it "sets the branch" do
20
- instance = described_class.new(dependency,
21
- git: "https://repo.com", branch: "magic_new_feature")
22
- expect(instance.branch).to eq("magic_new_feature")
23
- end
24
-
25
- it "sets the tag" do
26
- instance = described_class.new(dependency,
27
- git: "https://repo.com", tag: "v1.2.3")
28
- expect(instance.tag).to eq("v1.2.3")
29
- end
30
-
31
- it "adds the ref" do
32
- instance = described_class.new(dependency,
33
- git: "https://repo.com", ref: "abc123")
34
- expect(instance.ref).to eq("abc123")
35
- end
36
-
37
- it "sets the revision" do
38
- instance = described_class.new(dependency,
39
- git: "https://repo.com", revision: "abcde12345")
40
- expect(instance.revision).to eq("abcde12345")
41
- end
42
-
43
- it "sets the rel" do
44
- instance = described_class.new(dependency,
45
- git: "https://repo.com", rel: "internal/path")
46
- expect(instance.rel).to eq("internal/path")
47
- end
48
-
49
- context "rev_parse" do
50
- def rev_parse(instance)
51
- instance.instance_variable_get(:@rev_parse)
52
- end
53
-
54
- it "uses the :ref option with priority" do
55
- instance = described_class.new(dependency,
56
- git: "https://repo.com", ref: "abc123", branch: "magic_new_feature")
57
- expect(rev_parse(instance)).to eq("abc123")
58
- end
59
-
60
- it "uses the :branch option with priority" do
61
- instance = described_class.new(dependency,
62
- git: "https://repo.com", branch: "magic_new_feature", tag: "v1.2.3")
63
- expect(rev_parse(instance)).to eq("magic_new_feature")
64
- end
65
-
66
- it "uses the :tag option" do
67
- instance = described_class.new(dependency,
68
- git: "https://repo.com", tag: "v1.2.3")
69
- expect(rev_parse(instance)).to eq("v1.2.3")
70
- end
71
-
72
- it 'uses "master" when none is given' do
73
- instance = described_class.new(dependency, git: "https://repo.com")
74
- expect(rev_parse(instance)).to eq("master")
75
- end
76
- end
77
- end
78
-
79
- describe "#cache_key" do
80
-
81
- it "concatenates the name and revision" do
82
- subject.stub(:revision).and_return("abcdef123456")
83
- expect(subject.cache_key).to eq("bacon-abcdef123456")
84
- end
85
- end
86
-
87
- describe "#installed?" do
88
- it "returns false when there is no revision" do
89
- subject.stub(:revision).and_return(nil)
90
- expect(subject.installed?).to be false
91
- end
92
-
93
- it "returns false when the install_path does not exist" do
94
- subject.stub(:revision).and_return("abcd1234")
95
- subject.stub(:install_path).and_return(double(exist?: false))
96
- expect(subject.installed?).to be false
97
- end
98
-
99
- it "returns true when the location is installed" do
100
- subject.stub(:revision).and_return("abcd1234")
101
- subject.stub(:install_path).and_return(double(exist?: true))
102
- expect(subject.installed?).to be true
103
- end
104
- end
105
-
106
- describe "#install" do
107
- before do
108
- File.stub(:chmod)
109
- FileUtils.stub(:cp_r)
110
- subject.stub(:validate_cached!)
111
- subject.stub(:git)
112
- end
113
-
114
- context "when the repository is cached" do
115
- it "pulls a new version" do
116
- Dir.stub(:chdir) { |args, &b| b.call } # Force eval the chdir block
117
-
118
- subject.stub(:cached?).and_return(true)
119
- expect(subject).to receive(:git).with(
120
- 'fetch --force --tags https://repo.com "refs/heads/*:refs/heads/*"'
121
- )
122
- subject.install
123
- end
124
- end
125
-
126
- context "when the revision is not cached" do
127
- it "clones the repository" do
128
- Dir.stub(:chdir) { |args, &b| b.call } # Force eval the chdir block
129
-
130
- cache_path = subject.send(:cache_path)
131
- subject.stub(:cached?).and_return(false)
132
- expect(subject).to receive(:git).with(
133
- %{clone https://repo.com "#{cache_path}" --bare --no-hardlinks}
134
- )
135
- subject.install
136
- end
137
- end
138
- end
139
-
140
- describe "#cached_cookbook" do
141
- it "returns nil if the cookbook is not installed" do
142
- subject.stub(:installed?).and_return(false)
143
- expect(subject.cached_cookbook).to be_nil
144
- end
145
-
146
- it "returns the cookbook at the install_path" do
147
- subject.stub(:installed?).and_return(true)
148
- MockCachedCookbook.stub(:from_path)
149
-
150
- expect(MockCachedCookbook).to receive(:from_path).once
151
- subject.cached_cookbook
152
- end
153
- end
154
-
155
- describe "#==" do
156
- let(:other) { subject.dup }
157
-
158
- it "returns true when everything matches" do
159
- expect(subject).to eq(other)
160
- end
161
-
162
- it "returns false when the other location is not an GitLocation" do
163
- other.stub(:is_a?).and_return(false)
164
- expect(subject).to_not eq(other)
165
- end
166
-
167
- it "returns false when the uri is different" do
168
- other.stub(:uri).and_return("different")
169
- expect(subject).to_not eq(other)
170
- end
171
-
172
- it "returns false when the branch is different" do
173
- other.stub(:branch).and_return("different")
174
- expect(subject).to_not eq(other)
175
- end
176
-
177
- it "returns false when the tag is different" do
178
- other.stub(:tag).and_return("different")
179
- expect(subject).to_not eq(other)
180
- end
181
-
182
- it "returns false when the ref is different" do
183
- other.stub(:ref).and_return("different")
184
- expect(subject).to_not eq(other)
185
- end
186
-
187
- it "returns false when the rel is different" do
188
- other.stub(:rel).and_return("different")
189
- expect(subject).to_not eq(other)
190
- end
191
- end
192
-
193
- describe "#to_s" do
194
- it "prefers the tag" do
195
- expect(subject.to_s).to eq("https://repo.com (at v1.2.3/hi)")
196
- end
197
-
198
- it "prefers the branch" do
199
- subject.stub(:tag).and_return(nil)
200
- expect(subject.to_s).to eq("https://repo.com (at ham/hi)")
201
- end
202
-
203
- it "falls back to the ref" do
204
- subject.stub(:tag).and_return(nil)
205
- subject.stub(:branch).and_return(nil)
206
- expect(subject.to_s).to eq("https://repo.com (at abc123/hi)")
207
- end
208
-
209
- it "does not use the rel if missing" do
210
- subject.stub(:rel).and_return(nil)
211
- expect(subject.to_s).to eq("https://repo.com (at v1.2.3)")
212
- end
213
- end
214
-
215
- describe "#to_lock" do
216
- it "includes all the information" do
217
- expect(subject.to_lock).to eq <<-EOH.gsub(/^ {8}/, "")
218
- git: https://repo.com
219
- revision: defjkl123456
220
- ref: abc123
221
- branch: ham
222
- tag: v1.2.3
223
- rel: hi
224
- EOH
225
- end
226
-
227
- it "does not include the branch if missing" do
228
- subject.stub(:branch).and_return(nil)
229
- expect(subject.to_lock).to_not include("branch")
230
- end
231
-
232
- it "does not include the tag if missing" do
233
- subject.stub(:tag).and_return(nil)
234
- expect(subject.to_lock).to_not include("tag")
235
- end
236
-
237
- it "does not include the rel if missing" do
238
- subject.stub(:rel).and_return(nil)
239
- expect(subject.to_lock).to_not include("rel")
240
- end
241
- end
242
-
243
- describe "#lock_data" do
244
- let(:full_lock_data) do
245
- {
246
- "git" => "https://repo.com",
247
- "revision" => "defjkl123456",
248
- "ref" => "abc123",
249
- "branch" => "ham",
250
- "tag" => "v1.2.3",
251
- "rel" => "hi",
252
- }
253
- end
254
-
255
- it "includes all the information" do
256
- expect(subject.lock_data).to eq(full_lock_data)
257
- end
258
-
259
- it "does not include the branch if missing" do
260
- subject.stub(:branch).and_return(nil)
261
- expect(subject.lock_data).to_not have_key("branch")
262
- end
263
-
264
- it "does not include the tag if missing" do
265
- subject.stub(:tag).and_return(nil)
266
- expect(subject.lock_data).to_not have_key("tag")
267
- end
268
-
269
- it "does not include the rel if missing" do
270
- subject.stub(:rel).and_return(nil)
271
- expect(subject.lock_data).to_not have_key("rel")
272
- end
273
- end
274
-
275
- describe "#git" do
276
- before { described_class.send(:public, :git) }
277
-
278
- it "raises an error if Git is not installed" do
279
- CookbookOmnifetch.stub(:which).and_return(false)
280
- expect { subject.git("foo") }.to raise_error(GitNotInstalled)
281
- end
282
-
283
- it "raises an error if the command fails" do
284
- shell_out = double("shell_out", success?: false, stderr: nil)
285
- MockShellOut.stub(:shell_out).and_return(shell_out)
286
- expect { subject.git("foo") }.to raise_error(GitCommandError)
287
- end
288
- end
289
- end
290
- end
@@ -1,137 +0,0 @@
1
- require "spec_helper"
2
- require "cookbook-omnifetch/metadata_based_installer.rb"
3
-
4
- RSpec.shared_context "sample_metadata" do
5
-
6
- let(:raw_metadata) do
7
- {
8
- "recipes" => [
9
- { "name" => "default.rb", "path" => "recipes/default.rb", "checksum" => "a6be794cdd2eb44d38fdf17f792a0d0d", "specificity" => "default", "url" => "https://example.com/recipes/default.rb" },
10
- ],
11
- "root_files" => [
12
- { "name" => "metadata.rb", "path" => "metadata.rb", "checksum" => "5b346119e5e41ab99500608decac8dca", "specificity" => "default", "url" => "https://example.com/metadata.rb" },
13
- ],
14
- }
15
-
16
- end
17
- end
18
-
19
- RSpec.describe CookbookOmnifetch::MetadataBasedInstaller::CookbookMetadata do
20
-
21
- include_context "sample_metadata"
22
-
23
- subject(:cb_metadata) { described_class.new(raw_metadata) }
24
-
25
- it "yields a set of paths and urls" do
26
- expect { |b| cb_metadata.files(&b) }.to yield_successive_args(["https://example.com/recipes/default.rb", "recipes/default.rb"], ["https://example.com/metadata.rb", "metadata.rb"])
27
- end
28
- end
29
-
30
- RSpec.describe CookbookOmnifetch::MetadataBasedInstaller do
31
-
32
- include_context "sample_metadata"
33
-
34
- let(:url_path) { "/cookbooks/example/0.5.0" }
35
-
36
- let(:http_client) do
37
- double("Http Client")
38
- end
39
-
40
- let(:recipe_url) do
41
- raw_metadata["recipes"][0]["url"]
42
- end
43
-
44
- let(:recipe_path) do
45
- raw_metadata["recipes"][0]["path"]
46
- end
47
-
48
- let(:recipe_filehandle) do
49
- File.open(File.join(remote_path, recipe_path))
50
- end
51
-
52
- let(:root_file_url) do
53
- raw_metadata["root_files"][0]["url"]
54
- end
55
-
56
- let(:root_file_path) do
57
- raw_metadata["root_files"][0]["path"]
58
- end
59
-
60
- let(:root_file_filehandle) do
61
- File.open(File.join(remote_path, root_file_path))
62
- end
63
-
64
- let(:cookbook_fixture_path) { fixtures_path.join("cookbooks/example_cookbook") }
65
-
66
- let(:test_root) { Dir.mktmpdir(nil) }
67
-
68
- let(:cache_path) { File.join(test_root, "cache") }
69
-
70
- let(:remote_path) { File.join(test_root, "remote") }
71
-
72
- let(:install_path) { File.join(test_root, "install_path") }
73
-
74
- let(:cookbook_files) { %w{metadata.rb recipes recipes/default.rb} }
75
-
76
- let(:expected_installed_files) do
77
- cookbook_files.map do |file|
78
- File.join(install_path, file)
79
- end
80
- end
81
-
82
- subject(:installer) do
83
- described_class.new(http_client: http_client,
84
- url_path: url_path,
85
- install_path: install_path)
86
- end
87
-
88
- before do
89
- FileUtils.cp_r(cookbook_fixture_path, remote_path)
90
-
91
- allow(CookbookOmnifetch).to receive(:cache_path).and_return(cache_path)
92
- end
93
-
94
- after do
95
- FileUtils.rm_r(test_root)
96
- end
97
-
98
- it "stages the download to a randomized location" do
99
- Kernel.srand(0)
100
- expected_path = Pathname.new(cache_path).join(".cache_tmp/metadata-installer/_cookbooks_example_0_5_0_209652396")
101
-
102
- expect(installer.staging_path).to eq(expected_path)
103
-
104
- next_installer = described_class.new(http_client: http_client,
105
- url_path: url_path,
106
- install_path: install_path)
107
-
108
- next_expected_path = Pathname.new(cache_path).join(".cache_tmp/metadata-installer/_cookbooks_example_0_5_0_398764591")
109
- expect(next_installer.staging_path).to eq(next_expected_path)
110
- end
111
-
112
- describe "installing the cookbook" do
113
-
114
- before do
115
- expect(http_client).to receive(:get).
116
- with(url_path).
117
- and_return(raw_metadata)
118
- expect(http_client).to receive(:streaming_request).
119
- with(recipe_url).
120
- and_yield(recipe_filehandle)
121
- expect(http_client).to receive(:streaming_request).
122
- with(root_file_url).
123
- and_yield(root_file_filehandle)
124
- end
125
-
126
- it "installs the cookbook to the desired install path" do
127
- expect(Dir).to_not exist(install_path)
128
-
129
- installer.install
130
-
131
- expect(Dir).to exist(install_path)
132
- expect(Dir.glob("#{install_path}/**/*")).to match_array(expected_installed_files)
133
- end
134
-
135
- end
136
-
137
- end