berkshelf-api 1.4.0 → 2.0.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.
Files changed (31) hide show
  1. data/CHANGELOG.md +12 -0
  2. data/README.md +19 -4
  3. data/lib/berkshelf/api.rb +2 -1
  4. data/lib/berkshelf/api/cache_builder.rb +1 -1
  5. data/lib/berkshelf/api/cache_builder/worker/file_store.rb +1 -1
  6. data/lib/berkshelf/api/cache_builder/worker/supermarket.rb +47 -0
  7. data/lib/berkshelf/api/config.rb +1 -4
  8. data/lib/berkshelf/api/remote_cookbook.rb +17 -1
  9. data/lib/berkshelf/api/rspec.rb +1 -1
  10. data/lib/berkshelf/api/site_connector.rb +1 -1
  11. data/lib/berkshelf/api/site_connector/supermarket.rb +67 -0
  12. data/lib/berkshelf/api/version.rb +1 -1
  13. data/spec/unit/berkshelf/api/application_spec.rb +6 -4
  14. data/spec/unit/berkshelf/api/cache_builder/worker/chef_server_spec.rb +5 -4
  15. data/spec/unit/berkshelf/api/cache_builder/worker/file_store_spec.rb +5 -4
  16. data/spec/unit/berkshelf/api/cache_builder/worker/github_spec.rb +13 -17
  17. data/spec/unit/berkshelf/api/cache_builder/worker/supermarket_spec.rb +103 -0
  18. data/spec/unit/berkshelf/api/cache_builder/worker_spec.rb +1 -1
  19. data/spec/unit/berkshelf/api/cache_builder_spec.rb +12 -8
  20. data/spec/unit/berkshelf/api/cache_manager_spec.rb +16 -15
  21. data/spec/unit/berkshelf/api/config_spec.rb +3 -4
  22. data/spec/unit/berkshelf/api/dependency_cache_spec.rb +10 -6
  23. data/spec/unit/berkshelf/api/endpoint/v1_spec.rb +58 -12
  24. data/spec/unit/berkshelf/api/rack_app_spec.rb +5 -2
  25. data/spec/unit/berkshelf/api/rest_gateway_spec.rb +31 -10
  26. data/spec/unit/berkshelf/api/site_connector/supermarket_spec.rb +90 -0
  27. metadata +9 -25
  28. data/lib/berkshelf/api/cache_builder/worker/opscode.rb +0 -67
  29. data/lib/berkshelf/api/site_connector/opscode.rb +0 -181
  30. data/spec/unit/berkshelf/api/cache_builder/worker/opscode_spec.rb +0 -43
  31. data/spec/unit/berkshelf/api/site_connector/opscode_spec.rb +0 -85
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: berkshelf-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2014-06-06 00:00:00.000000000 Z
13
+ date: 2014-07-10 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: ridley
@@ -130,22 +130,6 @@ dependencies:
130
130
  - - <
131
131
  - !ruby/object:Gem::Version
132
132
  version: 3.0.0
133
- - !ruby/object:Gem::Dependency
134
- name: faraday
135
- requirement: !ruby/object:Gem::Requirement
136
- none: false
137
- requirements:
138
- - - ~>
139
- - !ruby/object:Gem::Version
140
- version: 0.9.0
141
- type: :runtime
142
- prerelease: false
143
- version_requirements: !ruby/object:Gem::Requirement
144
- none: false
145
- requirements:
146
- - - ~>
147
- - !ruby/object:Gem::Version
148
- version: 0.9.0
149
133
  - !ruby/object:Gem::Dependency
150
134
  name: retryable
151
135
  requirement: !ruby/object:Gem::Requirement
@@ -242,7 +226,7 @@ files:
242
226
  - lib/berkshelf/api/cache_builder/worker/chef_server.rb
243
227
  - lib/berkshelf/api/cache_builder/worker/file_store.rb
244
228
  - lib/berkshelf/api/cache_builder/worker/github.rb
245
- - lib/berkshelf/api/cache_builder/worker/opscode.rb
229
+ - lib/berkshelf/api/cache_builder/worker/supermarket.rb
246
230
  - lib/berkshelf/api/cache_builder/worker.rb
247
231
  - lib/berkshelf/api/cache_builder.rb
248
232
  - lib/berkshelf/api/cache_manager.rb
@@ -263,7 +247,7 @@ files:
263
247
  - lib/berkshelf/api/rest_gateway.rb
264
248
  - lib/berkshelf/api/rspec/server.rb
265
249
  - lib/berkshelf/api/rspec.rb
266
- - lib/berkshelf/api/site_connector/opscode.rb
250
+ - lib/berkshelf/api/site_connector/supermarket.rb
267
251
  - lib/berkshelf/api/site_connector.rb
268
252
  - lib/berkshelf/api/srv_ctl.rb
269
253
  - lib/berkshelf/api/version.rb
@@ -278,7 +262,7 @@ files:
278
262
  - spec/unit/berkshelf/api/cache_builder/worker/chef_server_spec.rb
279
263
  - spec/unit/berkshelf/api/cache_builder/worker/file_store_spec.rb
280
264
  - spec/unit/berkshelf/api/cache_builder/worker/github_spec.rb
281
- - spec/unit/berkshelf/api/cache_builder/worker/opscode_spec.rb
265
+ - spec/unit/berkshelf/api/cache_builder/worker/supermarket_spec.rb
282
266
  - spec/unit/berkshelf/api/cache_builder/worker_spec.rb
283
267
  - spec/unit/berkshelf/api/cache_builder_spec.rb
284
268
  - spec/unit/berkshelf/api/cache_manager_spec.rb
@@ -289,7 +273,7 @@ files:
289
273
  - spec/unit/berkshelf/api/mixin/services_spec.rb
290
274
  - spec/unit/berkshelf/api/rack_app_spec.rb
291
275
  - spec/unit/berkshelf/api/rest_gateway_spec.rb
292
- - spec/unit/berkshelf/api/site_connector/opscode_spec.rb
276
+ - spec/unit/berkshelf/api/site_connector/supermarket_spec.rb
293
277
  - spec/unit/berkshelf/api/srv_ctl_spec.rb
294
278
  - bin/berks-api
295
279
  homepage: https://github.com/berkshelf/berkshelf-api
@@ -313,7 +297,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
313
297
  version: '0'
314
298
  segments:
315
299
  - 0
316
- hash: 80644279196753361
300
+ hash: -144777955995008759
317
301
  requirements: []
318
302
  rubyforge_project:
319
303
  rubygems_version: 1.8.23
@@ -331,7 +315,7 @@ test_files:
331
315
  - spec/unit/berkshelf/api/cache_builder/worker/chef_server_spec.rb
332
316
  - spec/unit/berkshelf/api/cache_builder/worker/file_store_spec.rb
333
317
  - spec/unit/berkshelf/api/cache_builder/worker/github_spec.rb
334
- - spec/unit/berkshelf/api/cache_builder/worker/opscode_spec.rb
318
+ - spec/unit/berkshelf/api/cache_builder/worker/supermarket_spec.rb
335
319
  - spec/unit/berkshelf/api/cache_builder/worker_spec.rb
336
320
  - spec/unit/berkshelf/api/cache_builder_spec.rb
337
321
  - spec/unit/berkshelf/api/cache_manager_spec.rb
@@ -342,6 +326,6 @@ test_files:
342
326
  - spec/unit/berkshelf/api/mixin/services_spec.rb
343
327
  - spec/unit/berkshelf/api/rack_app_spec.rb
344
328
  - spec/unit/berkshelf/api/rest_gateway_spec.rb
345
- - spec/unit/berkshelf/api/site_connector/opscode_spec.rb
329
+ - spec/unit/berkshelf/api/site_connector/supermarket_spec.rb
346
330
  - spec/unit/berkshelf/api/srv_ctl_spec.rb
347
331
  has_rdoc:
@@ -1,67 +0,0 @@
1
- module Berkshelf::API
2
- class CacheBuilder
3
- module Worker
4
- class Opscode < Worker::Base
5
- worker_type "opscode"
6
-
7
- finalizer :finalize_callback
8
-
9
- # @param [Hash] options
10
- # see {API::SiteConnector::Opscode.new} for options
11
- def initialize(options = {})
12
- @connection = Berkshelf::API::SiteConnector::Opscode.pool_link(size: 25, args: [ options ])
13
- super
14
- end
15
-
16
- # @return [Array<RemoteCookbook>]
17
- # The list of cookbooks this builder can find
18
- def cookbooks
19
- [].tap do |cookbook_versions|
20
- connection.cookbooks.collect do |cookbook|
21
- [ cookbook, connection.future(:versions, cookbook) ]
22
- end.each do |cookbook, versions|
23
- versions.value.each do |version|
24
- cookbook_versions << RemoteCookbook.new(cookbook, version, self.class.worker_type, @connection.api_uri, priority)
25
- end
26
- end
27
- end
28
- end
29
-
30
- # Return the metadata of the given RemoteCookbook. If the metadata could not be found or parsed
31
- # nil is returned.
32
- #
33
- # @param [RemoteCookbook] remote
34
- #
35
- # @return [Ridley::Chef::Cookbook::Metadata, nil]
36
- def metadata(remote)
37
- Dir.mktmpdir('metadata') do |destination|
38
- if connection.download(remote.name, remote.version, destination)
39
- load_metadata(destination, remote.name)
40
- end
41
- end
42
- end
43
-
44
- private
45
-
46
- attr_accessor :connection
47
-
48
- def finalize_callback
49
- connection.terminate if connection && connection.alive?
50
- end
51
-
52
- def load_metadata(directory, cookbook)
53
- # The community site does not enforce the name of the cookbook contained in the archive
54
- # downloaded and extracted. This will just find the first metadata.json and load it.
55
- file = Dir["#{directory}/**/*/metadata.json"].first
56
- return nil if file.nil?
57
-
58
- metadata = File.read(file)
59
- Ridley::Chef::Cookbook::Metadata.from_json(metadata)
60
- rescue JSON::ParserError => ex
61
- log.warn "Error loading metadata for #{cookbook} from: #{file}"
62
- abort MetadataLoadError.new(ex)
63
- end
64
- end
65
- end
66
- end
67
- end
@@ -1,181 +0,0 @@
1
- require 'open-uri'
2
- require 'retryable'
3
- require 'archive'
4
- require 'tempfile'
5
-
6
- module Berkshelf::API
7
- module SiteConnector
8
- class Opscode
9
- class << self
10
- # @param [String] version
11
- #
12
- # @return [String]
13
- def uri_escape_version(version)
14
- version.to_s.gsub('.', '_')
15
- end
16
-
17
- # @param [String] uri
18
- #
19
- # @return [String]
20
- def version_from_uri(uri)
21
- File.basename(uri.to_s).gsub('_', '.')
22
- end
23
- end
24
-
25
- include Celluloid
26
- include Berkshelf::API::Logging
27
-
28
- V1_API = 'http://cookbooks.opscode.com/api/v1'.freeze
29
-
30
- # @return [String]
31
- attr_reader :api_uri
32
- # @return [Integer]
33
- # how many retries to attempt on HTTP requests
34
- attr_reader :retries
35
- # @return [Float]
36
- # time to wait between retries
37
- attr_reader :retry_interval
38
-
39
- # @option options [String] :url ({V1_API})
40
- # url of community site
41
- # @option options [Integer] :retries (5)
42
- # how many download retry attempts to make
43
- # @option options [Float] :retry_interval (0.5)
44
- # how long to wait before retrying again
45
- def initialize(options = {})
46
- options = { url: V1_API, retries: 5, retry_interval: 0.5 }.merge(options)
47
- @api_uri = options[:url]
48
-
49
- @connection = Faraday.new(@api_uri) do |c|
50
- c.response :parse_json
51
- c.use Faraday::Adapter::NetHttp
52
- end
53
- end
54
-
55
- # @return [Array<String>]
56
- # A list of cookbook names available on the server
57
- def cookbooks
58
- start = 0
59
- count = connection.get("cookbooks").body["total"]
60
- cookbooks = Array.new
61
-
62
- while count > 0
63
- req = connection.get("cookbooks?start=#{start}&items=#{count}")
64
- chunk = req.body["items"]
65
- if chunk
66
- cookbooks += chunk
67
- start += 100
68
- count -= 100
69
- else
70
- log.warn "Didn't get any cookbooks - #{req.body}"
71
- end
72
- end
73
-
74
- cookbooks.map { |cb| cb["cookbook_name"] }
75
- end
76
-
77
- # @param [String] cookbook
78
- # the name of the cookbook to find version for
79
- #
80
- # @return [Array<String>]
81
- # A list of versions of this cookbook available on the server
82
- def versions(cookbook)
83
- response = connection.get("cookbooks/#{cookbook}")
84
-
85
- case response.status
86
- when (200..299)
87
- response.body['versions'].collect do |version_uri|
88
- self.class.version_from_uri(version_uri)
89
- end
90
- else
91
- Array.new
92
- end
93
- end
94
-
95
- # Download the cookbook with the given name and version to the destination. The directory
96
- # containing the extracted contents will be returned on success. On failure, nil will
97
- # be returned.
98
- #
99
- # @param [String] cookbook
100
- # The name of the cookbook to download
101
- # @param [String] version
102
- # The version of the cookbook to download
103
- # @param [String] destination
104
- # The directory to download the cookbook to
105
- #
106
- # @return [String, nil]
107
- def download(name, version, destination = Dir.mktmpdir)
108
- log.debug "Downloading #{name}(#{version})"
109
- if uri = download_uri(name, version)
110
- begin
111
- archive = stream(uri)
112
- Archive.extract(archive.path, destination)
113
- destination
114
- rescue => ex
115
- log.warn "Error downloading/extracting #{name} (#{version}): #{ex}"
116
- nil
117
- ensure
118
- archive.unlink unless archive.nil?
119
- end
120
- end
121
- end
122
-
123
- # Return the location where a cookbook of the given name and version can be downloaded from
124
- #
125
- # @param [String] cookbook
126
- # The name of the cookbook
127
- # @param [String] version
128
- # The version of the cookbook
129
- #
130
- # @return [String, nil]
131
- def download_uri(name, version)
132
- unless cookbook = find(name, version)
133
- return nil
134
- end
135
- cookbook[:file]
136
- end
137
-
138
- # @param [String] cookbook
139
- # The name of the cookbook to retrieve
140
- # @param [String] version
141
- # The version of the cookbook to retrieve
142
- #
143
- # @return [Hashie::Mash, nil]
144
- def find(name, version)
145
- response = connection.get("cookbooks/#{name}/versions/#{self.class.uri_escape_version(version)}")
146
-
147
- case response.status
148
- when (200..299)
149
- response.body
150
- else
151
- nil
152
- end
153
- end
154
-
155
- # Stream the response body of a remote URL to a file on the local file system
156
- #
157
- # @param [String] target
158
- # a URL to stream the response body from
159
- #
160
- # @return [Tempfile]
161
- def stream(target)
162
- local = Tempfile.new('opscode-site-stream')
163
- local.binmode
164
-
165
- retryable(tries: retries, on: OpenURI::HTTPError, sleep: retry_interval) do
166
- open(target, 'rb', connection.headers) do |remote|
167
- local.write(remote.read)
168
- end
169
- end
170
-
171
- local
172
- ensure
173
- local.close(false) unless local.nil?
174
- end
175
-
176
- private
177
-
178
- attr_reader :connection
179
- end
180
- end
181
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Berkshelf::API::CacheBuilder::Worker::Opscode do
4
- describe "ClassMethods" do
5
- subject { described_class }
6
- its(:worker_type) { should eql("opscode") }
7
- end
8
-
9
- let(:cookbooks) { ["chicken", "tuna"] }
10
- let(:chicken_versions) { ["1.0", "2.0"] }
11
- let(:tuna_versions) { ["3.0.0", "3.0.1"] }
12
- let(:connection) do
13
- connection = double('connection')
14
- connection.stub(:cookbooks).and_return(cookbooks)
15
- connection
16
- end
17
-
18
- subject do
19
- Berkshelf::API::CacheManager.start
20
- described_class.new
21
- end
22
-
23
- it_behaves_like "a human-readable string"
24
-
25
- describe "#cookbooks" do
26
- let(:location_type) { described_class.worker_type }
27
- let(:location_path) { Berkshelf::API::SiteConnector::Opscode::V1_API}
28
-
29
- it "returns an array of RemoteCookbooks described by the server" do
30
- expected_value = [
31
- Berkshelf::API::RemoteCookbook.new("chicken", "1.0", location_type, location_path),
32
- Berkshelf::API::RemoteCookbook.new("chicken", "2.0", location_type, location_path),
33
- Berkshelf::API::RemoteCookbook.new("tuna", "3.0.0", location_type, location_path),
34
- Berkshelf::API::RemoteCookbook.new("tuna", "3.0.1", location_type, location_path)
35
- ]
36
-
37
- connection.should_receive(:future).with(:versions, "chicken").and_return(double(value: chicken_versions))
38
- connection.should_receive(:future).with(:versions, "tuna").and_return(double(value: tuna_versions))
39
- subject.should_receive(:connection).at_least(1).times.and_return(connection)
40
- expect(subject.cookbooks).to eql(expected_value)
41
- end
42
- end
43
- end
@@ -1,85 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Berkshelf::API::SiteConnector::Opscode do
4
- let(:connection) { double("connection") }
5
- let(:total_response) { double("total", status: 200, body: { "total" => 10 } ) }
6
- let(:cookbooks_response) do
7
- double("cookbooks", status: 200, body: {
8
- "items"=> [
9
- {"cookbook_name" => "chicken"},
10
- {"cookbook_name" => "tuna"}
11
- ]})
12
- end
13
- let(:chicken_versions_response) do
14
- double("chicken_versions", status: 200, body: {
15
- "versions" => [
16
- "http://www.example.com/api/v1/cookbooks/chicken/versions/1_0",
17
- "http://www.example.com/api/v1/cookbooks/chicken/versions/2_0"
18
- ]})
19
- end
20
-
21
- subject { described_class.new }
22
-
23
- describe "#cookbooks" do
24
- it "should fetch all the cookbooks and return a list of their names" do
25
- connection.should_receive(:get).
26
- with("cookbooks").
27
- and_return(total_response)
28
-
29
- connection.should_receive(:get).
30
- with("cookbooks?start=0&items=10").
31
- and_return(cookbooks_response)
32
-
33
- subject.should_receive(:connection).at_least(1).times.and_return(connection)
34
- expect(subject.cookbooks).to eql(["chicken", "tuna"])
35
- end
36
- end
37
-
38
- describe "#versions" do
39
- it "should call the server for the cookbook provied and return a list of available version number" do
40
- connection.should_receive(:get).
41
- with("cookbooks/chicken").
42
- and_return(chicken_versions_response)
43
-
44
- subject.should_receive(:connection).at_least(1).times.and_return(connection)
45
- expect(subject.versions("chicken")).to eql(["1.0", "2.0"])
46
- end
47
- end
48
-
49
- describe "#find" do
50
- let(:name) { "nginx" }
51
- let(:version) { "1.4.0" }
52
- let(:result) { subject.find(name, version) }
53
-
54
- it "returns the cookbook and version information" do
55
- expect(result.cookbook).to eq('http://cookbooks.opscode.com/api/v1/cookbooks/nginx')
56
- expect(result.version).to eq('1.4.0')
57
- end
58
-
59
- context "when the cookbook is not found" do
60
- let(:name) { "not_a_real_cookbook_that_anyone_should_ever_make" }
61
-
62
- it "returns nil" do
63
- expect(result).to be_nil
64
- end
65
- end
66
- end
67
-
68
- describe "#download" do
69
- let(:name) { "chicken" }
70
- let(:version) { "1.0.0" }
71
- let(:destination) { "location" }
72
-
73
- it "should download then ungzip/tar the cookbook" do
74
- response = { file: "http://file" }
75
- tempfile = double('tempfile', path: '/some/path', unlink: nil)
76
-
77
- subject.should_receive(:find).with(name, version).and_return(response)
78
- subject.should_receive(:stream).with("http://file").and_return(tempfile)
79
- Archive.should_receive(:extract).with(tempfile.path, destination)
80
-
81
- subject.download(name, version, destination)
82
- end
83
- end
84
- end
85
-