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.
- data/CHANGELOG.md +12 -0
- data/README.md +19 -4
- data/lib/berkshelf/api.rb +2 -1
- data/lib/berkshelf/api/cache_builder.rb +1 -1
- data/lib/berkshelf/api/cache_builder/worker/file_store.rb +1 -1
- data/lib/berkshelf/api/cache_builder/worker/supermarket.rb +47 -0
- data/lib/berkshelf/api/config.rb +1 -4
- data/lib/berkshelf/api/remote_cookbook.rb +17 -1
- data/lib/berkshelf/api/rspec.rb +1 -1
- data/lib/berkshelf/api/site_connector.rb +1 -1
- data/lib/berkshelf/api/site_connector/supermarket.rb +67 -0
- data/lib/berkshelf/api/version.rb +1 -1
- data/spec/unit/berkshelf/api/application_spec.rb +6 -4
- data/spec/unit/berkshelf/api/cache_builder/worker/chef_server_spec.rb +5 -4
- data/spec/unit/berkshelf/api/cache_builder/worker/file_store_spec.rb +5 -4
- data/spec/unit/berkshelf/api/cache_builder/worker/github_spec.rb +13 -17
- data/spec/unit/berkshelf/api/cache_builder/worker/supermarket_spec.rb +103 -0
- data/spec/unit/berkshelf/api/cache_builder/worker_spec.rb +1 -1
- data/spec/unit/berkshelf/api/cache_builder_spec.rb +12 -8
- data/spec/unit/berkshelf/api/cache_manager_spec.rb +16 -15
- data/spec/unit/berkshelf/api/config_spec.rb +3 -4
- data/spec/unit/berkshelf/api/dependency_cache_spec.rb +10 -6
- data/spec/unit/berkshelf/api/endpoint/v1_spec.rb +58 -12
- data/spec/unit/berkshelf/api/rack_app_spec.rb +5 -2
- data/spec/unit/berkshelf/api/rest_gateway_spec.rb +31 -10
- data/spec/unit/berkshelf/api/site_connector/supermarket_spec.rb +90 -0
- metadata +9 -25
- data/lib/berkshelf/api/cache_builder/worker/opscode.rb +0 -67
- data/lib/berkshelf/api/site_connector/opscode.rb +0 -181
- data/spec/unit/berkshelf/api/cache_builder/worker/opscode_spec.rb +0 -43
- data/spec/unit/berkshelf/api/site_connector/opscode_spec.rb +0 -85
@@ -4,7 +4,7 @@ describe Berkshelf::API::CacheBuilder::Worker do
|
|
4
4
|
describe "ClassMethods" do
|
5
5
|
describe "::[]" do
|
6
6
|
it "returns the class of the registered worker" do
|
7
|
-
expect(described_class["
|
7
|
+
expect(described_class["supermarket"]).to eql(Berkshelf::API::CacheBuilder::Worker::Supermarket)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
@@ -11,12 +11,16 @@ describe Berkshelf::API::CacheBuilder do
|
|
11
11
|
let(:future) { double('future', value: nil) }
|
12
12
|
let(:cache_manager) { double('cache_manager') }
|
13
13
|
|
14
|
-
before
|
14
|
+
before do
|
15
|
+
# https://github.com/celluloid/celluloid/wiki/Testing
|
16
|
+
allow(instance.wrapped_object).to receive(:workers).and_return(workers)
|
17
|
+
allow(instance.wrapped_object).to receive(:cache_manager).and_return(cache_manager)
|
18
|
+
allow(cache_manager).to receive(:process_workers)
|
19
|
+
end
|
15
20
|
|
16
21
|
it "asks the cache_manager to process all of its actors" do
|
17
|
-
|
18
|
-
|
19
|
-
build
|
22
|
+
expect(cache_manager).to receive(:process_workers).with(workers)
|
23
|
+
instance.build
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -32,11 +36,11 @@ describe Berkshelf::API::CacheBuilder do
|
|
32
36
|
|
33
37
|
context "when no workers are explicitly configured" do
|
34
38
|
it "has one worker started by default" do
|
35
|
-
expect(workers).to
|
39
|
+
expect(workers.size).to eq(1)
|
36
40
|
end
|
37
41
|
|
38
|
-
it "has an
|
39
|
-
expect(workers.first).to be_a(described_class::Worker::
|
42
|
+
it "has an Supermarket worker started by default" do
|
43
|
+
expect(workers.first).to be_a(described_class::Worker::Supermarket)
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
@@ -68,7 +72,7 @@ describe Berkshelf::API::CacheBuilder do
|
|
68
72
|
end
|
69
73
|
|
70
74
|
it "has two workers" do
|
71
|
-
expect(workers).to
|
75
|
+
expect(workers.size).to eq(2)
|
72
76
|
end
|
73
77
|
|
74
78
|
it "keeps the ordering" do
|
@@ -1,10 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Berkshelf::API::CacheManager do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
4
6
|
describe "ClassMethods" do
|
5
|
-
describe "
|
6
|
-
|
7
|
-
|
7
|
+
describe ".new" do
|
8
|
+
it 'has an empty cache' do
|
9
|
+
expect(subject.cache).to be_empty
|
10
|
+
end
|
8
11
|
|
9
12
|
context "when a save file exists" do
|
10
13
|
before do
|
@@ -39,20 +42,18 @@ describe Berkshelf::API::CacheManager do
|
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
|
-
subject { described_class.new }
|
43
|
-
|
44
45
|
it_behaves_like "a human-readable string"
|
45
46
|
|
46
47
|
describe "#add" do
|
47
|
-
|
48
|
+
skip
|
48
49
|
end
|
49
50
|
|
50
51
|
describe "#load_save" do
|
51
|
-
|
52
|
+
skip
|
52
53
|
end
|
53
54
|
|
54
55
|
describe "#remove" do
|
55
|
-
|
56
|
+
skip
|
56
57
|
end
|
57
58
|
|
58
59
|
describe "#clear" do
|
@@ -69,8 +70,8 @@ describe Berkshelf::API::CacheManager do
|
|
69
70
|
end
|
70
71
|
|
71
72
|
describe "#diff" do
|
72
|
-
let(:cookbook_one) { Berkshelf::API::RemoteCookbook.new("ruby", "1.2.3", "
|
73
|
-
let(:cookbook_two) { Berkshelf::API::RemoteCookbook.new("elixir", "2.0.0", "
|
73
|
+
let(:cookbook_one) { Berkshelf::API::RemoteCookbook.new("ruby", "1.2.3", "supermarket", nil, 1) }
|
74
|
+
let(:cookbook_two) { Berkshelf::API::RemoteCookbook.new("elixir", "2.0.0", "supermarket", nil, 1) }
|
74
75
|
let(:comparison) { Array.new }
|
75
76
|
|
76
77
|
before do
|
@@ -81,11 +82,11 @@ describe Berkshelf::API::CacheManager do
|
|
81
82
|
end
|
82
83
|
|
83
84
|
it "returns two items" do
|
84
|
-
expect(@diff).to
|
85
|
+
expect(@diff.size).to eq(2)
|
85
86
|
end
|
86
87
|
|
87
88
|
context "when there are more than one worker endpoints" do
|
88
|
-
let(:new_cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "3.0.0", "
|
89
|
+
let(:new_cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "3.0.0", "supermarket", nil, 2) }
|
89
90
|
let(:comparison) { [ cookbook_one, cookbook_two, new_cookbook ] }
|
90
91
|
|
91
92
|
before do
|
@@ -100,7 +101,7 @@ describe Berkshelf::API::CacheManager do
|
|
100
101
|
let(:comparison) { [cookbook_one] }
|
101
102
|
|
102
103
|
before do
|
103
|
-
@created, @deleted = @diff = subject.send(:diff, comparison, 1)
|
104
|
+
@created, @deleted = @diff = subject.send(:diff, comparison, 1)
|
104
105
|
end
|
105
106
|
|
106
107
|
it "only deletes cookbooks at the same priority" do
|
@@ -110,7 +111,7 @@ describe Berkshelf::API::CacheManager do
|
|
110
111
|
end
|
111
112
|
|
112
113
|
context "when there are created and deleted cookbooks" do
|
113
|
-
let(:new_cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "3.0.0", "
|
114
|
+
let(:new_cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "3.0.0", "supermarket", nil, 1) }
|
114
115
|
let(:comparison) { [ cookbook_one, new_cookbook ] }
|
115
116
|
|
116
117
|
it "should return created and deleted cookbooks" do
|
@@ -120,7 +121,7 @@ describe Berkshelf::API::CacheManager do
|
|
120
121
|
end
|
121
122
|
|
122
123
|
context "when there are only created cookbooks" do
|
123
|
-
let(:new_cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "3.0.0", "
|
124
|
+
let(:new_cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "3.0.0", "supermarket", nil, 1) }
|
124
125
|
let(:comparison) { [ cookbook_one, cookbook_two, new_cookbook ] }
|
125
126
|
|
126
127
|
it "should return only created cookbooks" do
|
@@ -13,12 +13,11 @@ describe Berkshelf::API::Config do
|
|
13
13
|
subject { described_class.new }
|
14
14
|
|
15
15
|
it "has a endpoint configured" do
|
16
|
-
expect(subject.endpoints).to
|
16
|
+
expect(subject.endpoints.size).to eq(1)
|
17
17
|
end
|
18
18
|
|
19
|
-
it "has the
|
20
|
-
expect(subject.endpoints.first.type).to eql("
|
21
|
-
expect(subject.endpoints.first.options[:url]).to eql("http://cookbooks.opscode.com/api/v1")
|
19
|
+
it "has the Supermarket community site as an endpoint" do
|
20
|
+
expect(subject.endpoints.first.type).to eql("supermarket")
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
def remote_cookbook(name, version, location_type = 'supermarket', location_path = 'https://supermarket.getchef.com', priority = 1, info = {})
|
4
|
+
Berkshelf::API::RemoteCookbook.new(name, version, location_type, location_path, priority, info)
|
5
|
+
end
|
6
|
+
|
3
7
|
describe Berkshelf::API::DependencyCache do
|
4
8
|
describe "ClassMethods" do
|
5
9
|
describe "::from_file" do
|
@@ -77,8 +81,8 @@ describe Berkshelf::API::DependencyCache do
|
|
77
81
|
describe "#cookbooks" do
|
78
82
|
it "should return a list of RemoteCookbooks" do
|
79
83
|
expected_value = [
|
80
|
-
|
81
|
-
|
84
|
+
remote_cookbook("chicken", "1.0"),
|
85
|
+
remote_cookbook("tuna", "3.0.0")
|
82
86
|
]
|
83
87
|
|
84
88
|
expect(subject.cookbooks).to eql(expected_value)
|
@@ -86,12 +90,12 @@ describe Berkshelf::API::DependencyCache do
|
|
86
90
|
end
|
87
91
|
|
88
92
|
describe "#add" do
|
89
|
-
let(:cookbook) {
|
93
|
+
let(:cookbook) { remote_cookbook("ruby", "1.2.3", "supermarket") }
|
90
94
|
before { subject.clear }
|
91
95
|
|
92
96
|
it "adds items to the cache" do
|
93
97
|
subject.add(cookbook, double(platforms: nil, dependencies: nil))
|
94
|
-
expect(subject.to_hash).to
|
98
|
+
expect(subject.to_hash.size).to eq(1)
|
95
99
|
end
|
96
100
|
end
|
97
101
|
|
@@ -100,12 +104,12 @@ describe Berkshelf::API::DependencyCache do
|
|
100
104
|
|
101
105
|
it "saves the contents of the cache as json to the given path" do
|
102
106
|
subject.save(path)
|
103
|
-
expect(File.exist?(path)).to
|
107
|
+
expect(File.exist?(path)).to be_truthy
|
104
108
|
end
|
105
109
|
end
|
106
110
|
|
107
111
|
describe "#clear" do
|
108
|
-
let(:cookbook) {
|
112
|
+
let(:cookbook) { remote_cookbook("ruby", "1.2.3", "supermarket") }
|
109
113
|
before { subject.add(cookbook, double(platforms: nil, dependencies: nil)) }
|
110
114
|
|
111
115
|
it "empties items added to the cache" do
|
@@ -25,30 +25,50 @@ describe Berkshelf::API::Endpoint::V1 do
|
|
25
25
|
subject { last_response }
|
26
26
|
let(:app_cache) { cache_manager.cache }
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
it 'has the right status' do
|
29
|
+
expect(subject.status).to eq(200)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has the right body' do
|
33
|
+
expect(subject.body).to eq(app_cache.to_json)
|
34
|
+
end
|
30
35
|
end
|
31
36
|
context "the user requests json" do
|
32
37
|
subject { last_response }
|
33
38
|
let(:app_cache) { cache_manager.cache }
|
34
39
|
let(:rack_env) { { 'HTTP_ACCEPT' => 'application/json' } }
|
35
40
|
|
36
|
-
|
37
|
-
|
41
|
+
it 'has the right status' do
|
42
|
+
expect(subject.status).to eq(200)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'has the right body' do
|
46
|
+
expect(subject.body).to eq(app_cache.to_json)
|
47
|
+
end
|
38
48
|
end
|
39
49
|
context "the user requests msgpack" do
|
40
50
|
subject { last_response }
|
41
51
|
let(:app_cache) { cache_manager.cache }
|
42
52
|
let(:rack_env) { { 'HTTP_ACCEPT' => 'application/x-msgpack' } }
|
43
53
|
|
44
|
-
|
45
|
-
|
54
|
+
it 'has the right status' do
|
55
|
+
expect(subject.status).to eq(200)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'has the right body' do
|
59
|
+
expect(subject.body).to eq(app_cache.to_msgpack)
|
60
|
+
end
|
46
61
|
end
|
47
62
|
end
|
48
63
|
|
49
64
|
context "the cache is still warming" do
|
50
|
-
|
51
|
-
|
65
|
+
it 'has the right status' do
|
66
|
+
expect(subject.status).to eq(503)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'has the right headers' do
|
70
|
+
expect(subject.headers).to have_key('Retry-After')
|
71
|
+
end
|
52
72
|
end
|
53
73
|
end
|
54
74
|
|
@@ -62,13 +82,39 @@ describe Berkshelf::API::Endpoint::V1 do
|
|
62
82
|
context "the cache has been warmed" do
|
63
83
|
let(:cache_warm) { true }
|
64
84
|
|
65
|
-
|
66
|
-
|
85
|
+
it 'has the right status' do
|
86
|
+
expect(subject.status).to eq(200)
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'has the right body' do
|
90
|
+
status = {
|
91
|
+
status: 'ok',
|
92
|
+
version: Berkshelf::API::VERSION,
|
93
|
+
cache_status: 'ok',
|
94
|
+
uptime: 100.0,
|
95
|
+
}.to_json
|
96
|
+
|
97
|
+
expect(subject.body).to eq(status)
|
98
|
+
end
|
67
99
|
end
|
68
100
|
|
69
101
|
context "the cache is still warming" do
|
70
|
-
|
71
|
-
|
102
|
+
let(:cache_warm) { false }
|
103
|
+
|
104
|
+
it 'has the right status' do
|
105
|
+
expect(subject.status).to eq(200)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'has the right body' do
|
109
|
+
status = {
|
110
|
+
status: 'ok',
|
111
|
+
version: Berkshelf::API::VERSION,
|
112
|
+
cache_status: 'warming',
|
113
|
+
uptime: 100.0,
|
114
|
+
}.to_json
|
115
|
+
|
116
|
+
expect(subject.body).to eq(status)
|
117
|
+
end
|
72
118
|
end
|
73
119
|
end
|
74
120
|
end
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Berkshelf::API::RackApp do
|
4
|
-
|
5
|
-
|
4
|
+
describe '.endpoints' do
|
5
|
+
it 'has at least one item' do
|
6
|
+
expect(described_class.endpoints.size).to be > 0
|
7
|
+
end
|
8
|
+
end
|
6
9
|
end
|
@@ -1,19 +1,40 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'berkshelf/api/rest_gateway'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
describe
|
7
|
-
let(:options) {
|
4
|
+
module Berkshelf
|
5
|
+
module API
|
6
|
+
describe RESTGateway do
|
7
|
+
let(:options) { {} }
|
8
8
|
subject { described_class.new(options) }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
describe '.new' do
|
11
|
+
context 'when given a different port' do
|
12
|
+
before do
|
13
|
+
options[:port] = 26210
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
it 'uses the correct port' do
|
17
|
+
expect(subject.port).to eq(26210)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#host' do
|
23
|
+
it 'has the default value' do
|
24
|
+
expect(subject.host).to eq(described_class::DEFAULT_OPTIONS[:host])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#port' do
|
29
|
+
it 'has the default value' do
|
30
|
+
expect(subject.port).to eq(described_class::DEFAULT_OPTIONS[:port])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#app' do
|
35
|
+
it 'has the default value' do
|
36
|
+
expect(subject.app).to be_a(RackApp)
|
37
|
+
end
|
17
38
|
end
|
18
39
|
end
|
19
40
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Berkshelf::API::SiteConnector::Supermarket do
|
4
|
+
let(:url) { 'https://example.com' }
|
5
|
+
let(:json) do
|
6
|
+
<<-EOH.gsub(/^ {6}/, '')
|
7
|
+
{
|
8
|
+
"berkshelf": {
|
9
|
+
"0.1.0": {
|
10
|
+
"location_type": "supermarket",
|
11
|
+
"location_path": "#{url}",
|
12
|
+
"download_url": "#{url}/cookbooks/berkshelf/versions/0.1.0/download",
|
13
|
+
"dependencies": {
|
14
|
+
"ruby": ">= 0.0.0"
|
15
|
+
}
|
16
|
+
},
|
17
|
+
"0.2.0": {
|
18
|
+
"location_type": "supermarket",
|
19
|
+
"location_path": "#{url}",
|
20
|
+
"download_url": "#{url}/cookbooks/berkshelf/versions/0.2.0/download",
|
21
|
+
"dependencies": {
|
22
|
+
"ruby": ">= 0.0.0"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
EOH
|
28
|
+
end
|
29
|
+
|
30
|
+
subject { described_class.new(url: url) }
|
31
|
+
|
32
|
+
before do
|
33
|
+
allow(subject).to receive(:open)
|
34
|
+
.and_return(double(File, read: json))
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#universe" do
|
38
|
+
it "uses OpenURI to get the universe" do
|
39
|
+
expect(subject).to receive(:open)
|
40
|
+
.with("#{url}/universe.json", kind_of(Hash))
|
41
|
+
|
42
|
+
subject.universe
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'parses the response as JSON' do
|
46
|
+
expect(subject.universe).to be_a(Hash)
|
47
|
+
expect(subject.universe).to have_key('berkshelf')
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'when the server does not respond' do
|
51
|
+
before do
|
52
|
+
allow(subject).to receive(:open)
|
53
|
+
.and_raise(Timeout::Error)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'catches and logs the error' do
|
57
|
+
expect(subject.log).to receive(:error).with(/in 15 seconds/)
|
58
|
+
expect { subject.universe }.to_not raise_error
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when the response is not valid JSON' do
|
63
|
+
let(:json) { 'bad json' }
|
64
|
+
|
65
|
+
it 'catches a JSON::ParserError' do
|
66
|
+
expect(subject.log).to receive(:error).with(/^Failed to parse JSON/)
|
67
|
+
expect { subject.universe }.to_not raise_error
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
[
|
72
|
+
SocketError,
|
73
|
+
Errno::ECONNREFUSED,
|
74
|
+
Errno::ECONNRESET,
|
75
|
+
Errno::ENETUNREACH,
|
76
|
+
].each do |error|
|
77
|
+
context "when `#{error}' is raised" do
|
78
|
+
before do
|
79
|
+
allow(subject).to receive(:open)
|
80
|
+
.and_raise(error)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "catches and logs the error" do
|
84
|
+
expect(subject.log).to receive(:error).with(/^Failed to get/)
|
85
|
+
expect { subject.universe }.to_not raise_error
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|