synapse 0.12.1 → 0.12.2
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/.travis.yml +1 -0
- data/README.md +64 -55
- data/lib/synapse.rb +6 -6
- data/lib/synapse/file_output.rb +12 -1
- data/lib/synapse/haproxy.rb +14 -4
- data/lib/synapse/service_watcher.rb +11 -19
- data/lib/synapse/service_watcher/README.md +84 -0
- data/lib/synapse/service_watcher/base.rb +3 -3
- data/lib/synapse/service_watcher/dns.rb +1 -1
- data/lib/synapse/service_watcher/docker.rb +4 -3
- data/lib/synapse/service_watcher/ec2tag.rb +13 -9
- data/lib/synapse/service_watcher/marathon.rb +112 -0
- data/lib/synapse/service_watcher/zookeeper.rb +12 -7
- data/lib/synapse/service_watcher/zookeeper_dns.rb +3 -3
- data/lib/synapse/version.rb +1 -1
- data/spec/lib/synapse/file_output_spec.rb +61 -0
- data/spec/lib/synapse/haproxy_spec.rb +14 -1
- data/spec/lib/synapse/service_watcher_base_spec.rb +3 -3
- data/spec/lib/synapse/service_watcher_docker_spec.rb +12 -6
- data/spec/lib/synapse/service_watcher_ec2tags_spec.rb +36 -14
- data/spec/lib/synapse/service_watcher_marathon_spec.rb +191 -0
- data/spec/lib/synapse/service_watcher_spec.rb +102 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/minimum.conf.yaml +6 -1
- data/synapse.gemspec +1 -0
- metadata +26 -2
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'synapse/service_watcher/marathon'
|
3
|
+
|
4
|
+
describe Synapse::ServiceWatcher::MarathonWatcher do
|
5
|
+
let(:mocksynapse) { double() }
|
6
|
+
let(:marathon_host) { '127.0.0.1' }
|
7
|
+
let(:marathon_port) { '8080' }
|
8
|
+
let(:app_name) { 'foo' }
|
9
|
+
let(:check_interval) { 11 }
|
10
|
+
let(:marathon_request_uri) { "#{marathon_host}:#{marathon_port}/v2/apps/#{app_name}/tasks" }
|
11
|
+
let(:config) do
|
12
|
+
{
|
13
|
+
'name' => 'foo',
|
14
|
+
'discovery' => {
|
15
|
+
'method' => 'marathon',
|
16
|
+
'marathon_api_url' => "http://#{marathon_host}:#{marathon_port}",
|
17
|
+
'application_name' => app_name,
|
18
|
+
'check_interval' => check_interval,
|
19
|
+
},
|
20
|
+
'haproxy' => {},
|
21
|
+
}
|
22
|
+
end
|
23
|
+
let(:marathon_response) { { 'tasks' => [] } }
|
24
|
+
|
25
|
+
subject { described_class.new(config, mocksynapse) }
|
26
|
+
|
27
|
+
before do
|
28
|
+
allow(subject.log).to receive(:warn)
|
29
|
+
allow(subject.log).to receive(:info)
|
30
|
+
|
31
|
+
allow(Thread).to receive(:new).and_yield
|
32
|
+
allow(subject).to receive(:sleep)
|
33
|
+
allow(subject).to receive(:only_run_once?).and_return(true)
|
34
|
+
allow(subject).to receive(:splay).and_return(0)
|
35
|
+
|
36
|
+
stub_request(:get, marathon_request_uri).
|
37
|
+
with(:headers => { 'Accept' => 'application/json' }).
|
38
|
+
to_return(:body => JSON.generate(marathon_response))
|
39
|
+
end
|
40
|
+
|
41
|
+
context 'with a valid argument hash' do
|
42
|
+
it 'instantiates' do
|
43
|
+
expect(subject).to be_a(Synapse::ServiceWatcher::MarathonWatcher)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#watch' do
|
48
|
+
context 'when synapse cannot connect to marathon' do
|
49
|
+
before do
|
50
|
+
allow(Net::HTTP).to receive(:new).
|
51
|
+
with(marathon_host, marathon_port.to_i).
|
52
|
+
and_raise(Errno::ECONNREFUSED)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'does not crash' do
|
56
|
+
expect { subject.start }.not_to raise_error
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'requests the proper API endpoint one time' do
|
61
|
+
subject.start
|
62
|
+
expect(a_request(:get, marathon_request_uri)).to have_been_made.times(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
context 'when the API path (marathon_api_path) is customized' do
|
66
|
+
let(:config) do
|
67
|
+
super().tap do |c|
|
68
|
+
c['discovery']['marathon_api_path'] = '/v3/tasks/%{app}'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
let(:marathon_request_uri) { "#{marathon_host}:#{marathon_port}/v3/tasks/#{app_name}" }
|
73
|
+
|
74
|
+
it 'calls the customized path' do
|
75
|
+
subject.start
|
76
|
+
expect(a_request(:get, marathon_request_uri)).to have_been_made.times(1)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'with tasks returned from marathon' do
|
81
|
+
let(:marathon_response) do
|
82
|
+
{
|
83
|
+
'tasks' => [
|
84
|
+
{
|
85
|
+
'host' => 'agouti.local',
|
86
|
+
'id' => 'my-app_1-1396592790353',
|
87
|
+
'ports' => [
|
88
|
+
31336,
|
89
|
+
31337
|
90
|
+
],
|
91
|
+
'stagedAt' => '2014-04-04T06:26:30.355Z',
|
92
|
+
'startedAt' => '2014-04-04T06:26:30.860Z',
|
93
|
+
'version' => '2014-04-04T06:26:23.051Z'
|
94
|
+
},
|
95
|
+
]
|
96
|
+
}
|
97
|
+
end
|
98
|
+
let(:expected_backend_hash) do
|
99
|
+
{
|
100
|
+
'name' => 'agouti.local', 'host' => 'agouti.local', 'port' => 31336
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'adds the task as a backend' do
|
105
|
+
expect(subject).to receive(:set_backends).with([expected_backend_hash])
|
106
|
+
subject.start
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'with a custom port_index' do
|
110
|
+
let(:config) do
|
111
|
+
super().tap do |c|
|
112
|
+
c['discovery']['port_index'] = 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
let(:expected_backend_hash) do
|
117
|
+
{
|
118
|
+
'name' => 'agouti.local', 'host' => 'agouti.local', 'port' => 31337
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'adds the task as a backend' do
|
123
|
+
expect(subject).to receive(:set_backends).with([expected_backend_hash])
|
124
|
+
subject.start
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'when that port_index does not exist' do
|
128
|
+
let(:config) do
|
129
|
+
super().tap { |c| c['discovery']['port_index'] = 999 }
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'does not include the backend' do
|
133
|
+
expect(subject).to receive(:set_backends).with([])
|
134
|
+
subject.start
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
context 'with a task that has not started yet' do
|
140
|
+
let(:marathon_response) do
|
141
|
+
super().tap do |resp|
|
142
|
+
resp['tasks'] << {
|
143
|
+
'host' => 'agouti.local',
|
144
|
+
'id' => 'my-app_2-1396592790353',
|
145
|
+
'ports' => [
|
146
|
+
31336,
|
147
|
+
31337
|
148
|
+
],
|
149
|
+
'stagedAt' => '2014-04-04T06:26:30.355Z',
|
150
|
+
'startedAt' => nil,
|
151
|
+
'version' => '2014-04-04T06:26:23.051Z'
|
152
|
+
}
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'filters tasks that have no startedAt value' do
|
157
|
+
expect(subject).to receive(:set_backends).with([expected_backend_hash])
|
158
|
+
subject.start
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'when marathon returns invalid response' do
|
163
|
+
let(:marathon_response) { [] }
|
164
|
+
it 'does not blow up' do
|
165
|
+
expect { subject.start }.to_not raise_error
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context 'when the job takes a long time for some reason' do
|
170
|
+
let(:job_duration) { 10 } # seconds
|
171
|
+
|
172
|
+
before do
|
173
|
+
actual_time = Time.now
|
174
|
+
time_offset = -1 * job_duration
|
175
|
+
allow(Time).to receive(:now) do
|
176
|
+
# on first run, return the right time
|
177
|
+
# subsequently, add in our job_duration offset
|
178
|
+
actual_time + (time_offset += job_duration)
|
179
|
+
end
|
180
|
+
allow(subject).to receive(:set_backends)
|
181
|
+
end
|
182
|
+
|
183
|
+
it 'only sleeps for the difference' do
|
184
|
+
expect(subject).to receive(:sleep).with(check_interval - job_duration)
|
185
|
+
subject.start
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'synapse/service_watcher'
|
3
|
+
|
4
|
+
describe Synapse::ServiceWatcher do
|
5
|
+
let(:mock_synapse) { double }
|
6
|
+
subject { Synapse::ServiceWatcher }
|
7
|
+
let(:config) do
|
8
|
+
{
|
9
|
+
'haproxy' => {
|
10
|
+
'port' => '8080',
|
11
|
+
'server_port_override' => '8081',
|
12
|
+
},
|
13
|
+
'discovery' => {
|
14
|
+
'method' => 'test'
|
15
|
+
}
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def replace_discovery(new_value)
|
20
|
+
args = config.clone
|
21
|
+
args['discovery'] = new_value
|
22
|
+
args
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'bogus arguments' do
|
26
|
+
it 'complains if discovery method is bogus' do
|
27
|
+
expect {
|
28
|
+
subject.create('test', config, mock_synapse)
|
29
|
+
}.to raise_error(ArgumentError)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'service watcher dispatch' do
|
34
|
+
let (:zookeeper_config) {{
|
35
|
+
'method' => 'zookeeper',
|
36
|
+
'hosts' => 'localhost:2181',
|
37
|
+
'path' => '/smartstack',
|
38
|
+
}}
|
39
|
+
let (:dns_config) {{
|
40
|
+
'method' => 'dns',
|
41
|
+
'servers' => ['localhost'],
|
42
|
+
}}
|
43
|
+
let (:docker_config) {{
|
44
|
+
'method' => 'docker',
|
45
|
+
'servers' => 'localhost',
|
46
|
+
'image_name' => 'servicefoo',
|
47
|
+
'container_port' => 1234,
|
48
|
+
}}
|
49
|
+
let (:ec2_config) {{
|
50
|
+
'method' => 'ec2tag',
|
51
|
+
'tag_name' => 'footag',
|
52
|
+
'tag_value' => 'barvalue',
|
53
|
+
'aws_access_key_id' => 'bogus',
|
54
|
+
'aws_secret_access_key' => 'morebogus',
|
55
|
+
'aws_region' => 'evenmorebogus',
|
56
|
+
}}
|
57
|
+
let (:zookeeper_dns_config) {{
|
58
|
+
'method' => 'zookeeper_dns',
|
59
|
+
'hosts' => 'localhost:2181',
|
60
|
+
'path' => '/smartstack',
|
61
|
+
}}
|
62
|
+
let (:marathon_config) {{
|
63
|
+
'method' => 'marathon',
|
64
|
+
'marathon_api_url' => 'localhost:12345',
|
65
|
+
'application_name' => 'foobar',
|
66
|
+
}}
|
67
|
+
|
68
|
+
it 'creates zookeeper correctly' do
|
69
|
+
expect {
|
70
|
+
subject.create('test', replace_discovery(zookeeper_config), mock_synapse)
|
71
|
+
}.not_to raise_error
|
72
|
+
end
|
73
|
+
it 'creates dns correctly' do
|
74
|
+
expect {
|
75
|
+
subject.create('test', replace_discovery(dns_config), mock_synapse)
|
76
|
+
}.not_to raise_error
|
77
|
+
end
|
78
|
+
it 'creates docker correctly' do
|
79
|
+
expect {
|
80
|
+
subject.create('test', replace_discovery(docker_config), mock_synapse)
|
81
|
+
}.not_to raise_error
|
82
|
+
end
|
83
|
+
it 'creates ec2tag correctly' do
|
84
|
+
expect {
|
85
|
+
subject.create('test', replace_discovery(ec2_config), mock_synapse)
|
86
|
+
}.not_to raise_error
|
87
|
+
end
|
88
|
+
it 'creates zookeeper_dns correctly' do
|
89
|
+
expect {
|
90
|
+
subject.create('test', replace_discovery(zookeeper_dns_config), mock_synapse)
|
91
|
+
}.not_to raise_error
|
92
|
+
end
|
93
|
+
it 'creates marathon correctly' do
|
94
|
+
expect {
|
95
|
+
subject.create('test', replace_discovery(marathon_config), mock_synapse)
|
96
|
+
}.not_to raise_error
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
data/spec/spec_helper.rb
CHANGED
data/synapse.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: synapse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.12.
|
4
|
+
version: 0.12.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-07
|
12
|
+
date: 2015-12-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
@@ -123,6 +123,22 @@ dependencies:
|
|
123
123
|
- - ! '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: webmock
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
126
142
|
description: ': Write a gem description'
|
127
143
|
email:
|
128
144
|
- martin.rhoads@airbnb.com
|
@@ -153,17 +169,22 @@ files:
|
|
153
169
|
- lib/synapse/haproxy.rb
|
154
170
|
- lib/synapse/log.rb
|
155
171
|
- lib/synapse/service_watcher.rb
|
172
|
+
- lib/synapse/service_watcher/README.md
|
156
173
|
- lib/synapse/service_watcher/base.rb
|
157
174
|
- lib/synapse/service_watcher/dns.rb
|
158
175
|
- lib/synapse/service_watcher/docker.rb
|
159
176
|
- lib/synapse/service_watcher/ec2tag.rb
|
177
|
+
- lib/synapse/service_watcher/marathon.rb
|
160
178
|
- lib/synapse/service_watcher/zookeeper.rb
|
161
179
|
- lib/synapse/service_watcher/zookeeper_dns.rb
|
162
180
|
- lib/synapse/version.rb
|
181
|
+
- spec/lib/synapse/file_output_spec.rb
|
163
182
|
- spec/lib/synapse/haproxy_spec.rb
|
164
183
|
- spec/lib/synapse/service_watcher_base_spec.rb
|
165
184
|
- spec/lib/synapse/service_watcher_docker_spec.rb
|
166
185
|
- spec/lib/synapse/service_watcher_ec2tags_spec.rb
|
186
|
+
- spec/lib/synapse/service_watcher_marathon_spec.rb
|
187
|
+
- spec/lib/synapse/service_watcher_spec.rb
|
167
188
|
- spec/spec_helper.rb
|
168
189
|
- spec/support/configuration.rb
|
169
190
|
- spec/support/minimum.conf.yaml
|
@@ -193,10 +214,13 @@ signing_key:
|
|
193
214
|
specification_version: 3
|
194
215
|
summary: ': Write a gem summary'
|
195
216
|
test_files:
|
217
|
+
- spec/lib/synapse/file_output_spec.rb
|
196
218
|
- spec/lib/synapse/haproxy_spec.rb
|
197
219
|
- spec/lib/synapse/service_watcher_base_spec.rb
|
198
220
|
- spec/lib/synapse/service_watcher_docker_spec.rb
|
199
221
|
- spec/lib/synapse/service_watcher_ec2tags_spec.rb
|
222
|
+
- spec/lib/synapse/service_watcher_marathon_spec.rb
|
223
|
+
- spec/lib/synapse/service_watcher_spec.rb
|
200
224
|
- spec/spec_helper.rb
|
201
225
|
- spec/support/configuration.rb
|
202
226
|
- spec/support/minimum.conf.yaml
|