berkshelf 5.6.5 → 6.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33e876c1bf17b5d4b7f9476c516e1650ee94ec06
4
- data.tar.gz: 60ec3493e1c2588b9d57a1b9955b9835e41dcc0c
3
+ metadata.gz: c31585edab49dfddf07f23af1d5d14dd998bd856
4
+ data.tar.gz: f9ce9ff33e601797b53c0355da9464c230894130
5
5
  SHA512:
6
- metadata.gz: 76b01e75c80bd1babc5cc47713f7d24b61853eaa64657b806ce5a5b1eb7139da9d90529d4837d570f3ae2ce56f7674ec91b0c86e464b13e7d33838b9895e8a74
7
- data.tar.gz: 47b2910e768383ca4ed83d6e9bf1bfa4a539b8e4688484549c11d6f497b7ddfd63f8bdd004ec913383076c40de237d419fc4dd5e1a425e6e1ed893c3272a7c0a
6
+ metadata.gz: 899e6e73d3e9431e4662b07c3b118b99f60fd970dd54f3bc963bdc8e0e5d4a4379736ad4ea183b5f2e9e5eb924c0f66dc8ad946b6bc11aef837e5865e0d4bfea
7
+ data.tar.gz: 99a42e0ba55c5daf4909743b31c9bf2b80a75ba73c112e0e987ca3f255c4876760ce3bb47974c2360b16e980d69f3fc846a9a11af81f02f2f477a0469c2a16aa
@@ -1,14 +1,22 @@
1
1
  # Change Log
2
2
 
3
- ## [5.6.5](https://github.com/berkshelf/berkshelf/tree/5.6.4) (2017-05-04)
4
- [Full Changelog](https://github.com/berkshelf/berkshelf/compare/v5.6.4...5.6.5)
3
+ ## [6.0.0](https://github.com/berkshelf/berkshelf/tree/6.0.0) (2017-05-17)
4
+ [Full Changelog](https://github.com/berkshelf/berkshelf/compare/v5.6.5...6.0.0)
5
5
 
6
6
  **Merged pull requests:**
7
7
 
8
- - Handle Windows backslashes in trusted_certs path [\#1689](https://github.com/berkshelf/berkshelf/pull/1689) ([jeremymv2](https://github.com/jeremymv2))
8
+ - Minor refactor on the default artifactory options and support artifactory\_api\_key in knife.rb [\#1691](https://github.com/berkshelf/berkshelf/pull/1691) ([coderanger](https://github.com/coderanger))
9
+ - Artifactory support [\#1690](https://github.com/berkshelf/berkshelf/pull/1690) ([coderanger](https://github.com/coderanger))
9
10
 
10
- ## [5.6.4](https://github.com/berkshelf/berkshelf/tree/5.6.4) (2017-03-14)
11
- [Full Changelog](https://github.com/berkshelf/berkshelf/compare/v5.6.3...5.6.4)
11
+ ## [v5.6.5](https://github.com/berkshelf/berkshelf/tree/v5.6.5) (2017-05-04)
12
+ [Full Changelog](https://github.com/berkshelf/berkshelf/compare/v5.6.4...v5.6.5)
13
+
14
+ **Merged pull requests:**
15
+
16
+ - handle Windows backslashes in trusted\_certs path [\#1689](https://github.com/berkshelf/berkshelf/pull/1689) ([jeremymv2](https://github.com/jeremymv2))
17
+
18
+ ## [v5.6.4](https://github.com/berkshelf/berkshelf/tree/v5.6.4) (2017-03-14)
19
+ [Full Changelog](https://github.com/berkshelf/berkshelf/compare/v5.6.3...v5.6.4)
12
20
 
13
21
  **Merged pull requests:**
14
22
 
@@ -1426,4 +1434,4 @@
1426
1434
 
1427
1435
 
1428
1436
 
1429
- \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
1437
+ \* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
data/Gemfile CHANGED
@@ -45,6 +45,7 @@ group :development do
45
45
  gem "dep_selector", ">= 1.0"
46
46
  gem "fuubar", ">= 2.0"
47
47
  gem "rspec", ">= 3.0"
48
+ gem "rspec-its", ">= 1.2"
48
49
  gem "test-kitchen", ">= 1.2"
49
50
  gem "webmock", ">= 1.11"
50
51
  gem "yard", ">= 0.8"
@@ -20,7 +20,7 @@ GIT
20
20
  PATH
21
21
  remote: .
22
22
  specs:
23
- berkshelf (5.6.5)
23
+ berkshelf (6.0.0)
24
24
  addressable (~> 2.3, >= 2.3.4)
25
25
  berkshelf-api-client (>= 2.0.2, < 4.0)
26
26
  buff-config (~> 2.0)
@@ -40,9 +40,8 @@ PATH
40
40
  GEM
41
41
  remote: https://rubygems.org/
42
42
  specs:
43
- activesupport (4.2.7.1)
43
+ activesupport (4.2.8)
44
44
  i18n (~> 0.7)
45
- json (~> 1.7, >= 1.7.7)
46
45
  minitest (~> 5.1)
47
46
  thread_safe (~> 0.3, >= 0.3.4)
48
47
  tzinfo (~> 1.1)
@@ -50,7 +49,7 @@ GEM
50
49
  public_suffix (~> 2.0, >= 2.0.2)
51
50
  archive (0.0.6)
52
51
  ffi (~> 1.9.3)
53
- artifactory (2.6.0)
52
+ artifactory (2.8.1)
54
53
  aruba (0.14.2)
55
54
  childprocess (~> 0.5.6)
56
55
  contracts (~> 0.9)
@@ -85,7 +84,7 @@ GEM
85
84
  fuzzyurl
86
85
  mixlib-config (~> 2.0)
87
86
  mixlib-shellout (~> 2.0)
88
- chef-zero (5.3.0)
87
+ chef-zero (13.0.0)
89
88
  ffi-yajl (~> 2.2)
90
89
  hashie (>= 2.0, < 4.0)
91
90
  mixlib-log (~> 1.3)
@@ -97,7 +96,7 @@ GEM
97
96
  coderay (1.1.1)
98
97
  coercible (1.0.0)
99
98
  descendants_tracker (~> 0.0.1)
100
- contracts (0.14.0)
99
+ contracts (0.16.0)
101
100
  coolline (0.5.0)
102
101
  unicode_utils (~> 1.4)
103
102
  crack (0.4.3)
@@ -120,7 +119,7 @@ GEM
120
119
  descendants_tracker (0.0.4)
121
120
  thread_safe (~> 0.3, >= 0.3.1)
122
121
  diff-lcs (1.3)
123
- domain_name (0.5.20161129)
122
+ domain_name (0.5.20170404)
124
123
  unf (>= 0.0.5, < 1.0.0)
125
124
  equalizer (0.0.11)
126
125
  erubis (2.7.0)
@@ -128,7 +127,7 @@ GEM
128
127
  multipart-post (>= 1.2, < 3)
129
128
  faraday-http-cache (2.0.0)
130
129
  faraday (~> 0.8)
131
- ffi (1.9.17)
130
+ ffi (1.9.18)
132
131
  ffi-yajl (2.3.0)
133
132
  libyajl2 (~> 1.2)
134
133
  formatador (0.2.5)
@@ -136,7 +135,7 @@ GEM
136
135
  rspec-core (~> 3.0)
137
136
  ruby-progressbar (~> 1.4)
138
137
  fuzzyurl (0.9.0)
139
- gherkin (4.0.0)
138
+ gherkin (4.1.3)
140
139
  github_changelog_generator (1.14.3)
141
140
  activesupport
142
141
  faraday-http-cache
@@ -145,13 +144,13 @@ GEM
145
144
  rainbow (>= 2.1)
146
145
  rake (>= 10.0)
147
146
  retriable (~> 2.1)
148
- grape (0.19.1)
147
+ grape (0.19.2)
149
148
  activesupport
150
149
  builder
151
150
  hashie (>= 2.1.0)
152
151
  multi_json (>= 1.3.2)
153
152
  multi_xml (>= 0.5.2)
154
- mustermann-grape (~> 0.4.0)
153
+ mustermann-grape (~> 1.0.0)
155
154
  rack (>= 1.3.0)
156
155
  rack-accept
157
156
  virtus (>= 1.0.0)
@@ -177,22 +176,22 @@ GEM
177
176
  guard (~> 2.1)
178
177
  guard-compat (~> 1.1)
179
178
  rspec (>= 2.99.0, < 4.0)
180
- hashdiff (0.3.2)
179
+ hashdiff (0.3.4)
181
180
  hashie (3.5.5)
182
181
  hitimes (1.2.4)
183
- http (2.2.0)
182
+ http (2.2.2)
184
183
  addressable (~> 2.3)
185
184
  http-cookie (~> 1.0)
186
185
  http-form_data (~> 1.0.1)
187
186
  http_parser.rb (~> 0.6.0)
188
187
  http-cookie (1.0.3)
189
188
  domain_name (~> 0.5)
190
- http-form_data (1.0.1)
189
+ http-form_data (1.0.2)
191
190
  http_parser.rb (0.6.0)
192
191
  httpclient (2.8.3)
193
- i18n (0.8.0)
192
+ i18n (0.8.1)
194
193
  ice_nine (0.11.2)
195
- json (1.8.6)
194
+ json (2.1.0)
196
195
  libnotify (0.8.4)
197
196
  ffi (>= 1.0.11)
198
197
  libyajl2 (1.2.0)
@@ -200,10 +199,10 @@ GEM
200
199
  rb-fsevent (~> 0.9, >= 0.9.4)
201
200
  rb-inotify (~> 0.9, >= 0.9.7)
202
201
  ruby_dep (~> 1.2)
203
- lumberjack (1.0.11)
202
+ lumberjack (1.0.12)
204
203
  method_source (0.8.2)
205
204
  minitar (0.6.1)
206
- minitest (5.10.1)
205
+ minitest (5.10.2)
207
206
  mixlib-archive (0.4.1)
208
207
  mixlib-log
209
208
  mixlib-authentication (1.4.1)
@@ -218,19 +217,18 @@ GEM
218
217
  mixlib-shellout (2.2.7)
219
218
  mixlib-versioning (1.1.0)
220
219
  molinillo (0.5.7)
221
- msgpack (1.0.3)
220
+ msgpack (1.1.0)
222
221
  multi_json (1.12.1)
223
222
  multi_test (0.1.2)
224
223
  multi_xml (0.6.0)
225
224
  multipart-post (2.0.0)
226
- mustermann (0.4.0)
227
- tool (~> 0.2)
228
- mustermann-grape (0.4.0)
229
- mustermann (= 0.4.0)
225
+ mustermann (1.0.0)
226
+ mustermann-grape (1.0.0)
227
+ mustermann (~> 1.0.0)
230
228
  nenv (0.3.0)
231
229
  net-scp (1.2.1)
232
230
  net-ssh (>= 2.6.5)
233
- net-ssh (4.0.1)
231
+ net-ssh (4.1.0)
234
232
  net-ssh-gateway (1.3.0)
235
233
  net-ssh (>= 2.6.5)
236
234
  nio4r (2.0.0)
@@ -244,10 +242,11 @@ GEM
244
242
  method_source (~> 0.8.1)
245
243
  slop (~> 3.4)
246
244
  public_suffix (2.0.5)
247
- rack (2.0.1)
245
+ rack (2.0.3)
248
246
  rack-accept (0.4.5)
249
247
  rack (>= 0.4)
250
- rainbow (2.2.1)
248
+ rainbow (2.2.2)
249
+ rake
251
250
  rake (12.0.0)
252
251
  rb-fsevent (0.9.8)
253
252
  rb-inotify (0.9.8)
@@ -279,19 +278,22 @@ GEM
279
278
  retryable (~> 2.0)
280
279
  semverse (~> 2.0)
281
280
  varia_model (~> 0.6)
282
- rspec (3.5.0)
283
- rspec-core (~> 3.5.0)
284
- rspec-expectations (~> 3.5.0)
285
- rspec-mocks (~> 3.5.0)
286
- rspec-core (3.5.4)
287
- rspec-support (~> 3.5.0)
288
- rspec-expectations (3.5.0)
281
+ rspec (3.6.0)
282
+ rspec-core (~> 3.6.0)
283
+ rspec-expectations (~> 3.6.0)
284
+ rspec-mocks (~> 3.6.0)
285
+ rspec-core (3.6.0)
286
+ rspec-support (~> 3.6.0)
287
+ rspec-expectations (3.6.0)
289
288
  diff-lcs (>= 1.2.0, < 2.0)
290
- rspec-support (~> 3.5.0)
291
- rspec-mocks (3.5.0)
289
+ rspec-support (~> 3.6.0)
290
+ rspec-its (1.2.0)
291
+ rspec-core (>= 3.0.0)
292
+ rspec-expectations (>= 3.0.0)
293
+ rspec-mocks (3.6.0)
292
294
  diff-lcs (>= 1.2.0, < 2.0)
293
- rspec-support (~> 3.5.0)
294
- rspec-support (3.5.0)
295
+ rspec-support (~> 3.6.0)
296
+ rspec-support (3.6.0)
295
297
  ruby-progressbar (1.8.1)
296
298
  ruby_dep (1.5.0)
297
299
  safe_yaml (1.0.4)
@@ -305,24 +307,23 @@ GEM
305
307
  molinillo (>= 0.5)
306
308
  semverse (>= 1.1, < 3.0)
307
309
  terminal-notifier-guard (1.5.3)
308
- test-kitchen (1.15.0)
310
+ test-kitchen (1.16.0)
309
311
  mixlib-install (>= 1.2, < 3.0)
310
312
  mixlib-shellout (>= 1.2, < 3.0)
311
313
  net-scp (~> 1.1)
312
314
  net-ssh (>= 2.9, < 5.0)
313
315
  net-ssh-gateway (~> 1.2)
314
316
  safe_yaml (~> 1.0)
315
- thor (~> 0.18)
317
+ thor (~> 0.19, < 0.19.2)
316
318
  thor (0.19.1)
317
- thread_safe (0.3.5)
319
+ thread_safe (0.3.6)
318
320
  timers (4.0.4)
319
321
  hitimes
320
- tool (0.2.3)
321
- tzinfo (1.2.2)
322
+ tzinfo (1.2.3)
322
323
  thread_safe (~> 0.1)
323
324
  unf (0.1.4)
324
325
  unf_ext
325
- unf_ext (0.0.7.2)
326
+ unf_ext (0.0.7.4)
326
327
  unicode_utils (1.4.0)
327
328
  uuidtools (2.1.5)
328
329
  varia_model (0.6.0)
@@ -334,7 +335,7 @@ GEM
334
335
  descendants_tracker (~> 0.0, >= 0.0.3)
335
336
  equalizer (~> 0.0, >= 0.0.9)
336
337
  wdm (0.1.1)
337
- webmock (2.3.2)
338
+ webmock (3.0.1)
338
339
  addressable (>= 2.3.6)
339
340
  crack (>= 0.3.2)
340
341
  hashdiff
@@ -342,7 +343,7 @@ GEM
342
343
  websocket-extensions (>= 0.1.0)
343
344
  websocket-extensions (0.1.2)
344
345
  win32console (1.3.2)
345
- yard (0.9.8)
346
+ yard (0.9.9)
346
347
 
347
348
  PLATFORMS
348
349
  ruby
@@ -368,6 +369,7 @@ DEPENDENCIES
368
369
  rb-inotify
369
370
  rb-notifu (>= 0.0.4)
370
371
  rspec (>= 3.0)
372
+ rspec-its (>= 1.2)
371
373
  terminal-notifier-guard (~> 1.5.3)
372
374
  test-kitchen (>= 1.2)
373
375
  wdm
@@ -27,7 +27,7 @@ Gem::Specification.new do |s|
27
27
  s.name = "berkshelf"
28
28
  s.require_paths = ["lib"]
29
29
  s.version = Berkshelf::VERSION
30
- s.required_ruby_version = ">= 2.2.0"
30
+ s.required_ruby_version = ">= 2.3.3"
31
31
  s.required_rubygems_version = ">= 2.0.0"
32
32
 
33
33
  s.add_dependency "addressable", "~> 2.3", ">= 2.3.4"
@@ -0,0 +1,70 @@
1
+ Feature: Installing cookbooks from an Artifactory server
2
+ This integration test uses some environment variables to configure which
3
+ Artifactory server to talk to, as there is no ArtifactoryZero to test against.
4
+ If those aren't present, we skip the tests.
5
+
6
+ $TEST_BERKSHELF_ARTIFACTORY - URL to the Chef virtual repository.
7
+ $TEST_BERKSHELF_ARTIFACTORY_API_KEY - API key to use.
8
+
9
+ Scenario: when the cookbook exists
10
+ Given I have a Berksfile pointing at an authenticated Artifactory server with:
11
+ """
12
+ cookbook 'poise', '2.7.2'
13
+ """
14
+ When I successfully run `berks install`
15
+ Then the output should contain:
16
+ """
17
+ Installing poise (2.7.2)
18
+ """
19
+ And the cookbook store should have the cookbooks:
20
+ | poise | 2.7.2 |
21
+
22
+ Scenario: when the cookbook does not exist
23
+ Given I have a Berksfile pointing at an authenticated Artifactory server with:
24
+ """
25
+ cookbook '1234567890'
26
+ """
27
+ When I run `berks install`
28
+ Then the output should contain:
29
+ """
30
+ Unable to find a solution for demands: 1234567890 (>= 0.0.0)
31
+ """
32
+ And the exit status should be "NoSolutionError"
33
+
34
+ Scenario: when the cookbook exists, but the version does not
35
+ Given I have a Berksfile pointing at an authenticated Artifactory server with:
36
+ """
37
+ cookbook 'poise', '0.0.0'
38
+ """
39
+ When I run `berks install`
40
+ Then the output should contain:
41
+ """
42
+ Unable to find a solution for demands: poise (= 0.0.0)
43
+ """
44
+ And the exit status should be "NoSolutionError"
45
+
46
+ Scenario: when the API key is not present:
47
+ Given I have a Berksfile pointing at an Artifactory server with:
48
+ """
49
+ cookbook 'poise'
50
+ """
51
+ When I run `berks install`
52
+ Then the output should contain:
53
+ """
54
+ Unable to find a solution for demands: poise (>= 0.0.0)
55
+ """
56
+ And the exit status should be "NoSolutionError"
57
+
58
+ Scenario: when the API key is given in $ARTIFACTORY_API_KEY:
59
+ Given I have a Berksfile pointing at an Artifactory server with:
60
+ """
61
+ cookbook 'poise', '2.7.2'
62
+ """
63
+ And the environment variable ARTIFACTORY_API_KEY is $TEST_BERKSHELF_ARTIFACTORY_API_KEY
64
+ When I successfully run `berks install`
65
+ Then the output should contain:
66
+ """
67
+ Installing poise (2.7.2)
68
+ """
69
+ And the cookbook store should have the cookbooks:
70
+ | poise | 2.7.2 |
@@ -37,3 +37,18 @@ Given /^I have a Berksfile at "(.+)" pointing at the local Berkshelf API with:$/
37
37
  """
38
38
  }
39
39
  end
40
+
41
+ Given /I have a Berksfile pointing at an( authenticated)? Artifactory server with:/ do |authenticated, content|
42
+ if ENV['TEST_BERKSHELF_ARTIFACTORY']
43
+ steps %Q{
44
+ Given a file named "Berksfile" with:
45
+ """
46
+ source artifactory: '#{ENV['TEST_BERKSHELF_ARTIFACTORY']}'#{authenticated ? ", api_key: '#{ENV['TEST_BERKSHELF_ARTIFACTORY_API_KEY']}'" : ''}
47
+
48
+ #{content}
49
+ """
50
+ }
51
+ else
52
+ skip_this_scenario
53
+ end
54
+ end
@@ -5,3 +5,7 @@ end
5
5
  Given /^the environment variable (.+) is "(.+)"$/ do |variable, value|
6
6
  set_environment_variable(variable, value)
7
7
  end
8
+
9
+ Given /^the environment variable (.+) is \$TEST_BERKSHELF_ARTIFACTORY_API_KEY$/ do |variable|
10
+ set_environment_variable(variable, ENV['TEST_BERKSHELF_ARTIFACTORY_API_KEY'])
11
+ end
@@ -44,7 +44,7 @@ Then /^the cookbook store should have the cookbooks:$/ do |cookbooks|
44
44
  cookbooks.raw.each do |name, version|
45
45
  expect(cookbook_store.storage_path).to have_structure {
46
46
  directory "#{name}-#{version}" do
47
- file "metadata.rb" do
47
+ file "metadata.{rb,json}" do
48
48
  contains version
49
49
  end
50
50
  end
@@ -56,7 +56,7 @@ Then /^the cookbook store should have the git cookbooks:$/ do |cookbooks|
56
56
  cookbooks.raw.each do |name, version, sha1|
57
57
  expect(cookbook_store.storage_path).to have_structure {
58
58
  directory "#{name}-#{sha1}" do
59
- file "metadata.rb" do
59
+ file "metadata.{rb,json}" do
60
60
  contains version
61
61
  end
62
62
  end
@@ -14,10 +14,16 @@ class Hash
14
14
  end
15
15
  end
16
16
 
17
+ # Pending Ridley allowing newer Faraday and Celluloid.
18
+ def clean_json_output(output)
19
+ output.gsub(/^.+warning: constant ::Fixnum is deprecated$/, '') \
20
+ .gsub(/^.*forwarding to private method Celluloid::PoolManager#url_prefix$/, '')
21
+ end
22
+
17
23
  Then /^the output should contain JSON:$/ do |data|
18
24
  parsed = ERB.new(data).result
19
25
  target = JSON.pretty_generate(JSON.parse(parsed).sort_by_key)
20
- actual = JSON.pretty_generate(JSON.parse(all_commands.map { |c| c.output }.join("\n")).sort_by_key)
26
+ actual = JSON.pretty_generate(JSON.parse(all_commands.map { |c| clean_json_output(c.output) }.join("\n")).sort_by_key)
21
27
 
22
28
  expect(actual).to eq(target)
23
29
  end
@@ -191,11 +191,15 @@ module Berkshelf
191
191
  # @param [String] api_url
192
192
  # url for the api to add
193
193
  #
194
+ # @param [Hash] options
195
+ # extra source options
196
+ #
194
197
  # @raise [InvalidSourceURI]
195
198
  #
196
199
  # @return [Array<Source>]
197
- def source(api_url)
198
- @sources[api_url] = Source.new(api_url)
200
+ def source(api_url, **options)
201
+ source = Source.new(api_url, **options)
202
+ @sources[source.uri.to_s] = source
199
203
  end
200
204
  expose :source
201
205
 
@@ -115,6 +115,11 @@ module Berkshelf
115
115
  def find(name, version)
116
116
  response = get("cookbooks/#{name}/versions/#{self.class.uri_escape_version(version)}")
117
117
 
118
+ # Artifactory responds with a 200 and blank body for unknown cookbooks.
119
+ if response.status == 200 && response.body.to_s == ''
120
+ response.env.status = 404
121
+ end
122
+
118
123
  case response.status
119
124
  when (200..299)
120
125
  response.body
@@ -131,6 +136,11 @@ module Berkshelf
131
136
  def latest_version(name)
132
137
  response = get("cookbooks/#{name}")
133
138
 
139
+ # Artifactory responds with a 200 and blank body for unknown cookbooks.
140
+ if response.status == 200 && response.body.to_s == ''
141
+ response.env.status = 404
142
+ end
143
+
134
144
  case response.status
135
145
  when (200..299)
136
146
  self.class.version_from_uri response.body["latest_version"]
@@ -63,17 +63,18 @@ module Berkshelf
63
63
 
64
64
  case remote_cookbook.location_type
65
65
  when :opscode, :supermarket
66
- CommunityREST.new(remote_cookbook.location_path).download(name, version)
66
+ options = {}
67
+ if source.type == :artifactory
68
+ options[:headers] = {'X-Jfrog-Art-Api' => source.options[:api_key]}
69
+ end
70
+ CommunityREST.new(remote_cookbook.location_path, options).download(name, version)
67
71
  when :chef_server
68
72
  # @todo Dynamically get credentials for remote_cookbook.location_path
69
- ssl_options = { verify: Berkshelf::Config.instance.ssl.verify }
70
- ssl_options[:cert_store] = ssl_policy.store if ssl_policy.store
71
-
72
73
  credentials = {
73
74
  server_url: remote_cookbook.location_path,
74
- client_name: Berkshelf::Config.instance.chef.node_name,
75
- client_key: Berkshelf::Config.instance.chef.client_key,
76
- ssl: ssl_options,
75
+ client_name: source.options[:client_name] || Berkshelf::Config.instance.chef.node_name,
76
+ client_key: source.options[:client_key] || Berkshelf::Config.instance.chef.client_key,
77
+ ssl: source.options[:ssl],
77
78
  }
78
79
  # @todo Something scary going on here - getting an instance of Kitchen::Logger from test-kitchen
79
80
  # https://github.com/opscode/test-kitchen/blob/master/lib/kitchen.rb#L99
@@ -6,11 +6,42 @@ module Berkshelf
6
6
  class Source
7
7
  include Comparable
8
8
 
9
- attr_accessor :source
9
+ attr_accessor :type
10
+ attr_accessor :uri_string
11
+ attr_accessor :options
10
12
 
11
13
  # @param [String, Berkshelf::SourceURI] source
12
- def initialize(source)
13
- @source = source
14
+ def initialize(source, **options)
15
+ @options = {timeout: api_timeout, open_timeout: [(api_timeout / 10), 3].max, ssl: {}}
16
+ @options.update(options)
17
+ case source
18
+ when String
19
+ # source "https://supermarket.chef.io/"
20
+ @type = :supermarket
21
+ @uri_string = source
22
+ when :chef_server
23
+ # source :chef_server
24
+ @type = :chef_server
25
+ @uri_string = options[:url] || Berkshelf::Config.instance.chef.chef_server_url
26
+ when Hash
27
+ # source type: uri, option: value, option: value
28
+ source = source.dup
29
+ @type, @uri_string = source.shift
30
+ @options.update(source)
31
+ end
32
+ # Default options for some source types.
33
+ case @type
34
+ when :chef_server
35
+ @options[:client_name] ||= Berkshelf::Config.instance.chef.node_name
36
+ @options[:client_key] ||= Berkshelf::Config.instance.chef.client_key
37
+ when :artifactory
38
+ @options[:api_key] ||= Berkshelf::Config.instance.chef.artifactory_api_key || ENV['ARTIFACTORY_API_KEY']
39
+ end
40
+ # Set some default SSL options.
41
+ Berkshelf::Config.instance.ssl.each do |key, value|
42
+ @options[:ssl][key.to_sym] = value unless @options[:ssl].include?(key.to_sym)
43
+ end
44
+ @options[:ssl][:cert_store] = ssl_policy.store if ssl_policy.store
14
45
  @universe = nil
15
46
  end
16
47
 
@@ -19,35 +50,21 @@ module Berkshelf
19
50
  end
20
51
 
21
52
  def api_client
22
- @api_client ||= begin
23
- ssl_options = { verify: Berkshelf::Config.instance.ssl.verify }
24
- ssl_options[:cert_store] = ssl_policy.store if ssl_policy.store
25
-
26
- if source == :chef_server
27
- APIClient.chef_server(
28
- ssl: ssl_options,
29
- timeout: api_timeout,
30
- open_timeout: [(api_timeout / 10), 3].max,
31
- client_name: Berkshelf::Config.instance.chef.node_name,
32
- server_url: Berkshelf::Config.instance.chef.chef_server_url,
33
- client_key: Berkshelf::Config.instance.chef.client_key
34
- )
35
- else
36
- APIClient.new(uri,
37
- timeout: api_timeout,
38
- open_timeout: [(api_timeout / 10), 3].max,
39
- ssl: Berkshelf::Config.instance.ssl
40
- )
41
- end
42
- end
53
+ @api_client ||= case type
54
+ when :chef_server
55
+ APIClient.chef_server(server_url: uri.to_s, **options)
56
+ when :artifactory
57
+ # Don't accidentally mutate the options.
58
+ client_options = options.dup
59
+ api_key = client_options.delete(:api_key)
60
+ APIClient.new(uri, headers: {'X-Jfrog-Art-Api' => api_key}, **client_options)
61
+ else
62
+ APIClient.new(uri, **options)
63
+ end
43
64
  end
44
65
 
45
66
  def uri
46
- @uri ||= if source == :chef_server
47
- SourceURI.parse(Berkshelf::Config.instance.chef.chef_server_url)
48
- else
49
- SourceURI.parse(source)
50
- end
67
+ @uri ||= SourceURI.parse(uri_string)
51
68
  end
52
69
 
53
70
  # Forcefully obtain the universe from the API endpoint and assign it to {#universe}. This
@@ -116,20 +133,24 @@ module Berkshelf
116
133
  end
117
134
 
118
135
  def to_s
119
- "#{uri}"
136
+ if type == :supermarket
137
+ "#{uri}"
138
+ else
139
+ "#{type}: #{uri}"
140
+ end
120
141
  end
121
142
 
122
143
  def inspect
123
- "#<#{self.class.name} uri: #{@uri.to_s.inspect}>"
144
+ "#<#{self.class.name} #{type}: #{uri.to_s.inspect}, #{options.map {|k, v| "#{k}: #{v.inspect}" }.join(', ')}>"
124
145
  end
125
146
 
126
147
  def hash
127
- @uri.host.hash
148
+ [type, uri_string, options].hash
128
149
  end
129
150
 
130
151
  def ==(other)
131
152
  return false unless other.is_a?(self.class)
132
- uri == other.uri
153
+ type == other.type && uri == other.uri
133
154
  end
134
155
 
135
156
  private
@@ -1,3 +1,3 @@
1
1
  module Berkshelf
2
- VERSION = "5.6.5"
2
+ VERSION = "6.0.0"
3
3
  end
@@ -7,6 +7,7 @@ BERKS_SPEC_DATA = File.expand_path("../data", __FILE__)
7
7
  require "rspec"
8
8
  require "cleanroom/rspec"
9
9
  require "webmock/rspec"
10
+ require "rspec/its"
10
11
  require "berkshelf/api/rspec" unless windows?
11
12
 
12
13
  Dir["spec/support/**/*.rb"].each { |f| require File.expand_path(f) }
@@ -23,11 +23,12 @@ module Berkshelf
23
23
  end
24
24
 
25
25
  def matches?(root)
26
- unless root.join(@name).exist?
26
+ path = Pathname.glob(root.join(@name)).first
27
+ unless path.exist?
27
28
  throw :failure, root.join(@name)
28
29
  end
29
30
 
30
- contents = File.read(root.join(@name))
31
+ contents = File.read(path)
31
32
 
32
33
  @contents.each do |string|
33
34
  unless contents.include?(string)
@@ -38,23 +38,49 @@ module Berkshelf
38
38
  let(:version) { "1.0.0" }
39
39
 
40
40
  it "supports the 'opscode' location type" do
41
+ allow(source).to receive(:type) { :supermarket }
41
42
  allow(remote_cookbook).to receive(:location_type) { :opscode }
42
43
  allow(remote_cookbook).to receive(:location_path) { "http://api.opscode.com" }
43
44
  rest = double("community-rest")
44
- expect(CommunityREST).to receive(:new).with("http://api.opscode.com") { rest }
45
+ expect(CommunityREST).to receive(:new).with("http://api.opscode.com", {}) { rest }
45
46
  expect(rest).to receive(:download).with(name, version)
46
47
  subject.try_download(source, name, version)
47
48
  end
48
49
 
49
50
  it "supports the 'supermarket' location type" do
51
+ allow(source).to receive(:type) { :supermarket }
50
52
  allow(remote_cookbook).to receive(:location_type) { :supermarket }
51
53
  allow(remote_cookbook).to receive(:location_path) { "http://api.supermarket.com" }
52
54
  rest = double("community-rest")
53
- expect(CommunityREST).to receive(:new).with("http://api.supermarket.com") { rest }
55
+ expect(CommunityREST).to receive(:new).with("http://api.supermarket.com", {}) { rest }
54
56
  expect(rest).to receive(:download).with(name, version)
55
57
  subject.try_download(source, name, version)
56
58
  end
57
59
 
60
+ context "with an artifactory source" do
61
+ it "supports the 'opscode' location type" do
62
+ allow(source).to receive(:type) { :artifactory }
63
+ allow(source).to receive(:options) { {api_key: 'secret'} }
64
+ allow(remote_cookbook).to receive(:location_type) { :opscode }
65
+ allow(remote_cookbook).to receive(:location_path) { "http://artifactory/" }
66
+ rest = double("community-rest")
67
+ expect(CommunityREST).to receive(:new).with("http://artifactory/", {headers: {'X-Jfrog-Art-Api' => 'secret'}}) { rest }
68
+ expect(rest).to receive(:download).with(name, version)
69
+ subject.try_download(source, name, version)
70
+ end
71
+
72
+ it "supports the 'supermarket' location type" do
73
+ allow(source).to receive(:type) { :artifactory }
74
+ allow(source).to receive(:options) { {api_key: 'secret'} }
75
+ allow(remote_cookbook).to receive(:location_type) { :supermarket }
76
+ allow(remote_cookbook).to receive(:location_path) { "http://artifactory/" }
77
+ rest = double("community-rest")
78
+ expect(CommunityREST).to receive(:new).with("http://artifactory/", {headers: {'X-Jfrog-Art-Api' => 'secret'}}) { rest }
79
+ expect(rest).to receive(:download).with(name, version)
80
+ subject.try_download(source, name, version)
81
+ end
82
+ end
83
+
58
84
  describe "chef_server location type" do
59
85
  let(:chef_server_url) { "http://configured-chef-server/" }
60
86
  let(:ridley_client) do
@@ -91,6 +117,7 @@ module Berkshelf
91
117
  allow(subject).to receive(:ssl_policy).and_return(ssl_policy)
92
118
  allow(remote_cookbook).to receive(:location_type) { :chef_server }
93
119
  allow(remote_cookbook).to receive(:location_path) { chef_server_url }
120
+ allow(source).to receive(:options) { {read_timeout: 30, open_timeout: 3, ssl: {verify: true, cert_store: cert_store}} }
94
121
  end
95
122
 
96
123
  it "uses the berkshelf config and provides a custom cert_store" do
@@ -106,6 +133,44 @@ module Berkshelf
106
133
  expect(Ridley).to receive(:open).with(credentials) { ridley_client }
107
134
  subject.try_download(source, name, version)
108
135
  end
136
+
137
+ context "with a source option for client_name" do
138
+ before do
139
+ allow(source).to receive(:options) { {client_name: "other-client", read_timeout: 30, open_timeout: 3, ssl: {verify: true, cert_store: cert_store}} }
140
+ end
141
+ it "uses the override" do
142
+ credentials = {
143
+ server_url: chef_server_url,
144
+ client_name: "other-client",
145
+ client_key: chef_config.client_key,
146
+ ssl: {
147
+ verify: berkshelf_config.ssl.verify,
148
+ cert_store: cert_store,
149
+ },
150
+ }
151
+ expect(Ridley).to receive(:open).with(credentials) { ridley_client }
152
+ subject.try_download(source, name, version)
153
+ end
154
+ end
155
+
156
+ context "with a source option for client_key" do
157
+ before do
158
+ allow(source).to receive(:options) { {client_key: "other-key", read_timeout: 30, open_timeout: 3, ssl: {verify: true, cert_store: cert_store}} }
159
+ end
160
+ it "uses the override" do
161
+ credentials = {
162
+ server_url: chef_server_url,
163
+ client_name: chef_config.node_name,
164
+ client_key: "other-key",
165
+ ssl: {
166
+ verify: berkshelf_config.ssl.verify,
167
+ cert_store: cert_store,
168
+ },
169
+ }
170
+ expect(Ridley).to receive(:open).with(credentials) { ridley_client }
171
+ subject.try_download(source, name, version)
172
+ end
173
+ end
109
174
  end
110
175
 
111
176
  it "supports the 'file_store' location type" do
@@ -2,9 +2,152 @@ require "spec_helper"
2
2
 
3
3
  module Berkshelf
4
4
  describe Source do
5
- describe "#universe"
6
- describe "#cookbook"
7
- describe "#versions"
5
+ let(:arguments) { [] }
6
+ let(:config) { Config.new }
7
+ subject(:instance) { described_class.new(*arguments) }
8
+ before do
9
+ allow(Berkshelf::Config).to receive(:instance).and_return(config)
10
+ end
11
+
12
+ describe "#type" do
13
+ subject { instance.type }
14
+
15
+ context "with a string argument" do
16
+ let(:arguments) { ['https://example.com'] }
17
+ it { is_expected.to eq :supermarket }
18
+ end
19
+
20
+ context "with a string argument and options" do
21
+ let(:arguments) { ['https://example.com', {key: 'value'}] }
22
+ it { is_expected.to eq :supermarket }
23
+ end
24
+
25
+ context "with a symbol argument" do
26
+ let(:arguments) { [:chef_server] }
27
+ it { is_expected.to eq :chef_server }
28
+ end
29
+
30
+ context "with a symbol argument and options" do
31
+ let(:arguments) { [:chef_server, {key: 'value'}] }
32
+ it { is_expected.to eq :chef_server }
33
+ end
34
+
35
+ context "with a hash argument" do
36
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}] }
37
+ it { is_expected.to eq :artifactory }
38
+ end
39
+
40
+ context "with a hash argument and connected options" do
41
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual', key: 'value'}] }
42
+ it { is_expected.to eq :artifactory }
43
+ end
44
+
45
+ context "with a hash argument and disconnected options" do
46
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}, {key: 'value'}] }
47
+ it { is_expected.to eq :artifactory }
48
+ end
49
+ end
50
+
51
+ describe "#uri" do
52
+ subject { instance.uri.to_s }
53
+
54
+ context "with a string argument" do
55
+ let(:arguments) { ['https://example.com'] }
56
+ it { is_expected.to eq 'https://example.com' }
57
+ end
58
+
59
+ context "with a string argument and options" do
60
+ let(:arguments) { ['https://example.com', {key: 'value'}] }
61
+ it { is_expected.to eq 'https://example.com' }
62
+ end
63
+
64
+ context "with a symbol argument" do
65
+ let(:arguments) { [:chef_server] }
66
+ before { config.chef.chef_server_url = 'https://chefserver/' }
67
+ it { is_expected.to eq 'https://chefserver/' }
68
+ end
69
+
70
+ context "with a symbol argument and options" do
71
+ let(:arguments) { [:chef_server, {key: 'value'}] }
72
+ before { config.chef.chef_server_url = 'https://chefserver/' }
73
+ it { is_expected.to eq 'https://chefserver/' }
74
+ end
75
+
76
+ context "with a hash argument" do
77
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}] }
78
+ it { is_expected.to eq 'https://example.com/api/chef/chef-virtual' }
79
+ end
80
+
81
+ context "with a hash argument and connected options" do
82
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual', key: 'value'}] }
83
+ it { is_expected.to eq 'https://example.com/api/chef/chef-virtual' }
84
+ end
85
+
86
+ context "with a hash argument and disconnected options" do
87
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}, {key: 'value'}] }
88
+ it { is_expected.to eq 'https://example.com/api/chef/chef-virtual' }
89
+ end
90
+
91
+ context "with an invalid URI" do
92
+ let(:arguments) { ['ftp://example.com'] }
93
+ it { expect { subject }.to raise_error InvalidSourceURI }
94
+ end
95
+ end
96
+
97
+ describe "#options" do
98
+ subject { instance.options }
99
+
100
+ context "with a string argument" do
101
+ let(:arguments) { ['https://example.com'] }
102
+
103
+ it { is_expected.to be_a(Hash) }
104
+ # Check all baseline values.
105
+ its([:timeout]) { is_expected.to eq 30 }
106
+ its([:open_timeout]) { is_expected.to eq 3 }
107
+ its([:ssl, :verify]) { is_expected.to be true }
108
+ its([:ssl, :ca_file]) { is_expected.to be_nil }
109
+ its([:ssl, :ca_path]) { is_expected.to be_nil }
110
+ its([:ssl, :client_cert]) { is_expected.to be_nil }
111
+ its([:ssl, :client_key]) { is_expected.to be_nil }
112
+ its([:ssl, :cert_store]) { is_expected.to be_a(OpenSSL::X509::Store) }
113
+ end
114
+
115
+ context "with a string argument and options" do
116
+ let(:arguments) { ['https://example.com', {key: 'value'}] }
117
+ its([:key]) { is_expected.to eq 'value' }
118
+ end
119
+
120
+ context "with a symbol argument" do
121
+ let(:arguments) { [:chef_server] }
122
+ it { is_expected.to be_a(Hash) }
123
+ end
124
+
125
+ context "with a symbol argument and options" do
126
+ let(:arguments) { [:chef_server, {key: 'value'}] }
127
+ its([:key]) { is_expected.to eq 'value' }
128
+ end
129
+
130
+ context "with a hash argument" do
131
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}] }
132
+ it { is_expected.to be_a(Hash) }
133
+ end
134
+
135
+ context "with a hash argument and connected options" do
136
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual', key: 'value'}] }
137
+ its([:key]) { is_expected.to eq 'value' }
138
+ end
139
+
140
+ context "with a hash argument and disconnected options" do
141
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}, {key: 'value'}] }
142
+ its([:key]) { is_expected.to eq 'value' }
143
+ end
144
+
145
+ context "with an artifactory source and the API key in the Chef config" do
146
+ let(:arguments) { [{artifactory: 'https://example.com/api/chef/chef-virtual'}] }
147
+ before { config.chef.artifactory_api_key = 'secret' }
148
+ its([:api_key]) { is_expected.to eq 'secret' }
149
+ end
150
+ end
8
151
 
9
152
  describe "#==" do
10
153
  it "is the same if the uri matches" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkshelf
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.5
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamie Winsor
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2017-05-04 00:00:00.000000000 Z
15
+ date: 2017-05-17 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: addressable
@@ -284,6 +284,7 @@ files:
284
284
  - berkshelf.gemspec
285
285
  - bin/berks
286
286
  - docs/berkshelf_for_newcomers.md
287
+ - features/artifactory.feature
287
288
  - features/berksfile.feature
288
289
  - features/commands/apply.feature
289
290
  - features/commands/contingent.feature
@@ -471,7 +472,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
471
472
  requirements:
472
473
  - - ">="
473
474
  - !ruby/object:Gem::Version
474
- version: 2.2.0
475
+ version: 2.3.3
475
476
  required_rubygems_version: !ruby/object:Gem::Requirement
476
477
  requirements:
477
478
  - - ">="
@@ -479,11 +480,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
479
480
  version: 2.0.0
480
481
  requirements: []
481
482
  rubyforge_project:
482
- rubygems_version: 2.5.1
483
+ rubygems_version: 2.6.11
483
484
  signing_key:
484
485
  specification_version: 4
485
486
  summary: Manages a Cookbook's, or an Application's, Cookbook dependencies
486
487
  test_files:
488
+ - features/artifactory.feature
487
489
  - features/berksfile.feature
488
490
  - features/commands/apply.feature
489
491
  - features/commands/contingent.feature