berkshelf-api 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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