fleet-api 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+ require 'fleet/configuration'
3
+
4
+ describe Fleet::Configuration do
5
+
6
+ subject { Class.new { extend Fleet::Configuration } }
7
+
8
+ describe 'exposed attribes' do
9
+ Fleet::Configuration::VALID_OPTIONS_KEYS.each do |key|
10
+ it { should respond_to key.to_sym }
11
+ end
12
+ end
13
+
14
+ describe 'default values' do
15
+
16
+ describe 'adapter' do
17
+ it 'is matches DEFAULT_ADAPTER' do
18
+ expect(subject.adapter).to eq Fleet::Configuration::DEFAULT_ADAPTER
19
+ end
20
+ end
21
+
22
+ describe 'fleet_api_url' do
23
+ it 'is matches DEFAULT_ETCD_API_URL' do
24
+ expect(subject.fleet_api_url).to eq Fleet::Configuration::DEFAULT_ETCD_API_URL
25
+ end
26
+ end
27
+
28
+ describe 'open_timeout' do
29
+ it 'is matches DEFAULT_OPEN_TIMEOUT' do
30
+ expect(subject.open_timeout).to eq Fleet::Configuration::DEFAULT_OPEN_TIMEOUT
31
+ end
32
+ end
33
+
34
+ describe 'read_timeout' do
35
+ it 'is matches DEFAULT_READ_TIMEOUT' do
36
+ expect(subject.read_timeout).to eq Fleet::Configuration::DEFAULT_READ_TIMEOUT
37
+ end
38
+ end
39
+
40
+ describe 'logger' do
41
+ it 'is matches DEFAULT_LOGGER' do
42
+ expect(subject.logger).to eq Fleet::Configuration::DEFAULT_LOGGER
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fleet::Connection do
4
+
5
+ describe 'registered middleware' do
6
+
7
+ subject { Fleet::Client.new.connection }
8
+
9
+ handlers = [
10
+ Faraday::Request::UrlEncoded,
11
+ FaradayMiddleware::ParseJson,
12
+ Middleware::Response::RaiseError,
13
+ Faraday::Adapter::NetHttp
14
+ ]
15
+
16
+ handlers.each do |handler|
17
+ it { expect(subject.builder.handlers).to include handler }
18
+ end
19
+
20
+ it "includes exactly #{handlers.count} handlers" do
21
+ expect(subject.builder.handlers.count).to eql handlers.count
22
+ end
23
+ end
24
+
25
+ describe 'connection options' do
26
+
27
+ let(:url) { 'http://foo.com/bar' }
28
+ let(:ssl_options) { { verify: true } }
29
+ let(:proxy) { 'http://proxy.com' }
30
+
31
+ subject do
32
+ Fleet::Client.new(
33
+ fleet_api_url: url,
34
+ ssl_options: ssl_options,
35
+ proxy: proxy).connection
36
+ end
37
+
38
+ describe 'scheme' do
39
+ it 'matches the scheme of the URL' do
40
+ expect(subject.scheme).to eq 'http'
41
+ end
42
+ end
43
+
44
+ describe 'host' do
45
+ it 'matches the host of the URL' do
46
+ expect(subject.host).to eq 'foo.com'
47
+ end
48
+ end
49
+
50
+ describe 'port' do
51
+ it 'matches the port of the URL' do
52
+ expect(subject.port).to eq 80
53
+ end
54
+ end
55
+
56
+ describe 'path_prefix' do
57
+ it 'matches the path of the URL' do
58
+ expect(subject.path_prefix).to eq '/bar'
59
+ end
60
+ end
61
+
62
+ describe 'ssl' do
63
+ it 'matches the specified SSL options' do
64
+ expect(subject.ssl).to eq ssl_options
65
+ end
66
+ end
67
+
68
+ describe 'proxy' do
69
+ it 'matches the specified SSL options' do
70
+ expect(subject.proxy[:uri].to_s).to eq proxy
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fleet::Error do
4
+
5
+ let(:message) { 'some message' }
6
+ let(:error_code) { 12345 }
7
+ let(:cause) { 'user error' }
8
+
9
+ subject { Fleet::Error.new(message, error_code, cause) }
10
+
11
+ it { should respond_to(:message) }
12
+ it { should respond_to(:error_code) }
13
+ it { should respond_to(:cause) }
14
+
15
+ describe '#initialize' do
16
+
17
+ it 'saves the passed-in message' do
18
+ expect(subject.message).to eq message
19
+ end
20
+
21
+ it 'saves the passed-in error code' do
22
+ expect(subject.error_code).to eq error_code
23
+ end
24
+
25
+ it 'saves the passed-in cause' do
26
+ expect(subject.cause).to eq cause
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fleet::Request do
4
+
5
+ subject { Fleet::Client.new }
6
+
7
+ let(:path) { '/path' }
8
+
9
+ let(:request) do
10
+ double(:request,
11
+ options: {},
12
+ headers: {},
13
+ params: {},
14
+ 'headers=' => nil,
15
+ 'path=' => nil)
16
+ end
17
+
18
+ let(:response) do
19
+ double(:response, body: 'foo')
20
+ end
21
+
22
+ let(:connection) { double(:connection) }
23
+
24
+ before do
25
+ allow(connection).to receive(:send).and_yield(request).and_return(response)
26
+ allow(subject).to receive(:connection).and_return(connection)
27
+ end
28
+
29
+ [:get, :delete, :head, :put, :post].each do |method|
30
+
31
+ context "##{method}" do
32
+
33
+ it 'sets the path' do
34
+ expect(request).to receive(:path=).with(path)
35
+ subject.send(method, path)
36
+ end
37
+
38
+ it 'sets the headers' do
39
+ headers = { foo: :bar }
40
+ expect(request).to receive(:headers=).with(hash_including(headers))
41
+ subject.send(method, path, {}, headers)
42
+ end
43
+
44
+ it 'returns the response body' do
45
+ expect(subject.send(method, path)).to eql(response.body)
46
+ end
47
+
48
+ context 'when a Faraday::Error::ConnectionFailed error is raised' do
49
+
50
+ before do
51
+ allow(connection).to receive(:send)
52
+ .and_raise(Faraday::Error::ConnectionFailed, 'oops')
53
+ end
54
+
55
+ it 'raises a Fleet::ConnectionError' do
56
+ expect { subject.send(method, path) }.to raise_error(Fleet::ConnectionError, 'oops')
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ [:get, :delete, :head].each do |method|
63
+
64
+ context "##{method}" do
65
+
66
+ context 'when options provided' do
67
+
68
+ it 'sets options on the request' do
69
+ options = { a: :b }
70
+ expect(request).to receive(:params=).with(options)
71
+ subject.send(method, path, options)
72
+ end
73
+ end
74
+
75
+ context 'when no options provided' do
76
+
77
+ it 'does not set options on the request' do
78
+ expect(request).to_not receive(:params=)
79
+ subject.send(method, path)
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ [:put, :post].each do |method|
86
+
87
+ context "##{method}" do
88
+
89
+ context 'when options provided' do
90
+
91
+ it 'sets options on the request' do
92
+ options = { a: :b }
93
+ expect(request).to receive(:body=).with(options)
94
+ subject.send(method, path, options)
95
+ end
96
+ end
97
+
98
+ context 'when no options provided' do
99
+
100
+ it 'does not set options on the request' do
101
+ expect(request).to_not receive(:body=)
102
+ subject.send(method, path)
103
+ end
104
+ end
105
+
106
+ context 'when querystring AND body provided' do
107
+ let(:options) { { querystring: { a: :b }, body: { c: :d } } }
108
+
109
+ before do
110
+ allow(request).to receive(:params=)
111
+ allow(request).to receive(:body=)
112
+ end
113
+
114
+ it 'sets the querystring as request params' do
115
+ expect(request).to receive(:params=).with(options[:querystring])
116
+ subject.send(method, path, options)
117
+ end
118
+
119
+ it 'sets the body as request body' do
120
+ expect(request).to receive(:body=).with(options[:body])
121
+ subject.send(method, path, options)
122
+ end
123
+ end
124
+
125
+ end
126
+ end
127
+
128
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fleet::ServiceDefinition do
4
+
5
+ let(:name) { 'myservice.service' }
6
+
7
+ let(:service_hash) do
8
+ {
9
+ 'Unit' => {
10
+ 'Description' => 'infinite loop'
11
+ },
12
+ 'Service' => {
13
+ 'ExecStart' => "/bin/bash -c \"while true; do sleep 1; done\""
14
+ }
15
+ }
16
+ end
17
+
18
+ subject { described_class.new(name) }
19
+
20
+ it { should respond_to :name }
21
+
22
+ describe '#initialize' do
23
+
24
+ subject { described_class.new(name) }
25
+
26
+ describe 'name' do
27
+ it 'should equal the passed-in name' do
28
+ expect(subject.name).to eq name
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#to_unit' do
34
+
35
+ subject { described_class.new(name, service_hash) }
36
+
37
+ it 'provides a fleet formatted unit definition' do
38
+
39
+ raw = <<UNIT_FILE
40
+ [Unit]
41
+ Description=#{service_hash['Unit']['Description']}
42
+
43
+ [Service]
44
+ ExecStart=#{service_hash['Service']['ExecStart']}
45
+ UNIT_FILE
46
+
47
+ expected = {
48
+ 'Contents' => {
49
+ 'Unit' => {
50
+ 'Description' => [service_hash['Unit']['Description']]
51
+ },
52
+ 'Service' => {
53
+ 'ExecStart' => [service_hash['Service']['ExecStart']]
54
+ }
55
+ },
56
+ 'Raw' => raw
57
+ }
58
+
59
+ expect(subject.to_unit).to eq expected
60
+ end
61
+ end
62
+
63
+ describe '#to_job' do
64
+
65
+ subject { described_class.new(name, service_hash) }
66
+
67
+ it 'generates the appropriate job definition' do
68
+
69
+ expected = {
70
+ 'Name' => name,
71
+ 'UnitHash' => [111, 150, 87, 109, 217, 26, 190, 221, 31, 28, 8, 211, 198, 126, 76, 157, 106, 164, 220, 134]
72
+ }
73
+
74
+ expect(subject.to_job).to eq expected
75
+ end
76
+ end
77
+
78
+ describe '#sha1' do
79
+
80
+ subject { described_class.new(name, service_hash) }
81
+
82
+ it 'generates the appropriate sha1 hash' do
83
+ expect(subject.sha1).to eq '6f96576dd91abedd1f1c08d3c67e4c9d6aa4dc86'
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fleet do
4
+
5
+ after do
6
+ Fleet.reset
7
+ end
8
+
9
+ describe '.new' do
10
+
11
+ it 'returns a Fleet::Client' do
12
+ expect(Fleet.new).to be_a Fleet::Client
13
+ end
14
+
15
+ context 'when no options specified' do
16
+
17
+ Fleet::Configuration::VALID_OPTIONS_KEYS.each do |option|
18
+
19
+ it "new Fleet::Client inherits :#{option} default from Fleet" do
20
+ expect(Fleet.new.send(option)).to eq Fleet.send(option)
21
+ end
22
+ end
23
+ end
24
+
25
+ context 'when options are specified' do
26
+
27
+ Fleet::Configuration::VALID_OPTIONS_KEYS.each do |option|
28
+
29
+ it "new Fleet::Client receives specified :#{option} value" do
30
+ expect(Fleet.new({option => 'foo'}).send(option)).to eq 'foo'
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ describe '.fleet_api_url' do
37
+
38
+ let(:url) { 'http://foo.com/bar' }
39
+
40
+ before do
41
+ stub_const('Fleet::Configuration::DEFAULT_ETCD_API_URL', url)
42
+ Fleet.reset
43
+ end
44
+
45
+ it 'defaults to the value of DEFAULT_ETCD_API_URL' do
46
+ expect(Fleet.fleet_api_url).to eq url
47
+ end
48
+ end
49
+
50
+ describe '.open_timeout' do
51
+ it 'defaults to 2' do
52
+ expect(Fleet.open_timeout).to eq 2
53
+ end
54
+ end
55
+
56
+ describe '.read_timeout' do
57
+ it 'defaults to 5' do
58
+ expect(Fleet.read_timeout).to eq 5
59
+ end
60
+ end
61
+
62
+ describe '.ssl_options' do
63
+ it 'defaults to { verify: false }' do
64
+ expect(Fleet.ssl_options).to eq(verify: false)
65
+ end
66
+ end
67
+
68
+ describe '.proxy' do
69
+ it 'defaults to nil' do
70
+ expect(Fleet.proxy).to be_nil
71
+ end
72
+ end
73
+
74
+ describe '.configure' do
75
+ it "accepts a block" do
76
+ expect { Fleet.configure {} }.to_not raise_error
77
+ end
78
+
79
+ it "yields self" do
80
+ Fleet.configure { |conf| expect(conf).to be(Fleet) }
81
+ end
82
+
83
+ it "returns true" do
84
+ expect(Fleet.configure {}).to eq true
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe Middleware::Response::RaiseError do
4
+
5
+ describe '#on_complete' do
6
+
7
+ context 'when HTTP status is 200' do
8
+
9
+ let(:env) { { status: 200 } }
10
+
11
+ it 'raises no errors' do
12
+ expect { subject.on_complete(env) }.to_not raise_error
13
+ end
14
+ end
15
+
16
+ context 'when the HTTP status is a known error (404)' do
17
+
18
+ let(:message) { 'not found' }
19
+ let(:error_code) { 999 }
20
+ let(:cause) { 'just because ' }
21
+
22
+ let(:env) do
23
+ {
24
+ status: 404,
25
+ body: "{ \"message\": \"#{message}\", \"errorCode\": #{error_code}, \"cause\": \"#{cause}\" }"
26
+ }
27
+ end
28
+
29
+ it 'raises a NotFound execption' do
30
+ expect { subject.on_complete(env) }.to raise_error(Fleet::NotFound)
31
+ end
32
+
33
+ it 'sets the message on the exception' do
34
+ begin
35
+ subject.on_complete(env)
36
+ rescue Fleet::NotFound => ex
37
+ expect(ex.message).to eq message
38
+ end
39
+ end
40
+
41
+ it 'sets the error code on the exception' do
42
+ begin
43
+ subject.on_complete(env)
44
+ rescue Fleet::NotFound => ex
45
+ expect(ex.error_code).to eq error_code
46
+ end
47
+ end
48
+
49
+ it 'sets the cause on the exception' do
50
+ begin
51
+ subject.on_complete(env)
52
+ rescue Fleet::NotFound => ex
53
+ expect(ex.cause).to eq cause
54
+ end
55
+ end
56
+ end
57
+
58
+ context 'when HTTP status is an unknown error' do
59
+
60
+ let(:env) do
61
+ {
62
+ status: 499,
63
+ body: "{ \"message\": \"err\" }"
64
+ }
65
+ end
66
+
67
+ it 'raises an Error execption' do
68
+ expect { subject.on_complete(env) }.to raise_error(Fleet::Error)
69
+ end
70
+ end
71
+
72
+ context 'when error body is not JSON parseable' do
73
+
74
+ let(:env) do
75
+ {
76
+ status: 499,
77
+ body: 'FOO BAR'
78
+ }
79
+ end
80
+
81
+ it 'sets the error message to be the response body' do
82
+ begin
83
+ subject.on_complete(env)
84
+ rescue Fleet::Error => ex
85
+ expect(ex.message).to eq env[:body]
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,9 @@
1
+ require 'simplecov'
2
+ require 'simplecov-rcov'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
5
+ SimpleCov.start do
6
+ add_filter '/spec'
7
+ end
8
+
9
+ require 'fleet'