synapse 0.14.0 → 0.14.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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YTEwNDE5ZTdlZDM4Njk2YmJkMDRjYWQzYTNiM2FkZTM0MzgyZWE4YQ==
5
- data.tar.gz: !binary |-
6
- ZjBmNmVmOTY2YWRiYTY1NWZmYTg3YjhiMThhY2NmNjIxNmE3ODkwYQ==
2
+ SHA1:
3
+ metadata.gz: 1f4b4d3c79352195ba849dcbe72ae849a65f355b
4
+ data.tar.gz: 9270bec56704c96e37fc37862ee3bb3d4b2501a2
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NjhlNDA1YjY1ODkxZWU4YzMyMzI2ODE1YWNjMzlmZWM4MTk1OTVjZTVkMjc4
10
- ODFjMTVlNDEyYjVmMDk0YTAxMjM0MWMyNGRmOGFiYjdhNDM4OWFiNDFlMjE1
11
- ZDMzNzZiYjg2MjgzY2VmYjQ2YjAxOGEwOTE0Y2MwMTkwNGFjMmU=
12
- data.tar.gz: !binary |-
13
- MGI0ZTBjNGQ5NjA0NmU1OWI0NzJhYmYyNDI2NWEyODI0MjA1NDM5NmYxNzEw
14
- YWYxMzI3MDc2ZTEyMDFkM2U5MzkyY2U5NzBkNjQ4YjA4YWNhNTI0YmRlMzlj
15
- N2JhM2MxYjQ5YWVhMzBlZWFhZTM3Y2RkMzVhOTNlMzc0ZmVkY2Y=
6
+ metadata.gz: 7df9f4fec05f203f66d1b5113df94e35e08d3f3ce5864ae1ba543829640a752d1938e4f9b04530782f7897427b0bbd6e6e07bc88f1ec6f7b003783ba154ed565
7
+ data.tar.gz: 2bde1c280db160799a9f52cfdedfdf28ce9060d78462a90538849984a9cffd60dad45d304562553bcc44453d440c81ada8c711e7edab97e9493bcf3594e87851
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- synapse (0.13.8)
4
+ synapse (0.14.1)
5
5
  aws-sdk (~> 1.39)
6
6
  docker-api (~> 1.7)
7
7
  logging (~> 1.8)
data/README.md CHANGED
@@ -28,15 +28,29 @@ Synapse solves these difficulties in a simple and fault-tolerant way.
28
28
 
29
29
  ## How Synapse Works ##
30
30
 
31
- Synapse runs on your application servers; here at Airbnb, we just run it on every box we deploy.
32
- The heart of synapse is actually [HAProxy](http://haproxy.1wt.eu/), a stable and proven routing component.
31
+ Synapse typically runs on your application servers, often every machine. At the heart of Synapse
32
+ are proven routing components like [HAProxy](http://haproxy.1wt.eu/) or [NGINX](http://nginx.org/).
33
+
33
34
  For every external service that your application talks to, we assign a synapse local port on localhost.
34
35
  Synapse creates a proxy from the local port to the service, and you reconfigure your application to talk to the proxy.
35
36
 
36
- Synapse comes with a number of `watchers`, which are responsible for service discovery.
37
- The synapse watchers take care of re-configuring the proxy so that it always points at available servers.
37
+ Under the hood, Synapse sports `service_watcher`s for service discovery and
38
+ `config_generators` for configuring local state (e.g. load balancer configs)
39
+ based on that service discovery state.
40
+
41
+ Synapse supports service discovery with with pluggable `service_watcher`s which
42
+ take care of signaling to the `config_generators` so that they can react and
43
+ reconfigure to point at available servers on the fly.
44
+
38
45
  We've included a number of default watchers, including ones that query zookeeper and ones using the AWS API.
39
- It is easy to write your own watchers for your use case, and we encourage submitting them back to the project.
46
+ It is easy to write your own watchers for your use case, and install them as gems that
47
+ extend Synapse's functionality. Check out the [docs](#createsw) on creating
48
+ a watcher if you're interested, and if you think that the service watcher
49
+ would be generally useful feel free to pull request with a link to your watcher.
50
+
51
+ Synapse also has pluggable `config_generator`s, which are responsible for reacting to service discovery
52
+ changes and writing out appropriate config. Right now HAProxy, and local files are built in, but you
53
+ can plug your own in [easily](#createconfig).
40
54
 
41
55
  ## Example Migration ##
42
56
 
@@ -97,13 +111,22 @@ install synapse with:
97
111
 
98
112
  ```bash
99
113
  $ mkdir -p /opt/smartstack/synapse
114
+ # If you are on Ruby 2.X use --no-document instead of --no-ri --no-rdoc
100
115
 
101
116
  # If you want to install specific versions of dependencies such as an older
102
117
  # version of the aws-sdk, the docker-api, etc, gem install that here *before*
103
- # gem installing synapse
118
+ # gem installing synapse.
119
+
120
+ # Example:
121
+ # $ gem install aws-sdk -v XXX
104
122
 
105
- # If you are on Ruby 2.X use --no-document instead of --no-ri --no-rdoc
106
123
  $ gem install synapse --install-dir /opt/smartstack/synapse --no-ri --no-rdoc
124
+
125
+ # If you want to install specific plugins such as watchers or config generators
126
+ # gem install them *after* you install synapse.
127
+
128
+ # Example:
129
+ # $ gem install synapse-nginx --install-dir /opt/smartstack/synapse --no-ri --no-rdoc
107
130
  ```
108
131
 
109
132
  This will download synapse and its dependencies into /opt/smartstack/synapse. You
@@ -118,16 +141,26 @@ export GEM_PATH=/opt/smartstack/synapse
118
141
  /opt/smartstack/synapse/bin/synapse --help
119
142
  ```
120
143
 
121
- Don't forget to install HAProxy too.
144
+ Don't forget to install HAProxy or NGINX or whatever proxy your `config_generator`
145
+ is configuring.
122
146
 
123
147
  ## Configuration ##
124
148
 
125
149
  Synapse depends on a single config file in JSON format; it's usually called `synapse.conf.json`.
126
- The file has three main sections.
150
+ The file has a `services` section that describes how services are discovered
151
+ and configured, and then top level sections for every supported proxy or
152
+ configuration section. For example, the default Synapse supports three sections:
127
153
 
128
- 1. [`services`](#services): lists the services you'd like to connect.
129
- 2. [`haproxy`](#haproxy): specifies how to configure and interact with HAProxy.
130
- 3. [`file_output`](#file) (optional): specifies where to write service state to on the filesystem.
154
+ * [`services`](#services): lists the services you'd like to connect.
155
+ * [`haproxy`](#haproxy): specifies how to configure and interact with HAProxy.
156
+ * [`file_output`](#file) (optional): specifies where to write service state to on the filesystem.
157
+ * [`<your config generator here>`] (optional): configuration for your custom
158
+ configuration generators (e.g. nginx, vulcand, envoy, etc ..., w.e. you want).
159
+
160
+ If you have synapse `config_generator` plugins installed, you'll want a top
161
+ level as well, e.g.:
162
+ * [`nginx`](https://github.com/jolynch/synapse-nginx#top-level-config) (optional):
163
+ configuration for how to configure and interact with NGINX.
131
164
 
132
165
  <a name="services"/>
133
166
  ### Configuring a Service ###
@@ -138,13 +171,21 @@ Each value in the services hash is also a hash, and must contain the following k
138
171
 
139
172
  * [`discovery`](#discovery): how synapse will discover hosts providing this service (see [below](#discovery))
140
173
 
141
- The services hash *should* contain a section on how to configure the routing
142
- component you wish to use for this particular service. The only choice currently
143
- is `haproxy`:
174
+ The services hash *should* contain a section on how to configure each routing
175
+ component you wish to use for this particular service. The current choices are
176
+ `haproxy` but you can access others e.g. [`nginx`](https://github.com/jolynch/synapse-nginx)
177
+ through [plugins](createconfig). Note that if you give a routing component at the top level
178
+ but not at the service level the default is typically to make that service
179
+ available via that routing component, sans listening ports. If you wish to only
180
+ configure a single component explicitly pass the ``disabled`` option to the
181
+ relevant routing component. For example if you want to only configure HAProxy and
182
+ not NGINX for a particular service, you would pass ``disabled`` to the `nginx` section
183
+ of that service's watcher config.
144
184
 
145
185
  * [`haproxy`](#haproxysvc): how will the haproxy section for this service be configured
186
+ * [`nginx`](https://github.com/jolynch/synapse-nginx#service-watcher-config): how will the nginx section for this service be configured. **NOTE** to use this you must have the synapse-nginx [plugin](#plugins) installed.
146
187
 
147
- The services hash may contain the following keys:
188
+ The services hash may contain the following additional keys:
148
189
 
149
190
  * `default_servers` (default: `[]`): the list of default servers providing this service; synapse uses these if no others can be discovered. See [Listing Default Servers](#defaultservers).
150
191
  * `keep_default_servers` (default: false): whether default servers should be added to discovered services
@@ -278,8 +319,17 @@ This section is its own hash, which should contain the following keys:
278
319
  * `disabled`: A boolean value indicating if haproxy configuration management
279
320
  for just this service instance ought be disabled. For example, if you want
280
321
  file output for a particular service but no HAProxy config. (default is ``False``)
281
- * `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`
282
- * `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.
322
+ * `port`: the port (on localhost) where HAProxy will listen for connections to
323
+ the service. If this is null, just the bind_address will be used (e.g. for
324
+ unix sockets) and if omitted, only a backend stanza (and no frontend stanza)
325
+ will be generated for this service. In the case of a bare backend, you'll need
326
+ to get traffic to your service yourself via the `shared_frontend` or
327
+ manual frontends in `extra_sections`
328
+ * `bind_address`: force HAProxy to listen on this address (default is localhost).
329
+ Setting `bind_address` on a per service basis overrides the global `bind_address`
330
+ in the top level `haproxy`. Having HAProxy listen for connections on
331
+ different addresses (example: service1 listen on 127.0.0.2:443 and service2
332
+ listen on 127.0.0.3:443) allows /etc/hosts entries to point to services.
283
333
  * `bind_options`: optional: default value is an empty string, specify additional bind parameters, such as ssl accept-proxy, crt, ciphers etc.
284
334
  * `server_port_override`: **DEPRECATED**. Renamed [`backend_port_override`](#backend_port_override) and moved to the top level hash. This will be removed in future versions.
285
335
  * `server_options`: the haproxy options for each `server` line of the service in HAProxy config; it may be left out.
@@ -335,7 +385,6 @@ use discovery information but not go through HAProxy.
335
385
  * `output_directory`: the path to a directory on disk that service registrations
336
386
  should be written to.
337
387
 
338
-
339
388
  ### HAProxy shared HTTP Frontend ###
340
389
 
341
390
  For HTTP-only services, it is not always necessary or desirable to dedicate a TCP port per service, since HAProxy can route traffic based on host headers.
@@ -416,6 +465,9 @@ frontend shared-frontend
416
465
  Non-HTTP backends such as MySQL or RabbitMQ will obviously continue to need their own dedicated ports.
417
466
 
418
467
  ## Contributing
468
+ Note that now that we have a fully dynamic include system for service watchers
469
+ and configuration generators, you don't *have* to PR into the main tree, but
470
+ please do contribute a [link](#plugins).
419
471
 
420
472
  1. Fork it
421
473
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -423,12 +475,20 @@ Non-HTTP backends such as MySQL or RabbitMQ will obviously continue to need thei
423
475
  4. Push to the branch (`git push origin my-new-feature`)
424
476
  5. Create new Pull Request
425
477
 
478
+ <a name="createsw"/>
426
479
  ### Creating a Service Watcher ###
427
480
 
428
481
  See the Service Watcher [README](lib/synapse/service_watcher/README.md) for
429
482
  how to add new Service Watchers.
430
483
 
484
+ <a name="createconfig"/>
431
485
  ### Creating a Config Generator ###
432
486
 
433
487
  See the Config Generator [README](lib/synapse/config_generator/README.md) for
434
488
  how to add new Config Generators
489
+
490
+ <a name="plugins"/>
491
+ ## Links to Synapse Plugins ##
492
+ * [`synapse-nginx`](https://github.com/jolynch/synapse-nginx) Is a `config_generator`
493
+ which allows Synapse to automatically configure and administer a local NGINX
494
+ proxy.
@@ -997,9 +997,13 @@ class Synapse::ConfigGenerator
997
997
  )
998
998
  backend_name = watcher_config.fetch('backend_name', watcher.name)
999
999
 
1000
+ # Explicit null value passed indicating no port needed
1001
+ # For example if the bind_address is a unix port
1002
+ bind_port = port.nil? ? '' : ":#{port}"
1003
+
1000
1004
  bind_line = [
1001
1005
  "\tbind",
1002
- "#{bind_address}:#{port}",
1006
+ "#{bind_address}#{bind_port}",
1003
1007
  watcher_config['bind_options']
1004
1008
  ].compact.join(' ')
1005
1009
 
@@ -1,3 +1,3 @@
1
1
  module Synapse
2
- VERSION = "0.14.0"
2
+ VERSION = "0.14.1"
3
3
  end
@@ -69,6 +69,15 @@ describe Synapse::ConfigGenerator::Haproxy do
69
69
  mockWatcher
70
70
  end
71
71
 
72
+ let(:mockwatcher_frontend_with_nil_port) do
73
+ mockWatcher = double(Synapse::ServiceWatcher)
74
+ allow(mockWatcher).to receive(:name).and_return('example_service6')
75
+ allow(mockWatcher).to receive(:config_for_generator).and_return({
76
+ 'haproxy' => {'port' => nil, 'bind_address' => "unix@/foo/bar.sock"}
77
+ })
78
+ mockWatcher
79
+ end
80
+
72
81
  let(:mockwatcher_disabled) do
73
82
  mockWatcher = double(Synapse::ServiceWatcher)
74
83
  allow(mockWatcher).to receive(:name).and_return('disabled_watcher')
@@ -440,6 +449,11 @@ describe Synapse::ConfigGenerator::Haproxy do
440
449
  expect(subject.generate_frontend_stanza(mockwatcher_frontend_with_bind_options, mockConfig)).to eql(["\nfrontend example_service4", [], "\tbind localhost:2200 ssl no-sslv3 crt /path/to/cert/example.pem ciphers ECDHE-ECDSA-CHACHA20-POLY1305", "\tdefault_backend example_service4"])
441
450
  end
442
451
 
452
+ it 'generates frontend stanza with nil port' do
453
+ mockConfig= []
454
+ expect(subject.generate_frontend_stanza(mockwatcher_frontend_with_nil_port, mockConfig)).to eql(["\nfrontend example_service6", [], "\tbind unix@/foo/bar.sock", "\tdefault_backend example_service6"])
455
+ end
456
+
443
457
  it 'respects frontend bind_address ' do
444
458
  mockConfig = []
445
459
  expect(subject.generate_frontend_stanza(mockwatcher_frontend_with_bind_address, mockConfig)).to eql(["\nfrontend example_service5", [], "\tbind 127.0.0.3:2200", "\tdefault_backend example_service5"])
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.14.0
4
+ version: 0.14.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Rhoads
@@ -10,160 +10,160 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2017-03-09 00:00:00.000000000 Z
13
+ date: 2017-03-11 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: aws-sdk
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ~>
19
+ - - "~>"
20
20
  - !ruby/object:Gem::Version
21
21
  version: '1.39'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ~>
26
+ - - "~>"
27
27
  - !ruby/object:Gem::Version
28
28
  version: '1.39'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: docker-api
31
31
  requirement: !ruby/object:Gem::Requirement
32
32
  requirements:
33
- - - ~>
33
+ - - "~>"
34
34
  - !ruby/object:Gem::Version
35
35
  version: '1.7'
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
- - - ~>
40
+ - - "~>"
41
41
  - !ruby/object:Gem::Version
42
42
  version: '1.7'
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: zk
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ~>
47
+ - - "~>"
48
48
  - !ruby/object:Gem::Version
49
49
  version: 1.9.4
50
50
  type: :runtime
51
51
  prerelease: false
52
52
  version_requirements: !ruby/object:Gem::Requirement
53
53
  requirements:
54
- - - ~>
54
+ - - "~>"
55
55
  - !ruby/object:Gem::Version
56
56
  version: 1.9.4
57
57
  - !ruby/object:Gem::Dependency
58
58
  name: logging
59
59
  requirement: !ruby/object:Gem::Requirement
60
60
  requirements:
61
- - - ~>
61
+ - - "~>"
62
62
  - !ruby/object:Gem::Version
63
63
  version: '1.8'
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
67
67
  requirements:
68
- - - ~>
68
+ - - "~>"
69
69
  - !ruby/object:Gem::Version
70
70
  version: '1.8'
71
71
  - !ruby/object:Gem::Dependency
72
72
  name: rake
73
73
  requirement: !ruby/object:Gem::Requirement
74
74
  requirements:
75
- - - ! '>='
75
+ - - ">="
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
78
  type: :development
79
79
  prerelease: false
80
80
  version_requirements: !ruby/object:Gem::Requirement
81
81
  requirements:
82
- - - ! '>='
82
+ - - ">="
83
83
  - !ruby/object:Gem::Version
84
84
  version: '0'
85
85
  - !ruby/object:Gem::Dependency
86
86
  name: rspec
87
87
  requirement: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - ~>
89
+ - - "~>"
90
90
  - !ruby/object:Gem::Version
91
91
  version: 3.1.0
92
92
  type: :development
93
93
  prerelease: false
94
94
  version_requirements: !ruby/object:Gem::Requirement
95
95
  requirements:
96
- - - ~>
96
+ - - "~>"
97
97
  - !ruby/object:Gem::Version
98
98
  version: 3.1.0
99
99
  - !ruby/object:Gem::Dependency
100
100
  name: factory_girl
101
101
  requirement: !ruby/object:Gem::Requirement
102
102
  requirements:
103
- - - ! '>='
103
+ - - ">="
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  type: :development
107
107
  prerelease: false
108
108
  version_requirements: !ruby/object:Gem::Requirement
109
109
  requirements:
110
- - - ! '>='
110
+ - - ">="
111
111
  - !ruby/object:Gem::Version
112
112
  version: '0'
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: pry
115
115
  requirement: !ruby/object:Gem::Requirement
116
116
  requirements:
117
- - - ! '>='
117
+ - - ">="
118
118
  - !ruby/object:Gem::Version
119
119
  version: '0'
120
120
  type: :development
121
121
  prerelease: false
122
122
  version_requirements: !ruby/object:Gem::Requirement
123
123
  requirements:
124
- - - ! '>='
124
+ - - ">="
125
125
  - !ruby/object:Gem::Version
126
126
  version: '0'
127
127
  - !ruby/object:Gem::Dependency
128
128
  name: pry-nav
129
129
  requirement: !ruby/object:Gem::Requirement
130
130
  requirements:
131
- - - ! '>='
131
+ - - ">="
132
132
  - !ruby/object:Gem::Version
133
133
  version: '0'
134
134
  type: :development
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
137
137
  requirements:
138
- - - ! '>='
138
+ - - ">="
139
139
  - !ruby/object:Gem::Version
140
140
  version: '0'
141
141
  - !ruby/object:Gem::Dependency
142
142
  name: webmock
143
143
  requirement: !ruby/object:Gem::Requirement
144
144
  requirements:
145
- - - ! '>='
145
+ - - ">="
146
146
  - !ruby/object:Gem::Version
147
147
  version: '0'
148
148
  type: :development
149
149
  prerelease: false
150
150
  version_requirements: !ruby/object:Gem::Requirement
151
151
  requirements:
152
- - - ! '>='
152
+ - - ">="
153
153
  - !ruby/object:Gem::Version
154
154
  version: '0'
155
155
  - !ruby/object:Gem::Dependency
156
156
  name: timecop
157
157
  requirement: !ruby/object:Gem::Requirement
158
158
  requirements:
159
- - - ! '>='
159
+ - - ">="
160
160
  - !ruby/object:Gem::Version
161
161
  version: '0'
162
162
  type: :development
163
163
  prerelease: false
164
164
  version_requirements: !ruby/object:Gem::Requirement
165
165
  requirements:
166
- - - ! '>='
166
+ - - ">="
167
167
  - !ruby/object:Gem::Version
168
168
  version: '0'
169
169
  description: Synapse is a daemon used to dynamically configure and manage local instances
@@ -179,10 +179,10 @@ executables:
179
179
  extensions: []
180
180
  extra_rdoc_files: []
181
181
  files:
182
- - .gitignore
183
- - .mailmap
184
- - .rspec
185
- - .travis.yml
182
+ - ".gitignore"
183
+ - ".mailmap"
184
+ - ".rspec"
185
+ - ".travis.yml"
186
186
  - Gemfile
187
187
  - Gemfile.lock
188
188
  - LICENSE.txt
@@ -235,17 +235,17 @@ require_paths:
235
235
  - lib
236
236
  required_ruby_version: !ruby/object:Gem::Requirement
237
237
  requirements:
238
- - - ! '>='
238
+ - - ">="
239
239
  - !ruby/object:Gem::Version
240
240
  version: '0'
241
241
  required_rubygems_version: !ruby/object:Gem::Requirement
242
242
  requirements:
243
- - - ! '>='
243
+ - - ">="
244
244
  - !ruby/object:Gem::Version
245
245
  version: '0'
246
246
  requirements: []
247
247
  rubyforge_project:
248
- rubygems_version: 2.5.1
248
+ rubygems_version: 2.2.2
249
249
  signing_key:
250
250
  specification_version: 4
251
251
  summary: Dynamic HAProxy configuration daemon