fleet-api 0.0.1

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.
@@ -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'