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
@@ -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["opscode"]).to eql(Berkshelf::API::CacheBuilder::Worker::Opscode)
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 { instance.stub(workers: workers) }
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
- instance.stub(:cache_manager).and_return(cache_manager)
18
- cache_manager.should_receive(:process_workers).with(instance.workers).and_return(future)
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 have(1).item
39
+ expect(workers.size).to eq(1)
36
40
  end
37
41
 
38
- it "has an opscode worker started by default" do
39
- expect(workers.first).to be_a(described_class::Worker::Opscode)
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 have(2).items
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 "::new" do
6
- subject { described_class.new }
7
- its(:cache) { should be_empty }
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
- pending
48
+ skip
48
49
  end
49
50
 
50
51
  describe "#load_save" do
51
- pending
52
+ skip
52
53
  end
53
54
 
54
55
  describe "#remove" do
55
- pending
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", "opscode", nil, 1) }
73
- let(:cookbook_two) { Berkshelf::API::RemoteCookbook.new("elixir", "2.0.0", "opscode", nil, 1) }
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 have(2).items
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", "opscode", nil, 2) }
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", "opscode", nil, 1) }
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", "opscode", nil, 1) }
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 have(1).item
16
+ expect(subject.endpoints.size).to eq(1)
17
17
  end
18
18
 
19
- it "has the Opscode community site as an endpoint" do
20
- expect(subject.endpoints.first.type).to eql("opscode")
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
- Berkshelf::API::RemoteCookbook.new("chicken", "1.0"),
81
- Berkshelf::API::RemoteCookbook.new("tuna", "3.0.0")
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) { Berkshelf::API::RemoteCookbook.new("ruby", "1.2.3", "opscode") }
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 have(1).item
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 be_true
107
+ expect(File.exist?(path)).to be_truthy
104
108
  end
105
109
  end
106
110
 
107
111
  describe "#clear" do
108
- let(:cookbook) { Berkshelf::API::RemoteCookbook.new("ruby", "1.2.3", "opscode") }
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
- its(:status) { should be(200) }
29
- its(:body) { should eq(app_cache.to_json) }
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
- its(:status) { should be(200) }
37
- its(:body) { should eq(app_cache.to_json) }
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
- its(:status) { should be(200) }
45
- its(:body) { should eq(app_cache.to_msgpack) }
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
- its(:status) { should be(503) }
51
- its(:headers) { should have_key("Retry-After") }
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
- its(:status) { should be(200) }
66
- its(:body) { should eq({status: 'ok', version: Berkshelf::API::VERSION, cache_status: 'ok', uptime: 100.0}.to_json) }
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
- its(:status) { should be(200) }
71
- its(:body) { should eq({status: 'ok', version: Berkshelf::API::VERSION, cache_status: 'warming', uptime: 100.0}.to_json) }
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
- subject { described_class }
5
- its(:endpoints) { should have(1).item.at_least }
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
- describe Berkshelf::API::RESTGateway do
5
- describe "ClassMethods" do
6
- describe "::new" do
7
- let(:options) { Hash.new }
4
+ module Berkshelf
5
+ module API
6
+ describe RESTGateway do
7
+ let(:options) { {} }
8
8
  subject { described_class.new(options) }
9
9
 
10
- its(:host) { should eql(described_class::DEFAULT_OPTIONS[:host]) }
11
- its(:port) { should eql(described_class::DEFAULT_OPTIONS[:port]) }
12
- its(:app) { should be_a(Berkshelf::API::RackApp) }
10
+ describe '.new' do
11
+ context 'when given a different port' do
12
+ before do
13
+ options[:port] = 26210
14
+ end
13
15
 
14
- context "given a different port" do
15
- before { options[:port] = 26210 }
16
- its(:port) { should eql(26210) }
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