synapse 0.14.0 → 0.14.1

Sign up to get free protection for your applications and to get access to all the features.
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