synapse 0.12.2 → 0.13.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 34b7877f7f8196407e10fafab1a72354e861121c
4
+ data.tar.gz: 154d642f85c7a1d1ab13078a8adb1a75d295d993
5
+ SHA512:
6
+ metadata.gz: 06e858b8cd8a0c316baad80264754206ee64615f7ca0f7958ebf7d38a5b07d67968d949d09367dd127b525e1f6710611d48813af224fe3371bd1e2c78c4da343
7
+ data.tar.gz: 41be259d76cd50f950b4d6e2e217f4c68134a8f71cfcc75bf69842f7d5edee95bac61996412ba8b9a00057ceb52e651aa4837e2146c3c57432929fbbbfb1f641
data/README.md CHANGED
@@ -97,6 +97,11 @@ install synapse with:
97
97
 
98
98
  ```bash
99
99
  $ mkdir -p /opt/smartstack/synapse
100
+
101
+ # If you want to install specific versions of dependencies such as an older
102
+ # version of the aws-sdk, the docker-api, etc, gem install that here *before*
103
+ # gem installing synapse
104
+
100
105
  # If you are on Ruby 2.X use --no-document instead of --no-ri --no-rdoc
101
106
  $ gem install synapse --install-dir /opt/smartstack/synapse --no-ri --no-rdoc
102
107
  ```
@@ -141,25 +146,39 @@ Each value in the services hash is also a hash, and should contain the following
141
146
  We've included a number of `watchers` which provide service discovery.
142
147
  Put these into the `discovery` section of the service hash, with these options:
143
148
 
144
- ##### Stub #####
149
+ ##### Base #####
145
150
 
146
- The stub watcher is useful in situations where you only want to use the servers in the `default_servers` list.
151
+ The base watcher is useful in situations where you only want to use the servers in the `default_servers` list.
147
152
  It has only one option:
148
153
 
149
- * `method`: stub
154
+ * `method`: base
150
155
 
151
156
  ##### Zookeeper #####
152
157
 
153
158
  This watcher retrieves a list of servers from zookeeper.
154
- It takes the following options:
159
+ It takes the following mandatory arguments:
155
160
 
156
161
  * `method`: zookeeper
157
162
  * `path`: the zookeeper path where ephemeral nodes will be created for each available service server
158
163
  * `hosts`: the list of zookeeper servers to query
159
164
 
160
165
  The watcher assumes that each node under `path` represents a service server.
161
- Synapse attempts to decode the data in each of these nodes using JSON and also using Thrift under the standard Twitter service encoding.
162
- We assume that the data contains a hostname and a port for service servers.
166
+
167
+ The following arguments are optional:
168
+
169
+ * `decode`: A hash containing configuration for how to decode the data found in zookeeper.
170
+
171
+ ###### Decoding service nodes ######
172
+ Synapse attempts to decode the data in each of these nodes using JSON and you can control how it is decoded with the `decode` argument. If provided, the `decode` hash should contain the following:
173
+
174
+ * `method` (one of ['`nerve`', '`serverset`'], default: '`nerve`'): The kind of data to expect to find in zookeeper nodes
175
+ * `endpoint_name` (default: nil): If using the `serverset` method, this controls which of the `additionalEndpoints` is chosen instead of the `serviceEndpoint` data. If not supplied the `serverset` method will use the host/port from the `serviceEndpoint` data.
176
+
177
+ If the `method` is `nerve`, then we expect to find nerve registrations with a `host` and a `port`.
178
+
179
+ If the `method` is `serverset` then we expect to find Finagle ServerSet
180
+ (also used by [Aurora](https://github.com/apache/aurora/blob/master/docs/user-guide.md#service-discovery)) registrations with a `serviceEndpoint` and optionally one or more `additionalEndpoints`.
181
+ The Synapse `name` will be automatically deduced from `shard` if present.
163
182
 
164
183
  ##### Docker #####
165
184
 
@@ -232,6 +251,7 @@ by unsetting `use_previous_backends`.
232
251
  This section is its own hash, which should contain the following keys:
233
252
 
234
253
  * `port`: the port (on localhost) where HAProxy will listen for connections to the service. If this is omitted, only a backend stanza (and no frontend stanza) will be generated for this service; you'll need to get traffic to your service yourself via the `shared_frontend` or manual frontends in `extra_sections`
254
+ * `bind_address`: force HAProxy to listen on this address ( default is localhost ). Setting `bind_address` on a per service basis overrides the global `bind_address` in the top level `haproxy`. Having HAProxy listen for connections on different addresses ( example: service1 listen on 127.0.0.2:443 and service2 listen on 127.0.0.3:443) allows /etc/hosts entries to point to services.
235
255
  * `server_port_override`: the port that discovered servers listen on; you should specify this if your discovery mechanism only discovers names or addresses (like the DNS watcher). If the discovery method discovers a port along with hostnames (like the zookeeper watcher) this option may be left out, but will be used in preference if given.
236
256
  * `server_options`: the haproxy options for each `server` line of the service in HAProxy config; it may be left out.
237
257
  * `frontend`: additional lines passed to the HAProxy config in the `frontend` stanza of this service
@@ -239,6 +259,7 @@ This section is its own hash, which should contain the following keys:
239
259
  * `backend_name`: The name of the generated HAProxy backend for this service
240
260
  (defaults to the service's key in the `services` section)
241
261
  * `listen`: these lines will be parsed and placed in the correct `frontend`/`backend` section as applicable; you can put lines which are the same for the frontend and backend here.
262
+ * `backend_order`: optional: how backends should be ordered in the `backend` stanza. (default is shuffling). Setting to `asc` means sorting backends in ascending alphabetical order before generating stanza. `desc` means descending alphabetical order. `no_shuffle` means no shuffling or sorting.
242
263
  * `shared_frontend`: optional: haproxy configuration directives for a shared http frontend (see below)
243
264
 
244
265
  <a name="haproxy"/>
@@ -259,11 +280,16 @@ The top level `haproxy` section of the config file has the following options:
259
280
  * `restart_interval`: number of seconds to wait between restarts of haproxy (default: 2)
260
281
  * `restart_jitter`: percentage, expressed as a float, of jitter to multiply the `restart_interval` by when determining the next
261
282
  restart time. Use this to help prevent healthcheck storms when HAProxy restarts. (default: 0.0)
262
- * `state_file_path`: full path on disk (e.g. /tmp/synapse/state.json) for caching haproxy state between reloads.
263
- If provided, synapse will store recently seen backends at this location and can "remember" backends across both synapse and
264
- HAProxy restarts. Any backends that are "down" in the reporter but listed in the cache will be put into HAProxy disabled (default: nil)
265
- * `state_file_ttl`: the number of seconds that backends should be kept in the state file cache.
266
- This only applies if `state_file_path` is provided (default: 86400)
283
+ * `state_file_path`: full path on disk (e.g. /tmp/synapse/state.json) for
284
+ caching haproxy state between reloads. If provided, synapse will store
285
+ recently seen backends at this location and can "remember" backends across
286
+ both synapse and HAProxy restarts. Any backends that are "down" in the
287
+ reporter but listed in the cache will be put into HAProxy disabled. Synapse
288
+ writes the state file every sixty seconds, so the file's age can be used to
289
+ monitor that Synapse is alive and making progress. (default: nil)
290
+ * `state_file_ttl`: the number of seconds that backends should be kept in the
291
+ state file cache. This only applies if `state_file_path` is provided.
292
+ (default: 86400)
267
293
 
268
294
  Note that a non-default `bind_address` can be dangerous.
269
295
  If you configure an `address:port` combination that is already in use on the system, haproxy will fail to start.
@@ -686,7 +686,7 @@ module Synapse
686
686
  stanza = [
687
687
  "\nfrontend #{watcher.name}",
688
688
  config.map {|c| "\t#{c}"},
689
- "\tbind #{@opts['bind_address'] || 'localhost'}:#{watcher.haproxy['port']}",
689
+ "\tbind #{ watcher.haproxy['bind_address'] || @opts['bind_address'] || 'localhost'}:#{watcher.haproxy['port']}",
690
690
  "\tdefault_backend #{watcher.haproxy.fetch('backend_name', watcher.name)}"
691
691
  ]
692
692
  end
@@ -721,10 +721,20 @@ module Synapse
721
721
  log.debug "synapse: no backends found for watcher #{watcher.name}"
722
722
  end
723
723
 
724
+ keys = case watcher.haproxy['backend_order']
725
+ when 'asc'
726
+ backends.keys.sort
727
+ when 'desc'
728
+ backends.keys.sort.reverse
729
+ when 'no_shuffle'
730
+ backends.keys
731
+ else
732
+ backends.keys.shuffle
733
+ end
724
734
  stanza = [
725
735
  "\nbackend #{watcher.haproxy.fetch('backend_name', watcher.name)}",
726
736
  config.map {|c| "\t#{c}"},
727
- backends.keys.shuffle.map {|backend_name|
737
+ keys.map {|backend_name|
728
738
  backend = backends[backend_name]
729
739
  b = "\tserver #{backend_name} #{backend['host']}:#{backend['port']}"
730
740
  b = "#{b} cookie #{backend_name}" unless config.include?('mode tcp')
@@ -21,6 +21,7 @@ class Synapse::ServiceWatcher
21
21
 
22
22
  @name = opts['name']
23
23
  @discovery = opts['discovery']
24
+ @label_filter = @discovery['label_filter'] || false
24
25
 
25
26
  @leader_election = opts['leader_election'] || false
26
27
  @leader_last_warn = Time.now - LEADER_WARN_INTERVAL
@@ -86,6 +87,8 @@ class Synapse::ServiceWatcher
86
87
 
87
88
  # if leader election fails, return no backends
88
89
  return []
90
+ elsif @label_filter
91
+ return filter_backends_by_label(@backends, @label_filter)
89
92
  end
90
93
 
91
94
  return @backends
@@ -99,6 +102,17 @@ class Synapse::ServiceWatcher
99
102
  log.warn "synapse: warning: a stub watcher with no default servers is pretty useless" if @default_servers.empty?
100
103
  end
101
104
 
105
+ def filter_backends_by_label(backends, label_filter)
106
+ filtered_backends = []
107
+ backends.each do |backend|
108
+ backend_labels = backend['labels'] || {}
109
+ if label_filter['condition'] == 'equals' and backend_labels[label_filter['label']] == label_filter['value']
110
+ filtered_backends << backend
111
+ end
112
+ end
113
+ return filtered_backends
114
+ end
115
+
102
116
  def set_backends(new_backends)
103
117
  # Aggregate and deduplicate all potential backend service instances.
104
118
  new_backends = (new_backends + @default_servers) if @keep_default_servers
@@ -11,6 +11,24 @@ class Synapse::ServiceWatcher
11
11
  @@zk_pool_count = {}
12
12
  @@zk_pool_lock = Mutex.new
13
13
 
14
+ def initialize(opts={}, synapse)
15
+ super(opts, synapse)
16
+
17
+ # Alternative deserialization support. By default we use nerve
18
+ # deserialization, but we also support serverset registries
19
+ @decode_method = self.method(:nerve_decode)
20
+ if @discovery['decode']
21
+ valid_methods = ['nerve', 'serverset']
22
+ decode_method = @discovery['decode']['method']
23
+ unless decode_method && valid_methods.include?(decode_method)
24
+ raise ArgumentError, "missing or invalid decode method #{decode_method}"
25
+ end
26
+ if decode_method == 'serverset'
27
+ @decode_method = self.method(:serverset_decode)
28
+ end
29
+ end
30
+ end
31
+
14
32
  def start
15
33
  @zk_hosts = @discovery['hosts'].sort.join(',')
16
34
 
@@ -43,6 +61,57 @@ class Synapse::ServiceWatcher
43
61
  unless @discovery['path']
44
62
  end
45
63
 
64
+ # Supported decode methods
65
+
66
+ # Airbnb nerve ZK node data looks like this:
67
+ #
68
+ # {
69
+ # "host": "somehostname",
70
+ # "port": 1234,
71
+ # }
72
+ def nerve_decode(data)
73
+ JSON.parse(data)
74
+ end
75
+
76
+ # Twitter serverset ZK node data looks like this:
77
+ #
78
+ # {
79
+ # "additionalEndpoints": {
80
+ # "serverset": {
81
+ # "host": "somehostname",
82
+ # "port": 31943
83
+ # },
84
+ # "http": {
85
+ # "host": "somehostname",
86
+ # "port": 31943
87
+ # },
88
+ # "otherport": {
89
+ # "host": "somehostname",
90
+ # "port": 31944
91
+ # }
92
+ # },
93
+ # "serviceEndpoint": {
94
+ # "host": "somehostname",
95
+ # "port": 31943
96
+ # },
97
+ # "shard": 0,
98
+ # "status": "ALIVE"
99
+ # }
100
+ def serverset_decode(data)
101
+ decoded = JSON.parse(data)
102
+ if @discovery['decode']['endpoint_name']
103
+ endpoint_name = @discovery['decode']['endpoint_name']
104
+ raise KeyError, "json data has no additionalEndpoint called #{endpoint_name}" \
105
+ unless decoded['additionalEndpoints'] && decoded['additionalEndpoints'][endpoint_name]
106
+ result = decoded['additionalEndpoints'][endpoint_name]
107
+ else
108
+ result = decoded['serviceEndpoint']
109
+ end
110
+ result['name'] = decoded['shard'] || nil
111
+ result['name'] = result['name'].to_s unless result['name'].nil?
112
+ result
113
+ end
114
+
46
115
  # helper method that ensures that the discovery path exists
47
116
  def create(path)
48
117
  log.debug "synapse: creating ZK path: #{path}"
@@ -62,11 +131,11 @@ class Synapse::ServiceWatcher
62
131
 
63
132
  begin
64
133
  # TODO: Do less munging, or refactor out this processing
65
- host, port, name, weight, haproxy_server_options = deserialize_service_instance(node.first)
134
+ host, port, name, weight, haproxy_server_options, labels = deserialize_service_instance(node.first)
66
135
  rescue StandardError => e
67
136
  log.error "synapse: invalid data in ZK node #{id} at #{@discovery['path']}: #{e}"
68
137
  else
69
- server_port = @server_port_override ? @server_port_override : port
138
+ server_port = @haproxy['server_port_override'] ? @haproxy['server_port_override'] : port
70
139
 
71
140
  # find the numberic id in the node name; used for leader elections if enabled
72
141
  numeric_id = id.split('_').last
@@ -76,7 +145,8 @@ class Synapse::ServiceWatcher
76
145
  new_backends << {
77
146
  'name' => name, 'host' => host, 'port' => server_port,
78
147
  'id' => numeric_id, 'weight' => weight,
79
- 'haproxy_server_options' => haproxy_server_options
148
+ 'haproxy_server_options' => haproxy_server_options,
149
+ 'labels' => labels
80
150
  }
81
151
  end
82
152
  end
@@ -173,15 +243,17 @@ class Synapse::ServiceWatcher
173
243
  # decode the data at a zookeeper endpoint
174
244
  def deserialize_service_instance(data)
175
245
  log.debug "synapse: deserializing process data"
176
- decoded = JSON.parse(data)
246
+ decoded = @decode_method.call(data)
177
247
 
178
- host = decoded['host'] || (raise ValueError, 'instance json data does not have host key')
179
- port = decoded['port'] || (raise ValueError, 'instance json data does not have port key')
248
+ host = decoded['host'] || (raise KeyError, 'instance json data does not have host key')
249
+ port = decoded['port'] || (raise KeyError, 'instance json data does not have port key')
180
250
  name = decoded['name'] || nil
181
251
  weight = decoded['weight'] || nil
182
252
  haproxy_server_options = decoded['haproxy_server_options'] || nil
253
+ labels = decoded['labels'] || nil
183
254
 
184
- return host, port, name, weight, haproxy_server_options
255
+ return host, port, name, weight, haproxy_server_options, labels
185
256
  end
186
257
  end
187
258
  end
259
+
@@ -1,3 +1,3 @@
1
1
  module Synapse
2
- VERSION = "0.12.2"
2
+ VERSION = "0.13.1"
3
3
  end
@@ -23,6 +23,21 @@ describe Synapse::Haproxy do
23
23
  mockWatcher
24
24
  end
25
25
 
26
+ let(:mockwatcher_frontend) do
27
+ mockWatcher = double(Synapse::ServiceWatcher)
28
+ allow(mockWatcher).to receive(:name).and_return('example_service')
29
+ allow(mockWatcher).to receive(:haproxy).and_return('port' => 2200)
30
+ mockWatcher
31
+ end
32
+
33
+ let(:mockwatcher_frontend_with_bind_address) do
34
+ mockWatcher = double(Synapse::ServiceWatcher)
35
+ allow(mockWatcher).to receive(:name).and_return('example_service')
36
+ allow(mockWatcher).to receive(:haproxy).and_return('port' => 2200, 'bind_address' => "127.0.0.3")
37
+ mockWatcher
38
+ end
39
+
40
+
26
41
  it 'updating the config' do
27
42
  expect(subject).to receive(:generate_config)
28
43
  subject.update_config([mockwatcher])
@@ -33,6 +48,34 @@ describe Synapse::Haproxy do
33
48
  expect(subject.generate_backend_stanza(mockwatcher, mockConfig)).to eql(["\nbackend example_service", [], ["\tserver somehost:5555 somehost:5555 cookie somehost:5555 check inter 2000 rise 3 fall 2"]])
34
49
  end
35
50
 
51
+ describe 'generate backend stanza in correct order' do
52
+ let(:multiple_backends_stanza_map) do
53
+ {
54
+ 'asc' => ["\nbackend example_service", [], ["\tserver somehost1:5555 somehost1:5555 cookie somehost1:5555 check inter 2000 rise 3 fall 2", "\tserver somehost2:5555 somehost2:5555 cookie somehost2:5555 check inter 2000 rise 3 fall 2", "\tserver somehost3:5555 somehost3:5555 cookie somehost3:5555 check inter 2000 rise 3 fall 2"]],
55
+ 'desc' => ["\nbackend example_service", [], ["\tserver somehost3:5555 somehost3:5555 cookie somehost3:5555 check inter 2000 rise 3 fall 2", "\tserver somehost2:5555 somehost2:5555 cookie somehost2:5555 check inter 2000 rise 3 fall 2", "\tserver somehost1:5555 somehost1:5555 cookie somehost1:5555 check inter 2000 rise 3 fall 2"]],
56
+ 'no_shuffle' => ["\nbackend example_service", [], ["\tserver somehost1:5555 somehost1:5555 cookie somehost1:5555 check inter 2000 rise 3 fall 2", "\tserver somehost3:5555 somehost3:5555 cookie somehost3:5555 check inter 2000 rise 3 fall 2", "\tserver somehost2:5555 somehost2:5555 cookie somehost2:5555 check inter 2000 rise 3 fall 2"]]
57
+ }
58
+ end
59
+
60
+ let(:mockwatcher_with_multiple_backends) do
61
+ mockWatcher = double(Synapse::ServiceWatcher)
62
+ allow(mockWatcher).to receive(:name).and_return('example_service')
63
+ backends = [{ 'host' => 'somehost1', 'port' => 5555}, {'host' => 'somehost3', 'port' => 5555}, { 'host' => 'somehost2', 'port' => 5555}]
64
+ allow(mockWatcher).to receive(:backends).and_return(backends)
65
+ mockWatcher
66
+ end
67
+
68
+ ['asc', 'desc', 'no_shuffle'].each do |order_option|
69
+ context "when #{order_option} is specified for backend_order" do
70
+ it 'generates backend stanza in correct order' do
71
+ mockConfig = []
72
+ allow(mockwatcher_with_multiple_backends).to receive(:haproxy).and_return({'server_options' => "check inter 2000 rise 3 fall 2", 'backend_order' => order_option})
73
+ expect(subject.generate_backend_stanza(mockwatcher_with_multiple_backends, mockConfig)).to eql(multiple_backends_stanza_map[order_option])
74
+ end
75
+ end
76
+ end
77
+ end
78
+
36
79
  it 'generates backend stanza without cookies for tcp mode' do
37
80
  mockConfig = ['mode tcp']
38
81
  expect(subject.generate_backend_stanza(mockwatcher, mockConfig)).to eql(["\nbackend example_service", ["\tmode tcp"], ["\tserver somehost:5555 somehost:5555 check inter 2000 rise 3 fall 2"]])
@@ -42,4 +85,15 @@ describe Synapse::Haproxy do
42
85
  mockConfig = []
43
86
  expect(subject.generate_backend_stanza(mockwatcher_with_server_options, mockConfig)).to eql(["\nbackend example_service", [], ["\tserver somehost:5555 somehost:5555 cookie somehost:5555 check inter 2000 rise 3 fall 2 backup"]])
44
87
  end
88
+
89
+ it 'generates frontend stanza ' do
90
+ mockConfig = []
91
+ expect(subject.generate_frontend_stanza(mockwatcher_frontend, mockConfig)).to eql(["\nfrontend example_service", [], "\tbind localhost:2200", "\tdefault_backend example_service"])
92
+ end
93
+
94
+ it 'respects frontend bind_address ' do
95
+ mockConfig = []
96
+ expect(subject.generate_frontend_stanza(mockwatcher_frontend_with_bind_address, mockConfig)).to eql(["\nfrontend example_service", [], "\tbind 127.0.0.3:2200", "\tdefault_backend example_service"])
97
+ end
98
+
45
99
  end
@@ -109,5 +109,31 @@ describe Synapse::ServiceWatcher::BaseWatcher do
109
109
  expect(subject.backends).to eq(backends + default_servers)
110
110
  end
111
111
  end
112
+
113
+ context 'with label_filter set' do
114
+ let(:matching_labeled_backends) { [
115
+ { 'name' => 'server1', 'host' => 'server1', 'port' => 1111, 'labels' => { 'az' => 'us-east-1a' } },
116
+ { 'name' => 'server2', 'host' => 'server2', 'port' => 2222, 'labels' => { 'az' => 'us-east-1a' } },
117
+ ] }
118
+ let(:non_matching_labeled_backends) { [
119
+ { 'name' => 'server3', 'host' => 'server3', 'port' => 3333, 'labels' => { 'az' => 'us-west-1c' } },
120
+ { 'name' => 'server4', 'host' => 'server4', 'port' => 4444, 'labels' => { 'az' => 'us-west-2a' } },
121
+ ] }
122
+ let(:non_labeled_backends) { [
123
+ { 'name' => 'server5', 'host' => 'server5', 'port' => 5555 },
124
+ ] }
125
+ let(:args) {
126
+ testargs.merge({ 'discovery' => {
127
+ 'method' => 'base',
128
+ 'label_filter' => { 'condition' => 'equals', 'label' => 'az', 'value' => 'us-east-1a' } }
129
+ })
130
+ }
131
+ it 'removes all backends that do not match the label_filter' do
132
+ expect(subject).to receive(:'reconfigure!').exactly(:once)
133
+ subject.send(:set_backends, matching_labeled_backends + non_matching_labeled_backends +
134
+ non_labeled_backends)
135
+ expect(subject.backends).to eq(matching_labeled_backends)
136
+ end
137
+ end
112
138
  end
113
139
  end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'synapse/service_watcher/zookeeper'
3
+ require 'synapse/service_watcher/zookeeper_dns'
4
+
5
+ describe Synapse::ServiceWatcher::ZookeeperWatcher do
6
+ let(:mock_synapse) { double }
7
+ let(:config) do
8
+ {
9
+ 'name' => 'test',
10
+ 'haproxy' => {},
11
+ 'discovery' => discovery,
12
+ }
13
+ end
14
+
15
+ let(:service_data) do
16
+ {
17
+ 'host' => 'server',
18
+ 'port' => '8888',
19
+ 'name' => 'server',
20
+ 'weight' => '1',
21
+ 'haproxy_server_options' => 'backup',
22
+ 'labels' => { 'az' => 'us-east-1a' }
23
+ }
24
+ end
25
+ let(:service_data_string) { service_data.to_json }
26
+ let(:deserialized_service_data) {
27
+ [ service_data['host'], service_data['port'], service_data['name'], service_data['weight'],
28
+ service_data['haproxy_server_options'], service_data['labels'] ]
29
+ }
30
+
31
+ context 'ZookeeperWatcher' do
32
+ let(:discovery) { { 'method' => 'zookeeper', 'hosts' => 'somehost','path' => 'some/path' } }
33
+ subject { Synapse::ServiceWatcher::ZookeeperWatcher.new(config, mock_synapse) }
34
+ it 'decodes data correctly' do
35
+ expect(subject.send(:deserialize_service_instance, service_data_string)).to eql(deserialized_service_data)
36
+ end
37
+ end
38
+
39
+ context 'ZookeeperDnsWatcher' do
40
+ let(:discovery) { { 'method' => 'zookeeper_dns', 'hosts' => 'somehost','path' => 'some/path' } }
41
+ let(:message_queue) { [] }
42
+ subject { Synapse::ServiceWatcher::ZookeeperDnsWatcher::Zookeeper.new(config, mock_synapse, message_queue) }
43
+ it 'decodes data correctly' do
44
+ expect(subject.send(:deserialize_service_instance, service_data_string)).to eql(deserialized_service_data)
45
+ end
46
+ end
47
+ end
data/synapse.gemspec CHANGED
@@ -17,8 +17,9 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
 
19
19
  gem.add_runtime_dependency "aws-sdk", "~> 1.39"
20
- gem.add_runtime_dependency "docker-api", "~> 1.7.2"
20
+ gem.add_runtime_dependency "docker-api", "~> 1.7"
21
21
  gem.add_runtime_dependency "zk", "~> 1.9.4"
22
+ gem.add_runtime_dependency "logging", "~> 1.8"
22
23
 
23
24
  gem.add_development_dependency "rake"
24
25
  gem.add_development_dependency "rspec", "~> 3.1.0"
metadata CHANGED
@@ -1,145 +1,142 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synapse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.2
5
- prerelease:
4
+ version: 0.13.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Martin Rhoads
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-12-07 00:00:00.000000000 Z
11
+ date: 2016-02-18 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: aws-sdk
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '1.39'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - "~>"
28
25
  - !ruby/object:Gem::Version
29
26
  version: '1.39'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: docker-api
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - "~>"
36
32
  - !ruby/object:Gem::Version
37
- version: 1.7.2
33
+ version: '1.7'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - "~>"
44
39
  - !ruby/object:Gem::Version
45
- version: 1.7.2
40
+ version: '1.7'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: zk
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ~>
45
+ - - "~>"
52
46
  - !ruby/object:Gem::Version
53
47
  version: 1.9.4
54
48
  type: :runtime
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ~>
52
+ - - "~>"
60
53
  - !ruby/object:Gem::Version
61
54
  version: 1.9.4
55
+ - !ruby/object:Gem::Dependency
56
+ name: logging
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.8'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.8'
62
69
  - !ruby/object:Gem::Dependency
63
70
  name: rake
64
71
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
72
  requirements:
67
- - - ! '>='
73
+ - - ">="
68
74
  - !ruby/object:Gem::Version
69
75
  version: '0'
70
76
  type: :development
71
77
  prerelease: false
72
78
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
79
  requirements:
75
- - - ! '>='
80
+ - - ">="
76
81
  - !ruby/object:Gem::Version
77
82
  version: '0'
78
83
  - !ruby/object:Gem::Dependency
79
84
  name: rspec
80
85
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
86
  requirements:
83
- - - ~>
87
+ - - "~>"
84
88
  - !ruby/object:Gem::Version
85
89
  version: 3.1.0
86
90
  type: :development
87
91
  prerelease: false
88
92
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
93
  requirements:
91
- - - ~>
94
+ - - "~>"
92
95
  - !ruby/object:Gem::Version
93
96
  version: 3.1.0
94
97
  - !ruby/object:Gem::Dependency
95
98
  name: pry
96
99
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
100
  requirements:
99
- - - ! '>='
101
+ - - ">="
100
102
  - !ruby/object:Gem::Version
101
103
  version: '0'
102
104
  type: :development
103
105
  prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
107
  requirements:
107
- - - ! '>='
108
+ - - ">="
108
109
  - !ruby/object:Gem::Version
109
110
  version: '0'
110
111
  - !ruby/object:Gem::Dependency
111
112
  name: pry-nav
112
113
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
114
  requirements:
115
- - - ! '>='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
121
  requirements:
123
- - - ! '>='
122
+ - - ">="
124
123
  - !ruby/object:Gem::Version
125
124
  version: '0'
126
125
  - !ruby/object:Gem::Dependency
127
126
  name: webmock
128
127
  requirement: !ruby/object:Gem::Requirement
129
- none: false
130
128
  requirements:
131
- - - ! '>='
129
+ - - ">="
132
130
  - !ruby/object:Gem::Version
133
131
  version: '0'
134
132
  type: :development
135
133
  prerelease: false
136
134
  version_requirements: !ruby/object:Gem::Requirement
137
- none: false
138
135
  requirements:
139
- - - ! '>='
136
+ - - ">="
140
137
  - !ruby/object:Gem::Version
141
138
  version: '0'
142
- description: ': Write a gem description'
139
+ description: ": Write a gem description"
143
140
  email:
144
141
  - martin.rhoads@airbnb.com
145
142
  executables:
@@ -147,10 +144,10 @@ executables:
147
144
  extensions: []
148
145
  extra_rdoc_files: []
149
146
  files:
150
- - .gitignore
151
- - .mailmap
152
- - .rspec
153
- - .travis.yml
147
+ - ".gitignore"
148
+ - ".mailmap"
149
+ - ".rspec"
150
+ - ".travis.yml"
154
151
  - Gemfile
155
152
  - Gemfile.lock
156
153
  - LICENSE.txt
@@ -185,34 +182,34 @@ files:
185
182
  - spec/lib/synapse/service_watcher_ec2tags_spec.rb
186
183
  - spec/lib/synapse/service_watcher_marathon_spec.rb
187
184
  - spec/lib/synapse/service_watcher_spec.rb
185
+ - spec/lib/synapse/service_watcher_zookeeper_spec.rb
188
186
  - spec/spec_helper.rb
189
187
  - spec/support/configuration.rb
190
188
  - spec/support/minimum.conf.yaml
191
189
  - synapse.gemspec
192
190
  homepage: ''
193
191
  licenses: []
192
+ metadata: {}
194
193
  post_install_message:
195
194
  rdoc_options: []
196
195
  require_paths:
197
196
  - lib
198
197
  required_ruby_version: !ruby/object:Gem::Requirement
199
- none: false
200
198
  requirements:
201
- - - ! '>='
199
+ - - ">="
202
200
  - !ruby/object:Gem::Version
203
201
  version: '0'
204
202
  required_rubygems_version: !ruby/object:Gem::Requirement
205
- none: false
206
203
  requirements:
207
- - - ! '>='
204
+ - - ">="
208
205
  - !ruby/object:Gem::Version
209
206
  version: '0'
210
207
  requirements: []
211
208
  rubyforge_project:
212
- rubygems_version: 1.8.23.2
209
+ rubygems_version: 2.5.1
213
210
  signing_key:
214
- specification_version: 3
215
- summary: ': Write a gem summary'
211
+ specification_version: 4
212
+ summary: ": Write a gem summary"
216
213
  test_files:
217
214
  - spec/lib/synapse/file_output_spec.rb
218
215
  - spec/lib/synapse/haproxy_spec.rb
@@ -221,6 +218,7 @@ test_files:
221
218
  - spec/lib/synapse/service_watcher_ec2tags_spec.rb
222
219
  - spec/lib/synapse/service_watcher_marathon_spec.rb
223
220
  - spec/lib/synapse/service_watcher_spec.rb
221
+ - spec/lib/synapse/service_watcher_zookeeper_spec.rb
224
222
  - spec/spec_helper.rb
225
223
  - spec/support/configuration.rb
226
224
  - spec/support/minimum.conf.yaml