synapse-aurora 0.11.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/.gitignore +23 -0
- data/.mailmap +3 -0
- data/.nix/Gemfile.nix +141 -0
- data/.nix/rubylibs.nix +42 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/Makefile +6 -0
- data/README.md +339 -0
- data/Rakefile +8 -0
- data/bin/synapse +62 -0
- data/config/hostheader_test.json +71 -0
- data/config/svcdir_test.json +46 -0
- data/config/synapse.conf.json +90 -0
- data/config/synapse_services/service1.json +24 -0
- data/config/synapse_services/service2.json +24 -0
- data/default.nix +66 -0
- data/lib/synapse.rb +85 -0
- data/lib/synapse/base.rb +5 -0
- data/lib/synapse/haproxy.rb +797 -0
- data/lib/synapse/log.rb +24 -0
- data/lib/synapse/service_watcher.rb +36 -0
- data/lib/synapse/service_watcher/base.rb +109 -0
- data/lib/synapse/service_watcher/dns.rb +109 -0
- data/lib/synapse/service_watcher/docker.rb +120 -0
- data/lib/synapse/service_watcher/ec2tag.rb +133 -0
- data/lib/synapse/service_watcher/zookeeper.rb +153 -0
- data/lib/synapse/service_watcher/zookeeper_aurora.rb +76 -0
- data/lib/synapse/service_watcher/zookeeper_dns.rb +232 -0
- data/lib/synapse/version.rb +3 -0
- data/spec/lib/synapse/haproxy_spec.rb +32 -0
- data/spec/lib/synapse/service_watcher_base_spec.rb +55 -0
- data/spec/lib/synapse/service_watcher_docker_spec.rb +152 -0
- data/spec/lib/synapse/service_watcher_ec2tags_spec.rb +220 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/support/configuration.rb +9 -0
- data/spec/support/minimum.conf.yaml +27 -0
- data/synapse.gemspec +33 -0
- metadata +227 -0
data/lib/synapse/log.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
module Synapse
|
2
|
+
module Logging
|
3
|
+
|
4
|
+
def log
|
5
|
+
@logger ||= Logging.logger_for(self.class.name)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Use a hash class-ivar to cache a unique Logger per class:
|
9
|
+
@loggers = {}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def logger_for(classname)
|
13
|
+
@loggers[classname] ||= configure_logger_for(classname)
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure_logger_for(classname)
|
17
|
+
logger = Logger.new(STDERR)
|
18
|
+
logger.level = Logger::INFO unless ENV['DEBUG']
|
19
|
+
logger.progname = classname
|
20
|
+
return logger
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "synapse/service_watcher/base"
|
2
|
+
require "synapse/service_watcher/zookeeper"
|
3
|
+
require "synapse/service_watcher/ec2tag"
|
4
|
+
require "synapse/service_watcher/dns"
|
5
|
+
require "synapse/service_watcher/docker"
|
6
|
+
require "synapse/service_watcher/zookeeper_dns"
|
7
|
+
require "synapse/service_watcher/zookeeper_aurora"
|
8
|
+
|
9
|
+
module Synapse
|
10
|
+
class ServiceWatcher
|
11
|
+
|
12
|
+
@watchers = {
|
13
|
+
'base' => BaseWatcher,
|
14
|
+
'zookeeper' => ZookeeperWatcher,
|
15
|
+
'ec2tag' => EC2Watcher,
|
16
|
+
'dns' => DnsWatcher,
|
17
|
+
'docker' => DockerWatcher,
|
18
|
+
'zookeeper_dns' => ZookeeperDnsWatcher,
|
19
|
+
'zookeeper_aurora' => ZookeeperAuroraWatcher
|
20
|
+
}
|
21
|
+
|
22
|
+
# the method which actually dispatches watcher creation requests
|
23
|
+
def self.create(name, opts, synapse)
|
24
|
+
opts['name'] = name
|
25
|
+
|
26
|
+
raise ArgumentError, "Missing discovery method when trying to create watcher" \
|
27
|
+
unless opts.has_key?('discovery') && opts['discovery'].has_key?('method')
|
28
|
+
|
29
|
+
discovery_method = opts['discovery']['method']
|
30
|
+
raise ArgumentError, "Invalid discovery method #{discovery_method}" \
|
31
|
+
unless @watchers.has_key?(discovery_method)
|
32
|
+
|
33
|
+
return @watchers[discovery_method].new(opts, synapse)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'synapse/log'
|
2
|
+
|
3
|
+
module Synapse
|
4
|
+
class BaseWatcher
|
5
|
+
include Logging
|
6
|
+
|
7
|
+
LEADER_WARN_INTERVAL = 30
|
8
|
+
|
9
|
+
attr_reader :name, :haproxy
|
10
|
+
|
11
|
+
def initialize(opts={}, synapse)
|
12
|
+
super()
|
13
|
+
|
14
|
+
@synapse = synapse
|
15
|
+
|
16
|
+
# set required service parameters
|
17
|
+
%w{name discovery haproxy}.each do |req|
|
18
|
+
raise ArgumentError, "missing required option #{req}" unless opts[req]
|
19
|
+
end
|
20
|
+
|
21
|
+
@name = opts['name']
|
22
|
+
@discovery = opts['discovery']
|
23
|
+
|
24
|
+
@leader_election = opts['leader_election'] || false
|
25
|
+
@leader_last_warn = Time.now - LEADER_WARN_INTERVAL
|
26
|
+
|
27
|
+
# the haproxy config
|
28
|
+
@haproxy = opts['haproxy']
|
29
|
+
@haproxy['server_options'] ||= ""
|
30
|
+
@haproxy['server_port_override'] ||= nil
|
31
|
+
%w{backend frontend listen}.each do |sec|
|
32
|
+
@haproxy[sec] ||= []
|
33
|
+
end
|
34
|
+
|
35
|
+
unless @haproxy.include?('port')
|
36
|
+
log.warn "synapse: service #{name}: haproxy config does not include a port; only backend sections for the service will be created; you must move traffic there manually using configuration in `extra_sections`"
|
37
|
+
end
|
38
|
+
|
39
|
+
# set initial backends to default servers, if any
|
40
|
+
@default_servers = opts['default_servers'] || []
|
41
|
+
@backends = @default_servers
|
42
|
+
|
43
|
+
@keep_default_servers = opts['keep_default_servers'] || false
|
44
|
+
|
45
|
+
# set a flag used to tell the watchers to exit
|
46
|
+
# this is not used in every watcher
|
47
|
+
@should_exit = false
|
48
|
+
|
49
|
+
validate_discovery_opts
|
50
|
+
end
|
51
|
+
|
52
|
+
# this should be overridden to actually start your watcher
|
53
|
+
def start
|
54
|
+
log.info "synapse: starting stub watcher; this means doing nothing at all!"
|
55
|
+
end
|
56
|
+
|
57
|
+
# this should be overridden to actually stop your watcher if necessary
|
58
|
+
# if you are running a thread, your loop should run `until @should_exit`
|
59
|
+
def stop
|
60
|
+
log.info "synapse: stopping watcher #{self.name} using default stop handler"
|
61
|
+
@should_exit = true
|
62
|
+
end
|
63
|
+
|
64
|
+
# this should be overridden to do a health check of the watcher
|
65
|
+
def ping?
|
66
|
+
true
|
67
|
+
end
|
68
|
+
|
69
|
+
def backends
|
70
|
+
if @leader_election
|
71
|
+
if @backends.all?{|b| b.key?('id') && b['id']}
|
72
|
+
smallest = @backends.sort_by{ |b| b['id']}.first
|
73
|
+
log.debug "synapse: leader election chose one of #{@backends.count} backends " \
|
74
|
+
"(#{smallest['host']}:#{smallest['port']} with id #{smallest['id']})"
|
75
|
+
|
76
|
+
return [smallest]
|
77
|
+
elsif (Time.now - @leader_last_warn) > LEADER_WARN_INTERVAL
|
78
|
+
log.warn "synapse: service #{@name}: leader election failed; not all backends include an id"
|
79
|
+
@leader_last_warn = Time.now
|
80
|
+
end
|
81
|
+
|
82
|
+
# if leader election fails, return no backends
|
83
|
+
return []
|
84
|
+
end
|
85
|
+
|
86
|
+
return @backends
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def validate_discovery_opts
|
91
|
+
raise ArgumentError, "invalid discovery method '#{@discovery['method']}' for base watcher" \
|
92
|
+
unless @discovery['method'] == 'base'
|
93
|
+
|
94
|
+
log.warn "synapse: warning: a stub watcher with no default servers is pretty useless" if @default_servers.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
def set_backends(new_backends)
|
98
|
+
if @keep_default_servers
|
99
|
+
@backends = @default_servers + new_backends
|
100
|
+
else
|
101
|
+
@backends = new_backends
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def reconfigure!
|
106
|
+
@synapse.reconfigure!
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require "synapse/service_watcher/base"
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
require 'resolv'
|
5
|
+
|
6
|
+
module Synapse
|
7
|
+
class DnsWatcher < BaseWatcher
|
8
|
+
def start
|
9
|
+
@check_interval = @discovery['check_interval'] || 30.0
|
10
|
+
@nameserver = @discovery['nameserver']
|
11
|
+
|
12
|
+
@watcher = Thread.new do
|
13
|
+
watch
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def ping?
|
18
|
+
@watcher.alive? && !(resolver.getaddresses('airbnb.com').empty?)
|
19
|
+
end
|
20
|
+
|
21
|
+
def discovery_servers
|
22
|
+
@discovery['servers']
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def validate_discovery_opts
|
27
|
+
raise ArgumentError, "invalid discovery method #{@discovery['method']}" \
|
28
|
+
unless @discovery['method'] == 'dns'
|
29
|
+
raise ArgumentError, "a non-empty list of servers is required" \
|
30
|
+
if discovery_servers.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
def watch
|
34
|
+
last_resolution = resolve_servers
|
35
|
+
configure_backends(last_resolution)
|
36
|
+
until @should_exit
|
37
|
+
begin
|
38
|
+
start = Time.now
|
39
|
+
current_resolution = resolve_servers
|
40
|
+
unless last_resolution == current_resolution
|
41
|
+
last_resolution = current_resolution
|
42
|
+
configure_backends(last_resolution)
|
43
|
+
end
|
44
|
+
|
45
|
+
sleep_until_next_check(start)
|
46
|
+
rescue => e
|
47
|
+
log.warn "Error in watcher thread: #{e.inspect}"
|
48
|
+
log.warn e.backtrace
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
log.info "synapse: dns watcher exited successfully"
|
53
|
+
end
|
54
|
+
|
55
|
+
def sleep_until_next_check(start_time)
|
56
|
+
sleep_time = @check_interval - (Time.now - start_time)
|
57
|
+
if sleep_time > 0.0
|
58
|
+
sleep(sleep_time)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def resolve_servers
|
63
|
+
resolver.tap do |dns|
|
64
|
+
resolution = discovery_servers.map do |server|
|
65
|
+
addresses = dns.getaddresses(server['host']).map(&:to_s)
|
66
|
+
[server, addresses.sort]
|
67
|
+
end
|
68
|
+
|
69
|
+
return resolution
|
70
|
+
end
|
71
|
+
rescue => e
|
72
|
+
log.warn "Error while resolving host names: #{e.inspect}"
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
|
76
|
+
def resolver
|
77
|
+
args = [{:nameserver => @nameserver}] if @nameserver
|
78
|
+
Resolv::DNS.open(*args)
|
79
|
+
end
|
80
|
+
|
81
|
+
def configure_backends(servers)
|
82
|
+
new_backends = servers.flat_map do |(server, addresses)|
|
83
|
+
addresses.map do |address|
|
84
|
+
{
|
85
|
+
'host' => address,
|
86
|
+
'port' => server['port'],
|
87
|
+
'name' => server['name'],
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if new_backends.empty?
|
93
|
+
if @default_servers.empty?
|
94
|
+
log.warn "synapse: no backends and no default servers for service #{@name};" \
|
95
|
+
" using previous backends: #{@backends.inspect}"
|
96
|
+
else
|
97
|
+
log.warn "synapse: no backends for service #{@name};" \
|
98
|
+
" using default servers: #{@default_servers.inspect}"
|
99
|
+
@backends = @default_servers
|
100
|
+
end
|
101
|
+
else
|
102
|
+
log.info "synapse: discovered #{new_backends.length} backends for service #{@name}"
|
103
|
+
set_backends(new_backends)
|
104
|
+
end
|
105
|
+
|
106
|
+
reconfigure!
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require "synapse/service_watcher/base"
|
2
|
+
require 'docker'
|
3
|
+
|
4
|
+
module Synapse
|
5
|
+
class DockerWatcher < BaseWatcher
|
6
|
+
def start
|
7
|
+
@check_interval = @discovery['check_interval'] || 15.0
|
8
|
+
@watcher = Thread.new do
|
9
|
+
watch
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
def validate_discovery_opts
|
15
|
+
raise ArgumentError, "invalid discovery method #{@discovery['method']}" \
|
16
|
+
unless @discovery['method'] == 'docker'
|
17
|
+
raise ArgumentError, "a non-empty list of servers is required" \
|
18
|
+
if @discovery['servers'].nil? or @discovery['servers'].empty?
|
19
|
+
raise ArgumentError, "non-empty image_name required" \
|
20
|
+
if @discovery['image_name'].nil? or @discovery['image_name'].empty?
|
21
|
+
raise ArgumentError, "container_port required" \
|
22
|
+
if @discovery['container_port'].nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def watch
|
26
|
+
last_containers = []
|
27
|
+
until @should_exit
|
28
|
+
begin
|
29
|
+
start = Time.now
|
30
|
+
current_containers = containers
|
31
|
+
unless last_containers == current_containers
|
32
|
+
last_containers = current_containers
|
33
|
+
configure_backends(last_containers)
|
34
|
+
end
|
35
|
+
|
36
|
+
sleep_until_next_check(start)
|
37
|
+
rescue Exception => e
|
38
|
+
log.warn "synapse: error in watcher thread: #{e.inspect}"
|
39
|
+
log.warn e.backtrace
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
log.info "synapse: docker watcher exited successfully"
|
44
|
+
end
|
45
|
+
|
46
|
+
def sleep_until_next_check(start_time)
|
47
|
+
sleep_time = @check_interval - (Time.now - start_time)
|
48
|
+
if sleep_time > 0.0
|
49
|
+
sleep(sleep_time)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def rewrite_container_ports(ports)
|
54
|
+
pairs = []
|
55
|
+
if ports.is_a?(String)
|
56
|
+
# "Ports" comes through (as of 0.6.5) as a string like "0.0.0.0:49153->6379/tcp, 0.0.0.0:49153->6379/tcp"
|
57
|
+
# Convert string to a map of container port to host port: {"7000"->"49158", "6379": "49159"}
|
58
|
+
pairs = ports.split(", ").collect do |v|
|
59
|
+
pair = v.split('->')
|
60
|
+
[ pair[1].rpartition("/").first, pair[0].rpartition(":").last ]
|
61
|
+
end
|
62
|
+
elsif ports.is_a?(Array)
|
63
|
+
# New style API, ports is an array of hashes, with numeric values (or nil if no ports forwarded)
|
64
|
+
pairs = ports.collect do |v|
|
65
|
+
[v['PrivatePort'].to_s, v['PublicPort'].to_s]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
Hash[pairs]
|
69
|
+
end
|
70
|
+
|
71
|
+
def containers
|
72
|
+
backends = @discovery['servers'].map do |server|
|
73
|
+
Docker.url = "http://#{server['host']}:#{server['port'] || 4243}"
|
74
|
+
begin
|
75
|
+
cnts = Docker::Util.parse_json(Docker.connection.get('/containers/json', {}))
|
76
|
+
rescue => e
|
77
|
+
log.warn "synapse: error polling docker host #{Docker.url}: #{e.inspect}"
|
78
|
+
next []
|
79
|
+
end
|
80
|
+
cnts.each do |cnt|
|
81
|
+
cnt['Ports'] = rewrite_container_ports cnt['Ports']
|
82
|
+
end
|
83
|
+
# Discover containers that match the image/port we're interested in
|
84
|
+
cnts = cnts.find_all do |cnt|
|
85
|
+
cnt["Image"].rpartition(":").first == @discovery["image_name"] \
|
86
|
+
and cnt["Ports"].has_key?(@discovery["container_port"].to_s())
|
87
|
+
end
|
88
|
+
cnts.map do |cnt|
|
89
|
+
{
|
90
|
+
'name' => server['name'],
|
91
|
+
'host' => server['host'],
|
92
|
+
'port' => cnt["Ports"][@discovery["container_port"].to_s()]
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
backends.flatten
|
97
|
+
rescue => e
|
98
|
+
log.warn "synapse: error while polling for containers: #{e.inspect}"
|
99
|
+
[]
|
100
|
+
end
|
101
|
+
|
102
|
+
def configure_backends(new_backends)
|
103
|
+
if new_backends.empty?
|
104
|
+
if @default_servers.empty?
|
105
|
+
log.warn "synapse: no backends and no default servers for service #{@name};" \
|
106
|
+
" using previous backends: #{@backends.inspect}"
|
107
|
+
else
|
108
|
+
log.warn "synapse: no backends for service #{@name};" \
|
109
|
+
" using default servers: #{@default_servers.inspect}"
|
110
|
+
@backends = @default_servers
|
111
|
+
end
|
112
|
+
else
|
113
|
+
log.info "synapse: discovered #{new_backends.length} backends for service #{@name}"
|
114
|
+
set_backends(new_backends)
|
115
|
+
end
|
116
|
+
reconfigure!
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'synapse/service_watcher/base'
|
2
|
+
require 'aws-sdk'
|
3
|
+
|
4
|
+
module Synapse
|
5
|
+
class EC2Watcher < BaseWatcher
|
6
|
+
|
7
|
+
attr_reader :check_interval
|
8
|
+
|
9
|
+
def start
|
10
|
+
region = @discovery['aws_region'] || ENV['AWS_REGION']
|
11
|
+
log.info "Connecting to EC2 region: #{region}"
|
12
|
+
|
13
|
+
@ec2 = AWS::EC2.new(
|
14
|
+
region: region,
|
15
|
+
access_key_id: @discovery['aws_access_key_id'] || ENV['AWS_ACCESS_KEY_ID'],
|
16
|
+
secret_access_key: @discovery['aws_secret_access_key'] || ENV['AWS_SECRET_ACCESS_KEY'] )
|
17
|
+
|
18
|
+
@check_interval = @discovery['check_interval'] || 15.0
|
19
|
+
|
20
|
+
log.info "synapse: ec2tag watcher looking for instances " +
|
21
|
+
"tagged with #{@discovery['tag_name']}=#{@discovery['tag_value']}"
|
22
|
+
|
23
|
+
@watcher = Thread.new { watch }
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def validate_discovery_opts
|
29
|
+
# Required, via options only.
|
30
|
+
raise ArgumentError, "invalid discovery method #{@discovery['method']}" \
|
31
|
+
unless @discovery['method'] == 'ec2tag'
|
32
|
+
raise ArgumentError, "aws tag name is required for service #{@name}" \
|
33
|
+
unless @discovery['tag_name']
|
34
|
+
raise ArgumentError, "aws tag value required for service #{@name}" \
|
35
|
+
unless @discovery['tag_value']
|
36
|
+
|
37
|
+
# As we're only looking up instances with hostnames/IPs, need to
|
38
|
+
# be explicitly told which port the service we're balancing for listens on.
|
39
|
+
unless @haproxy['server_port_override']
|
40
|
+
raise ArgumentError,
|
41
|
+
"Missing server_port_override for service #{@name} - which port are backends listening on?"
|
42
|
+
end
|
43
|
+
|
44
|
+
unless @haproxy['server_port_override'].match(/^\d+$/)
|
45
|
+
raise ArgumentError, "Invalid server_port_override value"
|
46
|
+
end
|
47
|
+
|
48
|
+
# Required, but can use well-known environment variables.
|
49
|
+
%w[aws_access_key_id aws_secret_access_key aws_region].each do |attr|
|
50
|
+
unless (@discovery[attr] || ENV[attr.upcase])
|
51
|
+
raise ArgumentError, "Missing #{attr} option or #{attr.upcase} environment variable"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def watch
|
57
|
+
last_backends = []
|
58
|
+
until @should_exit
|
59
|
+
begin
|
60
|
+
start = Time.now
|
61
|
+
current_backends = discover_instances
|
62
|
+
|
63
|
+
if last_backends != current_backends
|
64
|
+
log.info "synapse: ec2tag watcher backends have changed."
|
65
|
+
last_backends = current_backends
|
66
|
+
configure_backends(current_backends)
|
67
|
+
else
|
68
|
+
log.info "synapse: ec2tag watcher backends are unchanged."
|
69
|
+
end
|
70
|
+
|
71
|
+
sleep_until_next_check(start)
|
72
|
+
rescue Exception => e
|
73
|
+
log.warn "synapse: error in ec2tag watcher thread: #{e.inspect}"
|
74
|
+
log.warn e.backtrace
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
log.info "synapse: ec2tag watcher exited successfully"
|
79
|
+
end
|
80
|
+
|
81
|
+
def sleep_until_next_check(start_time)
|
82
|
+
sleep_time = check_interval - (Time.now - start_time)
|
83
|
+
if sleep_time > 0.0
|
84
|
+
sleep(sleep_time)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def discover_instances
|
89
|
+
AWS.memoize do
|
90
|
+
instances = instances_with_tags(@discovery['tag_name'], @discovery['tag_value'])
|
91
|
+
|
92
|
+
new_backends = []
|
93
|
+
|
94
|
+
# choice of private_dns_name, dns_name, private_ip_address or
|
95
|
+
# ip_address, for now, just stick with the private fields.
|
96
|
+
instances.each do |instance|
|
97
|
+
new_backends << {
|
98
|
+
'name' => instance.private_dns_name,
|
99
|
+
'host' => instance.private_ip_address,
|
100
|
+
'port' => @haproxy['server_port_override'],
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
new_backends
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def instances_with_tags(tag_name, tag_value)
|
109
|
+
@ec2.instances
|
110
|
+
.tagged(tag_name)
|
111
|
+
.tagged_values(tag_value)
|
112
|
+
.select { |i| i.status == :running }
|
113
|
+
end
|
114
|
+
|
115
|
+
def configure_backends(new_backends)
|
116
|
+
if new_backends.empty?
|
117
|
+
if @default_servers.empty?
|
118
|
+
log.warn "synapse: no backends and no default servers for service #{@name};" \
|
119
|
+
" using previous backends: #{@backends.inspect}"
|
120
|
+
else
|
121
|
+
log.warn "synapse: no backends for service #{@name};" \
|
122
|
+
" using default servers: #{@default_servers.inspect}"
|
123
|
+
@backends = @default_servers
|
124
|
+
end
|
125
|
+
else
|
126
|
+
log.info "synapse: discovered #{new_backends.length} backends for service #{@name}"
|
127
|
+
@backends = new_backends
|
128
|
+
end
|
129
|
+
@synapse.reconfigure!
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|