puppet-library 0.2.0 → 0.3.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.
- checksums.yaml +13 -5
- data/.travis.yml +7 -4
- data/CHANGELOG.yml +4 -0
- data/{lib/puppet_library/module_repo/multi.rb → Guardfile} +6 -24
- data/README.md +15 -0
- data/Rakefile +60 -5
- data/config.ru +2 -2
- data/lib/puppet_library/forge/abstract.rb +183 -0
- data/lib/puppet_library/{module_repo → forge}/directory.rb +9 -3
- data/lib/puppet_library/forge/multi.rb +81 -0
- data/lib/puppet_library/{module_repo → forge}/proxy.rb +32 -22
- data/lib/puppet_library/forge/search_result.rb +50 -0
- data/lib/puppet_library/forge.rb +6 -91
- data/lib/puppet_library/http/cache.rb +21 -0
- data/lib/puppet_library/http.rb +22 -0
- data/lib/puppet_library/puppet_library.rb +13 -14
- data/lib/puppet_library/server.rb +22 -7
- data/lib/puppet_library/util.rb +25 -0
- data/lib/puppet_library/version.rb +1 -1
- data/lib/puppet_library.rb +8 -13
- data/puppet-library.gemspec +7 -0
- data/spec/{forge_spec.rb → forge/abstract_spec.rb} +120 -3
- data/spec/{module_repo → forge}/directory_spec.rb +27 -1
- data/spec/forge/multi_spec.rb +314 -0
- data/spec/forge/proxy_spec.rb +206 -0
- data/spec/puppet_library_spec.rb +17 -25
- data/spec/server_spec.rb +26 -3
- data/spec/spec_helper.rb +1 -1
- data/test/librarian_puppet_integration_test.rb +21 -6
- metadata +83 -37
- data/lib/puppet_library/module_metadata.rb +0 -72
- data/spec/module_repo/multi_spec.rb +0 -97
- data/spec/module_repo/proxy_spec.rb +0 -115
@@ -0,0 +1,314 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# Puppet Library
|
3
|
+
# Copyright (C) 2014 drrb
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require 'spec_helper'
|
19
|
+
|
20
|
+
class Hash
|
21
|
+
def deep_clone
|
22
|
+
other = clone
|
23
|
+
keys.each do |key|
|
24
|
+
other[key] = self[key].clone
|
25
|
+
end
|
26
|
+
other
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module PuppetLibrary::Forge
|
31
|
+
describe Multi do
|
32
|
+
let(:subforge_one) { double('subforge_one').as_null_object }
|
33
|
+
let(:subforge_two) { double('subforge_two').as_null_object }
|
34
|
+
let(:multi_forge) do
|
35
|
+
forge = Multi.new
|
36
|
+
forge.add_forge(subforge_one)
|
37
|
+
forge.add_forge(subforge_two)
|
38
|
+
return forge
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#search_modules" do
|
42
|
+
context "when no modules match in any subforge" do
|
43
|
+
it "returns an empty array" do
|
44
|
+
expect(subforge_one).to receive(:search_modules).with("apache").and_return([])
|
45
|
+
expect(subforge_two).to receive(:search_modules).with("apache").and_return([])
|
46
|
+
|
47
|
+
result = multi_forge.search_modules("apache")
|
48
|
+
|
49
|
+
expect(result).to eq []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when modules match in subforges" do
|
54
|
+
it "returns an array with all of them" do
|
55
|
+
apache = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "version" => "1"}
|
56
|
+
concat = { "author" => "puppetlabs", "full_name" => "puppetlabs/concat", "version" => "1"}
|
57
|
+
expect(subforge_one).to receive(:search_modules).with("puppetlabs").and_return([apache])
|
58
|
+
expect(subforge_two).to receive(:search_modules).with("puppetlabs").and_return([concat])
|
59
|
+
|
60
|
+
result = multi_forge.search_modules("puppetlabs")
|
61
|
+
|
62
|
+
result = result.sort_by {|r| r["full_name"]}
|
63
|
+
expect(result).to eq [apache, concat]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when modules match in subforges that overlap" do
|
68
|
+
it "favors the details of the ones in the first repository" do
|
69
|
+
apache_1 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "one", "version" => "1"}
|
70
|
+
apache_2 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "two", "version" => "2"}
|
71
|
+
expect(subforge_one).to receive(:search_modules).with("puppetlabs").and_return([apache_1])
|
72
|
+
expect(subforge_two).to receive(:search_modules).with("puppetlabs").and_return([apache_2])
|
73
|
+
|
74
|
+
result = multi_forge.search_modules("puppetlabs")
|
75
|
+
|
76
|
+
expect(result.size).to eq 1
|
77
|
+
expect(result.first["desc"]).to eq "one"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "sets the version to the maximum version" do
|
81
|
+
apache_1 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "one", "version" => "1"}
|
82
|
+
apache_2 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "two", "version" => "2"}
|
83
|
+
expect(subforge_one).to receive(:search_modules).with("puppetlabs").and_return([apache_1])
|
84
|
+
expect(subforge_two).to receive(:search_modules).with("puppetlabs").and_return([apache_2])
|
85
|
+
|
86
|
+
result = multi_forge.search_modules("puppetlabs")
|
87
|
+
|
88
|
+
expect(result.size).to eq 1
|
89
|
+
expect(result.first["version"]).to eq "2"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "combines the available tags" do
|
93
|
+
apache_1 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "one", "version" => "1", "tag_list" => ["a", "b"]}
|
94
|
+
apache_2 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "two", "version" => "2", "tag_list" => ["a", "c"]}
|
95
|
+
expect(subforge_one).to receive(:search_modules).with("puppetlabs").and_return([apache_1])
|
96
|
+
expect(subforge_two).to receive(:search_modules).with("puppetlabs").and_return([apache_2])
|
97
|
+
|
98
|
+
result = multi_forge.search_modules("puppetlabs")
|
99
|
+
|
100
|
+
tags = result.first["tag_list"]
|
101
|
+
expect(tags).to eq ["a", "b", "c"]
|
102
|
+
end
|
103
|
+
|
104
|
+
it "combines the available versions, in order" do
|
105
|
+
apache_3 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "two", "version" => "3", "releases" => [{"version" => "3"}]}
|
106
|
+
apache_1 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "one", "version" => "1", "releases" => [{"version" => "1"}]}
|
107
|
+
apache_2 = { "author" => "puppetlabs", "full_name" => "puppetlabs/apache", "desc" => "two", "version" => "2", "releases" => [{"version" => "2"}]}
|
108
|
+
expect(subforge_one).to receive(:search_modules).with("puppetlabs").and_return([apache_1, apache_3])
|
109
|
+
expect(subforge_two).to receive(:search_modules).with("puppetlabs").and_return([apache_2])
|
110
|
+
|
111
|
+
result = multi_forge.search_modules("puppetlabs")
|
112
|
+
|
113
|
+
tags = result.first["releases"]
|
114
|
+
expect(tags).to eq [ {"version" => "3"}, {"version" => "2"}, {"version" => "1"} ]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
describe "#get_module_buffer" do
|
120
|
+
context "when the module is found in a subforge" do
|
121
|
+
it "returns the module from the first subforge it's found in" do
|
122
|
+
expect(subforge_one).to receive(:get_module_buffer).with("puppetlabs", "apache", "1.0.0").and_return("puppetlabs/apache module: 1.0.0")
|
123
|
+
expect(subforge_two).not_to receive(:get_mo_bufferdule_buffer)
|
124
|
+
|
125
|
+
mod = multi_forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
126
|
+
|
127
|
+
expect(mod).to eq "puppetlabs/apache module: 1.0.0"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when the module is not found in any subforge" do
|
132
|
+
it "raises an error" do
|
133
|
+
expect(subforge_one).to receive(:get_module_buffer).with("puppetlabs", "nonexistant", "1.0.0").and_raise(ModuleNotFound)
|
134
|
+
expect(subforge_two).to receive(:get_module_buffer).with("puppetlabs", "nonexistant", "1.0.0").and_raise(ModuleNotFound)
|
135
|
+
|
136
|
+
expect {
|
137
|
+
multi_forge.get_module_buffer("puppetlabs", "nonexistant", "1.0.0")
|
138
|
+
}.to raise_exception(ModuleNotFound)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "#get_module_metadata" do
|
144
|
+
context "when versions of the module are found in subforges" do
|
145
|
+
it "combines the metadata" do
|
146
|
+
apache_module_metadata_one = {
|
147
|
+
"full_name" => "puppetlabs-apache", "releases" => [{"version"=>"1.0.0"}]
|
148
|
+
}
|
149
|
+
apache_module_metadata_two = {
|
150
|
+
"full_name" => "puppetlabs-apache", "releases" => [{"version"=>"2.0.0"}]
|
151
|
+
}
|
152
|
+
expect(subforge_one).to receive(:get_module_metadata).with("puppetlabs", "apache").and_return(apache_module_metadata_one)
|
153
|
+
expect(subforge_two).to receive(:get_module_metadata).with("puppetlabs", "apache").and_return(apache_module_metadata_two)
|
154
|
+
|
155
|
+
metadata_list = multi_forge.get_module_metadata("puppetlabs", "apache")
|
156
|
+
|
157
|
+
expect(metadata_list).to eq({
|
158
|
+
"full_name" => "puppetlabs-apache",
|
159
|
+
"releases" => [{"version"=>"1.0.0"}, {"version"=>"2.0.0"}]
|
160
|
+
})
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when no versions of the module are found in any subforge" do
|
165
|
+
it "raises an error" do
|
166
|
+
expect(subforge_one).to receive(:get_module_metadata).with("puppetlabs", "apache").and_raise(ModuleNotFound)
|
167
|
+
expect(subforge_two).to receive(:get_module_metadata).with("puppetlabs", "apache").and_raise(ModuleNotFound)
|
168
|
+
|
169
|
+
expect {
|
170
|
+
multi_forge.get_module_metadata("puppetlabs", "apache")
|
171
|
+
}.to raise_exception(ModuleNotFound)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context "when the same version of a module is found in multiple forges" do
|
176
|
+
it "returns the one from the first forge it appears in" do
|
177
|
+
apache_module_metadata_one = {
|
178
|
+
"full_name" => "puppetlabs-apache", "releases" => [{"version"=>"1.0.0", "forge" => "one"}]
|
179
|
+
}
|
180
|
+
apache_module_metadata_two = {
|
181
|
+
"full_name" => "puppetlabs-apache", "releases" => [{"version"=>"1.0.0", "forge" => "two"}]
|
182
|
+
}
|
183
|
+
expect(subforge_one).to receive(:get_module_metadata).with("puppetlabs", "apache").and_return(apache_module_metadata_one)
|
184
|
+
expect(subforge_two).to receive(:get_module_metadata).with("puppetlabs", "apache").and_return(apache_module_metadata_two)
|
185
|
+
|
186
|
+
metadata_list = multi_forge.get_module_metadata("puppetlabs", "apache")
|
187
|
+
|
188
|
+
expect(metadata_list).to eq({
|
189
|
+
"full_name" => "puppetlabs-apache",
|
190
|
+
"releases" => [{"version"=>"1.0.0", "forge"=>"one"}]
|
191
|
+
})
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "#get_module_metadata_with_dependencies" do
|
197
|
+
context "when no versions of the module are found in any subforge" do
|
198
|
+
it "raises an error" do
|
199
|
+
expect(subforge_one).to receive(:get_module_metadata_with_dependencies).with("puppetlabs", "apache", nil).and_raise(ModuleNotFound)
|
200
|
+
expect(subforge_two).to receive(:get_module_metadata_with_dependencies).with("puppetlabs", "apache", nil).and_raise(ModuleNotFound)
|
201
|
+
|
202
|
+
expect {
|
203
|
+
multi_forge.get_module_metadata_with_dependencies("puppetlabs", "apache", nil)
|
204
|
+
}.to raise_error(ModuleNotFound)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "when versions of the module are found in subforges" do
|
209
|
+
it "a merged hash of the metadata" do
|
210
|
+
base_metadata = {
|
211
|
+
"puppetlabs/apache" => [ ],
|
212
|
+
"puppetlabs/stdlib" => [
|
213
|
+
{
|
214
|
+
"version" => "2.4.0",
|
215
|
+
"dependencies" => [ ]
|
216
|
+
}
|
217
|
+
],
|
218
|
+
"puppetlabs/concat" => [
|
219
|
+
{
|
220
|
+
"version" => "1.0.0",
|
221
|
+
"dependencies" => [ ]
|
222
|
+
}
|
223
|
+
]
|
224
|
+
}
|
225
|
+
apache_module_metadata_one = base_metadata.deep_clone.tap do |meta|
|
226
|
+
meta["puppetlabs/apache"] << {
|
227
|
+
"version" => "1",
|
228
|
+
"dependencies" => [
|
229
|
+
[ "puppetlabs/concat", ">= 1.0.0" ],
|
230
|
+
[ "puppetlabs/stdlib", ">= 2.4.0" ]
|
231
|
+
]
|
232
|
+
}
|
233
|
+
end
|
234
|
+
apache_module_metadata_two = base_metadata.deep_clone.tap do |meta|
|
235
|
+
meta["puppetlabs/apache"] << {
|
236
|
+
"version" => "2",
|
237
|
+
"dependencies" => [
|
238
|
+
[ "puppetlabs/concat", ">= 1.0.0" ],
|
239
|
+
[ "puppetlabs/stdlib", ">= 2.4.0" ]
|
240
|
+
]
|
241
|
+
}
|
242
|
+
end
|
243
|
+
expect(subforge_one).to receive(:get_module_metadata_with_dependencies).with("puppetlabs", "apache", nil).and_return(apache_module_metadata_one)
|
244
|
+
expect(subforge_two).to receive(:get_module_metadata_with_dependencies).with("puppetlabs", "apache", nil).and_return(apache_module_metadata_two)
|
245
|
+
|
246
|
+
metadata = multi_forge.get_module_metadata_with_dependencies("puppetlabs", "apache", nil)
|
247
|
+
|
248
|
+
expect(metadata["puppetlabs/apache"]).to eq [
|
249
|
+
{
|
250
|
+
"version"=>"1",
|
251
|
+
"dependencies"=> [["puppetlabs/concat", ">= 1.0.0"], ["puppetlabs/stdlib", ">= 2.4.0"]]
|
252
|
+
},
|
253
|
+
{
|
254
|
+
"version"=>"2",
|
255
|
+
"dependencies"=> [["puppetlabs/concat", ">= 1.0.0"], ["puppetlabs/stdlib", ">= 2.4.0"]]
|
256
|
+
}
|
257
|
+
]
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
context "when the same version of a module is found in multiple forges" do
|
262
|
+
it "favors the one it finds first" do
|
263
|
+
base_metadata = {
|
264
|
+
"puppetlabs/apache" => [ ],
|
265
|
+
"puppetlabs/stdlib" => [
|
266
|
+
{
|
267
|
+
"version" => "2.4.0",
|
268
|
+
"dependencies" => [ ]
|
269
|
+
}
|
270
|
+
],
|
271
|
+
"puppetlabs/concat" => [
|
272
|
+
{
|
273
|
+
"version" => "1.0.0",
|
274
|
+
"dependencies" => [ ]
|
275
|
+
}
|
276
|
+
]
|
277
|
+
}
|
278
|
+
apache_module_metadata_one = base_metadata.deep_clone.tap do |meta|
|
279
|
+
meta["puppetlabs/apache"] << {
|
280
|
+
"version" => "1",
|
281
|
+
"forge" => "1",
|
282
|
+
"dependencies" => [
|
283
|
+
[ "puppetlabs/concat", ">= 1.0.0" ],
|
284
|
+
[ "puppetlabs/stdlib", ">= 2.4.0" ]
|
285
|
+
]
|
286
|
+
}
|
287
|
+
end
|
288
|
+
apache_module_metadata_two = base_metadata.deep_clone.tap do |meta|
|
289
|
+
meta["puppetlabs/apache"] << {
|
290
|
+
"version" => "1",
|
291
|
+
"forge" => "2",
|
292
|
+
"dependencies" => [
|
293
|
+
[ "puppetlabs/concat", ">= 1.0.0" ],
|
294
|
+
[ "puppetlabs/stdlib", ">= 2.4.0" ]
|
295
|
+
]
|
296
|
+
}
|
297
|
+
end
|
298
|
+
expect(subforge_one).to receive(:get_module_metadata_with_dependencies).with("puppetlabs", "apache", nil).and_return(apache_module_metadata_one)
|
299
|
+
expect(subforge_two).to receive(:get_module_metadata_with_dependencies).with("puppetlabs", "apache", nil).and_return(apache_module_metadata_two)
|
300
|
+
|
301
|
+
metadata = multi_forge.get_module_metadata_with_dependencies("puppetlabs", "apache", nil)
|
302
|
+
|
303
|
+
expect(metadata["puppetlabs/apache"]).to eq [
|
304
|
+
{
|
305
|
+
"version"=>"1",
|
306
|
+
"forge"=>"1",
|
307
|
+
"dependencies"=> [["puppetlabs/concat", ">= 1.0.0"], ["puppetlabs/stdlib", ">= 2.4.0"]]
|
308
|
+
},
|
309
|
+
]
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# Puppet Library
|
3
|
+
# Copyright (C) 2014 drrb
|
4
|
+
#
|
5
|
+
# This program is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
|
+
|
18
|
+
require 'spec_helper'
|
19
|
+
|
20
|
+
module PuppetLibrary::Forge
|
21
|
+
describe Proxy do
|
22
|
+
let(:http_client) { double('http_client') }
|
23
|
+
let(:query_cache) { PuppetLibrary::Http::Cache::InMemory.new }
|
24
|
+
let(:download_cache) { PuppetLibrary::Http::Cache::InMemory.new }
|
25
|
+
let(:forge) { Proxy.new("http://puppetforge.example.com", query_cache, download_cache, http_client) }
|
26
|
+
|
27
|
+
describe "url" do
|
28
|
+
it "defaults to HTTP, when protocol not specified" do
|
29
|
+
forge = Proxy.new("forge.puppetlabs.com", query_cache, download_cache, http_client)
|
30
|
+
|
31
|
+
expect(http_client).to receive(:get).with("http:\/\/forge.puppetlabs.com/puppetlabs/apache.json").and_return('{"puppetlabs/apache":[]}')
|
32
|
+
|
33
|
+
forge.get_module_metadata("puppetlabs", "apache")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "copes with a trailing slash" do
|
37
|
+
forge = Proxy.new("forge.puppetlabs.com/", query_cache, download_cache, http_client)
|
38
|
+
|
39
|
+
expect(http_client).to receive(:get).with("http:\/\/forge.puppetlabs.com/puppetlabs/apache.json").and_return('{"puppetlabs/apache":[]}')
|
40
|
+
|
41
|
+
forge.get_module_metadata("puppetlabs", "apache")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#search_modules" do
|
46
|
+
it "forwards the request directly" do
|
47
|
+
search_results = '["a","b","c"]'
|
48
|
+
expect(http_client).to receive(:get).
|
49
|
+
with("http://puppetforge.example.com/modules.json?q=apache").
|
50
|
+
and_return(search_results)
|
51
|
+
|
52
|
+
result = forge.search_modules("apache")
|
53
|
+
expect(result).to eq JSON.parse(search_results)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "caches the results" do
|
57
|
+
search_results = '["a","b","c"]'
|
58
|
+
expect(http_client).to receive(:get).once.
|
59
|
+
with("http://puppetforge.example.com/modules.json?q=apache").
|
60
|
+
and_return(search_results)
|
61
|
+
|
62
|
+
forge.search_modules("apache")
|
63
|
+
forge.search_modules("apache")
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when the query is nil" do
|
67
|
+
it "doesn't forward it as a request parameter" do
|
68
|
+
expect(http_client).to receive(:get).
|
69
|
+
with("http://puppetforge.example.com/modules.json").
|
70
|
+
and_return("[]")
|
71
|
+
|
72
|
+
forge.search_modules(nil)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#get_module_buffer" do
|
78
|
+
context "module version not found" do
|
79
|
+
it "raises an error" do
|
80
|
+
expect(http_client).to receive(:get).
|
81
|
+
with("http://puppetforge.example.com/api/v1/releases.json?module=puppetlabs/apache").
|
82
|
+
and_raise(OpenURI::HTTPError.new("404 Not Found", "Module not found"))
|
83
|
+
|
84
|
+
expect {
|
85
|
+
forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
86
|
+
}.to raise_error ModuleNotFound
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when there is an error downloading the archive" do
|
91
|
+
it "raises an error" do
|
92
|
+
expect(http_client).to receive(:get).
|
93
|
+
with("http://puppetforge.example.com/api/v1/releases.json?module=puppetlabs/apache").
|
94
|
+
and_return('{"puppetlabs/apache":[{"version":"1.0.0","file":"/puppetlabs/apache.tgz","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}')
|
95
|
+
expect(http_client).to receive(:download).
|
96
|
+
with("http://puppetforge.example.com/puppetlabs/apache.tgz").
|
97
|
+
and_raise(OpenURI::HTTPError.new("404 Not Found", "Module not found"))
|
98
|
+
|
99
|
+
expect {
|
100
|
+
forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
101
|
+
}.to raise_error ModuleNotFound
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "when the module is found" do
|
106
|
+
before do
|
107
|
+
allow(http_client).to receive(:get).
|
108
|
+
with("http://puppetforge.example.com/api/v1/releases.json?module=puppetlabs/apache").
|
109
|
+
and_return('{"puppetlabs/apache":[{"version":"1.0.0","file":"/puppetlabs/apache.tgz","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}')
|
110
|
+
end
|
111
|
+
|
112
|
+
it "returns a buffer containing the module archive" do
|
113
|
+
file_buffer = "file buffer"
|
114
|
+
expect(http_client).to receive(:download).
|
115
|
+
with("http://puppetforge.example.com/puppetlabs/apache.tgz").
|
116
|
+
and_return(file_buffer)
|
117
|
+
|
118
|
+
result = forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
119
|
+
expect(result).to eq file_buffer
|
120
|
+
end
|
121
|
+
|
122
|
+
it "caches the download" do
|
123
|
+
file_buffer = "file buffer"
|
124
|
+
expect(http_client).to receive(:download).once.
|
125
|
+
with("http://puppetforge.example.com/puppetlabs/apache.tgz").
|
126
|
+
and_return(file_buffer)
|
127
|
+
|
128
|
+
forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
129
|
+
forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe "#get_module_metadata" do
|
135
|
+
context "when the module doesn't exist" do
|
136
|
+
it "raises an error" do
|
137
|
+
expect(http_client).to receive(:get).
|
138
|
+
with("http://puppetforge.example.com/puppetlabs/apache.json").
|
139
|
+
and_raise(OpenURI::HTTPError.new("404 Not Found", "Module not found"))
|
140
|
+
|
141
|
+
expect {
|
142
|
+
forge.get_module_metadata("puppetlabs", "apache")
|
143
|
+
}.to raise_error(ModuleNotFound)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "when versions of the module exist" do
|
148
|
+
it "forwards the query directly" do
|
149
|
+
response = '{"puppetlabs/apache":[{"version":"1.0.0","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}'
|
150
|
+
expect(http_client).to receive(:get).
|
151
|
+
with("http://puppetforge.example.com/puppetlabs/apache.json").
|
152
|
+
and_return(response)
|
153
|
+
|
154
|
+
metadata = forge.get_module_metadata("puppetlabs", "apache")
|
155
|
+
expect(metadata).to eq JSON.parse(response)
|
156
|
+
end
|
157
|
+
|
158
|
+
it "caches requests" do
|
159
|
+
expect(http_client).to receive(:get).once.
|
160
|
+
with("http://puppetforge.example.com/puppetlabs/apache.json").
|
161
|
+
and_return('{}')
|
162
|
+
|
163
|
+
forge.get_module_metadata("puppetlabs", "apache")
|
164
|
+
forge.get_module_metadata("puppetlabs", "apache")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
describe "#get_module_metadata_with_dependencies" do
|
170
|
+
context "the module isn't found" do
|
171
|
+
it "raises an error" do
|
172
|
+
expect(http_client).to receive(:get).
|
173
|
+
with("http://puppetforge.example.com/api/v1/releases.json?module=nonexistant/nonexistant").
|
174
|
+
and_raise(OpenURI::HTTPError.new("410 Gone", "Module not found"))
|
175
|
+
|
176
|
+
expect {
|
177
|
+
forge.get_module_metadata_with_dependencies("nonexistant", "nonexistant", nil)
|
178
|
+
}.to raise_error ModuleNotFound
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when the module is found" do
|
183
|
+
it "forwards the request directly" do
|
184
|
+
response = '{"puppetlabs/apache":[{"version":"1.0.0","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}'
|
185
|
+
expect(http_client).to receive(:get).
|
186
|
+
with("http://puppetforge.example.com/api/v1/releases.json?module=puppetlabs/apache&version=1.0.0").
|
187
|
+
and_return(response)
|
188
|
+
|
189
|
+
result = forge.get_module_metadata_with_dependencies("puppetlabs", "apache", "1.0.0")
|
190
|
+
|
191
|
+
expect(result).to eq JSON.parse(response)
|
192
|
+
end
|
193
|
+
|
194
|
+
it "caches the result" do
|
195
|
+
response = '{"puppetlabs/apache":[{"version":"1.0.0","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}'
|
196
|
+
expect(http_client).to receive(:get).once.
|
197
|
+
with("http://puppetforge.example.com/api/v1/releases.json?module=puppetlabs/apache&version=1.0.0").
|
198
|
+
and_return(response)
|
199
|
+
|
200
|
+
forge.get_module_metadata_with_dependencies("puppetlabs", "apache", "1.0.0")
|
201
|
+
forge.get_module_metadata_with_dependencies("puppetlabs", "apache", "1.0.0")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
data/spec/puppet_library_spec.rb
CHANGED
@@ -19,14 +19,9 @@ require 'spec_helper'
|
|
19
19
|
|
20
20
|
module PuppetLibrary
|
21
21
|
describe PuppetLibrary do
|
22
|
-
let(:module_repo) do
|
23
|
-
module_repo = double(ModuleRepo::Multi)
|
24
|
-
allow(ModuleRepo::Multi).to receive(:new).and_return(module_repo)
|
25
|
-
return module_repo
|
26
|
-
end
|
27
22
|
let(:forge) do
|
28
|
-
forge = double(Forge)
|
29
|
-
allow(Forge).to receive(:new).and_return(forge)
|
23
|
+
forge = double(Forge::Multi).as_null_object
|
24
|
+
allow(Forge::Multi).to receive(:new).and_return(forge)
|
30
25
|
return forge
|
31
26
|
end
|
32
27
|
let(:server) do
|
@@ -91,13 +86,12 @@ module PuppetLibrary
|
|
91
86
|
end
|
92
87
|
|
93
88
|
context "when using --proxy option" do
|
94
|
-
it "adds a proxy module
|
89
|
+
it "adds a proxy module forge for each option specified" do
|
95
90
|
proxy1 = double('proxy1')
|
96
91
|
proxy2 = double('proxy2')
|
97
|
-
expect(
|
98
|
-
expect(
|
99
|
-
expect(
|
100
|
-
expect(module_repo).to receive(:add_repo).twice
|
92
|
+
expect(Forge::Proxy).to receive(:new).with("http://forge1.example.com").and_return(proxy1)
|
93
|
+
expect(Forge::Proxy).to receive(:new).with("http://forge2.example.com").and_return(proxy2)
|
94
|
+
expect(forge).to receive(:add_forge).twice
|
101
95
|
expect(Rack::Server).to receive(:start).with(default_options)
|
102
96
|
|
103
97
|
library.go(["--proxy", "http://forge1.example.com", "--proxy", "http://forge2.example.com"])
|
@@ -105,14 +99,13 @@ module PuppetLibrary
|
|
105
99
|
end
|
106
100
|
|
107
101
|
context "when using --module-dir option" do
|
108
|
-
it "adds a
|
109
|
-
|
110
|
-
|
111
|
-
expect(
|
112
|
-
expect(
|
113
|
-
expect(
|
114
|
-
expect(
|
115
|
-
expect(module_repo).to receive(:add_repo).with(directory_repo_2)
|
102
|
+
it "adds a directory forge to the server for each module directory" do
|
103
|
+
directory_forge_1 = double("directory_forge_1")
|
104
|
+
directory_forge_2 = double("directory_forge_2")
|
105
|
+
expect(Forge::Directory).to receive(:new).with("dir1").and_return(directory_forge_1)
|
106
|
+
expect(Forge::Directory).to receive(:new).with("dir2").and_return(directory_forge_2)
|
107
|
+
expect(forge).to receive(:add_forge).with(directory_forge_1)
|
108
|
+
expect(forge).to receive(:add_forge).with(directory_forge_2)
|
116
109
|
expect(Rack::Server).to receive(:start).with(default_options)
|
117
110
|
|
118
111
|
library.go(["--module-dir", "dir1", "--module-dir", "dir2"])
|
@@ -122,9 +115,8 @@ module PuppetLibrary
|
|
122
115
|
context "when no proxy URLs or module directories specified" do
|
123
116
|
it "proxies the Puppet Forge" do
|
124
117
|
proxy = double("proxy")
|
125
|
-
expect(
|
126
|
-
expect(
|
127
|
-
expect(module_repo).to receive(:add_repo).with(proxy)
|
118
|
+
expect(Forge::Proxy).to receive(:new).with("http://forge.puppetlabs.com").and_return(proxy)
|
119
|
+
expect(forge).to receive(:add_forge).with(proxy)
|
128
120
|
expect(Rack::Server).to receive(:start).with(default_options)
|
129
121
|
|
130
122
|
library.go([])
|
@@ -135,8 +127,8 @@ module PuppetLibrary
|
|
135
127
|
expect(log).to receive(:puts).with(/Port: default/)
|
136
128
|
expect(log).to receive(:puts).with(/Host: default/)
|
137
129
|
expect(log).to receive(:puts).with(/Server: default/)
|
138
|
-
expect(log).to receive(:puts).with(/
|
139
|
-
expect(log).to receive(:puts).with(/- PuppetLibrary::
|
130
|
+
expect(log).to receive(:puts).with(/Forges:/)
|
131
|
+
expect(log).to receive(:puts).with(/- PuppetLibrary::Forge::Directory: \.\/modules/)
|
140
132
|
library.go(["--module-dir", "./modules"])
|
141
133
|
end
|
142
134
|
end
|
data/spec/server_spec.rb
CHANGED
@@ -28,6 +28,29 @@ module PuppetLibrary
|
|
28
28
|
Server.new(forge)
|
29
29
|
end
|
30
30
|
|
31
|
+
describe "GET /modules.json" do
|
32
|
+
it "renders the search result as JSON" do
|
33
|
+
search_results = [
|
34
|
+
{
|
35
|
+
"author" => "puppetlabs",
|
36
|
+
"name" => "apache",
|
37
|
+
"tag_list" => ["apache", "httpd"],
|
38
|
+
"releases" => [{"version"=>"0.0.1"}, {"version"=>"0.0.2"}],
|
39
|
+
"full_name" => "puppetlabs/apache",
|
40
|
+
"version" => "0.0.2",
|
41
|
+
"project_url" => "http://github.com/puppetlabs/puppetlabs-apache",
|
42
|
+
"desc" => "Puppet module for Apache"
|
43
|
+
}
|
44
|
+
]
|
45
|
+
expect(forge).to receive(:search_modules).with("apache").and_return(search_results)
|
46
|
+
|
47
|
+
get "/modules.json?q=apache"
|
48
|
+
|
49
|
+
expect(last_response.body).to eq search_results.to_json
|
50
|
+
expect(last_response).to be_ok
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
31
54
|
describe "GET /modules/<author>-<module>-<version>.tar.gz" do
|
32
55
|
context "when the module is on the server" do
|
33
56
|
it "serves the module" do
|
@@ -45,7 +68,7 @@ module PuppetLibrary
|
|
45
68
|
|
46
69
|
context "when the module is not on the server" do
|
47
70
|
it "returns an error" do
|
48
|
-
expect(forge).to receive(:get_module_buffer).with("puppetlabs", "apache", "1.0.0").and_raise(ModuleNotFound)
|
71
|
+
expect(forge).to receive(:get_module_buffer).with("puppetlabs", "apache", "1.0.0").and_raise(Forge::ModuleNotFound)
|
49
72
|
|
50
73
|
get "/modules/puppetlabs-apache-1.0.0.tar.gz"
|
51
74
|
|
@@ -77,7 +100,7 @@ module PuppetLibrary
|
|
77
100
|
|
78
101
|
context "when no modules found" do
|
79
102
|
it "returns an error" do
|
80
|
-
expect(forge).to receive(:get_module_metadata).with("nonexistant", "nonexistant").and_raise(ModuleNotFound)
|
103
|
+
expect(forge).to receive(:get_module_metadata).with("nonexistant", "nonexistant").and_raise(Forge::ModuleNotFound)
|
81
104
|
|
82
105
|
get "/nonexistant/nonexistant.json"
|
83
106
|
|
@@ -125,7 +148,7 @@ module PuppetLibrary
|
|
125
148
|
|
126
149
|
context "when the module can't be found" do
|
127
150
|
it "returns an error" do
|
128
|
-
expect(forge).to receive(:get_module_metadata_with_dependencies).with("nonexistant", "nonexistant", nil).and_raise(ModuleNotFound)
|
151
|
+
expect(forge).to receive(:get_module_metadata_with_dependencies).with("nonexistant", "nonexistant", nil).and_raise(Forge::ModuleNotFound)
|
129
152
|
|
130
153
|
get "/api/v1/releases.json?module=nonexistant/nonexistant"
|
131
154
|
|