syncwrap 2.6.2 → 2.7.0
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 +4 -4
- data/History.rdoc +44 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +3 -3
- data/bin/syncwrap +1 -1
- data/lib/syncwrap/amazon_ec2.rb +1 -1
- data/lib/syncwrap/amazon_ws.rb +51 -17
- data/lib/syncwrap/base.rb +2 -2
- data/lib/syncwrap/cli.rb +1 -1
- data/lib/syncwrap/component.rb +6 -1
- data/lib/syncwrap/components/amazon_linux.rb +1 -1
- data/lib/syncwrap/components/arch.rb +48 -5
- data/lib/syncwrap/components/bundle.rb +1 -1
- data/lib/syncwrap/components/bundled_iyyov_daemon.rb +1 -1
- data/lib/syncwrap/components/bundler_gem.rb +1 -1
- data/lib/syncwrap/components/centos.rb +1 -1
- data/lib/syncwrap/components/commercial_jdk.rb +2 -1
- data/lib/syncwrap/components/cruby_vm.rb +15 -11
- data/lib/syncwrap/components/debian.rb +46 -10
- data/lib/syncwrap/components/etc_hosts.rb +1 -1
- data/lib/syncwrap/components/geminabox.rb +1 -1
- data/lib/syncwrap/components/hashdot.rb +2 -2
- data/lib/syncwrap/components/iyyov.rb +1 -1
- data/lib/syncwrap/components/iyyov_daemon.rb +1 -1
- data/lib/syncwrap/components/jruby_vm.rb +13 -7
- data/lib/syncwrap/components/lvm_cache.rb +1 -1
- data/lib/syncwrap/components/mdraid.rb +1 -1
- data/lib/syncwrap/components/network.rb +1 -1
- data/lib/syncwrap/components/open_jdk.rb +1 -1
- data/lib/syncwrap/components/postgresql.rb +24 -4
- data/lib/syncwrap/components/puma.rb +1 -1
- data/lib/syncwrap/components/qpid.rb +1 -1
- data/lib/syncwrap/components/rake_gem.rb +1 -1
- data/lib/syncwrap/components/rhel.rb +38 -17
- data/lib/syncwrap/components/run_user.rb +1 -1
- data/lib/syncwrap/components/source_tree.rb +1 -1
- data/lib/syncwrap/components/tarpit_gem.rb +1 -1
- data/lib/syncwrap/components/ubuntu.rb +1 -1
- data/lib/syncwrap/components/users.rb +10 -1
- data/lib/syncwrap/context.rb +11 -1
- data/lib/syncwrap/distro.rb +10 -5
- data/lib/syncwrap/formatter.rb +1 -1
- data/lib/syncwrap/git_help.rb +1 -1
- data/lib/syncwrap/hash_support.rb +1 -1
- data/lib/syncwrap/host.rb +1 -1
- data/lib/syncwrap/main.rb +1 -1
- data/lib/syncwrap/path_util.rb +1 -1
- data/lib/syncwrap/rsync.rb +8 -17
- data/lib/syncwrap/ruby_support.rb +1 -1
- data/lib/syncwrap/shell.rb +1 -1
- data/lib/syncwrap/systemd.rb +1 -1
- data/lib/syncwrap/user_data.rb +1 -1
- data/lib/syncwrap/version_support.rb +1 -1
- data/lib/syncwrap/zone_balancer.rb +65 -0
- data/lib/syncwrap.rb +19 -6
- data/sync/postgresql/postgresql.conf.erb +27 -5
- data/test/setup.rb +1 -1
- data/test/test_components.rb +3 -1
- data/test/test_context.rb +1 -1
- data/test/test_context_rput.rb +1 -1
- data/test/test_rsync.rb +1 -1
- data/test/test_shell.rb +1 -1
- data/test/test_space.rb +1 -1
- data/test/test_space_main.rb +9 -2
- data/test/test_version_support.rb +1 -1
- data/test/test_zone_balancer.rb +48 -0
- metadata +4 -2
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You may
|
@@ -40,6 +40,7 @@ module SyncWrap
|
|
40
40
|
# * RHEL, CentOS 7: 9.2
|
41
41
|
# * AmazonLinux 2013.03: 8.4 9.2
|
42
42
|
# * AmazonLinux 2014.09: 8.4 9.2 9.3
|
43
|
+
# * AmazonLinux 2015.09: 9.2 9.3 9.4
|
43
44
|
# * Debian 7: 9.1
|
44
45
|
# * Debian 8: 9.4
|
45
46
|
# * Ubuntu 14: 9.3
|
@@ -150,8 +151,25 @@ module SyncWrap
|
|
150
151
|
# increased risk. (PG Default: 0 -> none)
|
151
152
|
attr_accessor :commit_delay
|
152
153
|
|
153
|
-
# WAL log segments (16MB each)
|
154
|
-
|
154
|
+
# WAL log segments (16MB each)
|
155
|
+
# Deprecated with PostgreSQL 9.5: Use min/max_wal_size instead
|
156
|
+
attr_writer :checkpoint_segments
|
157
|
+
|
158
|
+
def checkpoint_segments
|
159
|
+
@checkpoint_segments || ( version_lt?(pg_version, [9,5]) ? 3 : 5 )
|
160
|
+
end
|
161
|
+
|
162
|
+
# Minimum WAL size as string with units
|
163
|
+
# Default: PG <9.5: "48MB"; PG 9.5+: "80MB"
|
164
|
+
attr_writer :min_wal_size
|
165
|
+
|
166
|
+
def min_wal_size
|
167
|
+
@min_wal_size || "#{ checkpoint_segments * 16 }MB"
|
168
|
+
end
|
169
|
+
|
170
|
+
# Maximum WAL size as string with units.
|
171
|
+
# (Default: unset, PG Default: '1GB')
|
172
|
+
attr_accessor :max_wal_size
|
155
173
|
|
156
174
|
# Shared buffers (Default: '256MB' vs PG: '128MB')
|
157
175
|
attr_accessor :shared_buffers
|
@@ -231,7 +249,9 @@ module SyncWrap
|
|
231
249
|
@service_name = 'postgresql'
|
232
250
|
@synchronous_commit = :on
|
233
251
|
@commit_delay = 0
|
234
|
-
@checkpoint_segments =
|
252
|
+
@checkpoint_segments = nil
|
253
|
+
@min_wal_size = nil
|
254
|
+
@max_wal_size = nil
|
235
255
|
@shared_buffers = '256MB'
|
236
256
|
@work_mem = '128MB'
|
237
257
|
@maintenance_work_mem = '128MB'
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You may
|
@@ -45,17 +45,21 @@ module SyncWrap
|
|
45
45
|
# interpreted as options, see below.
|
46
46
|
#
|
47
47
|
# ==== Options
|
48
|
-
# :succeed:: Always succeed (useful for local rpm files which
|
49
|
-
# might already be installed.)
|
50
48
|
#
|
51
|
-
#
|
49
|
+
# :check_install:: Short-circuit if all packages already
|
50
|
+
# installed. Thus no upgrades will be performed.
|
51
|
+
#
|
52
|
+
# :succeed:: Deprecated, use check_install instead
|
53
|
+
#
|
54
|
+
# Additional options are passed to the sudo calls.
|
52
55
|
def dist_install( *pkgs )
|
53
|
-
opts = pkgs.last.is_a?( Hash ) && pkgs.pop || {}
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
56
|
+
opts = pkgs.last.is_a?( Hash ) && pkgs.pop.dup || {}
|
57
|
+
opts.delete( :minimal )
|
58
|
+
pkgs.flatten!
|
59
|
+
chk = opts.delete( :check_install ) || opts.delete( :succeed )
|
60
|
+
chk = check_install? if chk.nil?
|
61
|
+
dist_if_not_installed?( pkgs, chk, opts ) do
|
62
|
+
sudo( "yum install -q -y #{pkgs.join( ' ' )}", opts )
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
@@ -63,19 +67,36 @@ module SyncWrap
|
|
63
67
|
# interpreted as options, see below.
|
64
68
|
#
|
65
69
|
# ==== Options
|
66
|
-
# :succeed:: Succeed even if no such packages are installed
|
67
70
|
#
|
68
|
-
#
|
71
|
+
# :succeed:: Succeed even if none of the packages are
|
72
|
+
# installed. (Deprecated, Default: true)
|
73
|
+
#
|
74
|
+
# Additional options are passed to the sudo calls.
|
69
75
|
def dist_uninstall( *pkgs )
|
70
|
-
opts = pkgs.last.is_a?( Hash ) && pkgs.pop || {}
|
71
|
-
|
72
|
-
|
73
|
-
|
76
|
+
opts = pkgs.last.is_a?( Hash ) && pkgs.pop.dup || {}
|
77
|
+
pkgs.flatten!
|
78
|
+
if opts.delete( :succeed ) != false
|
79
|
+
sudo( <<-SH, opts )
|
80
|
+
if yum list -C -q installed #{pkgs.join( ' ' )} >/dev/null 2>&1; then
|
74
81
|
yum remove -q -y #{pkgs.join( ' ' )}
|
75
82
|
fi
|
76
83
|
SH
|
77
84
|
else
|
78
|
-
sudo "yum remove -q -y #{pkgs.join( ' ' )}"
|
85
|
+
sudo( "yum remove -q -y #{pkgs.join( ' ' )}", opts )
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# If chk is true, then wrap block in a sudo bash conditional
|
90
|
+
# testing if any specified pkgs are not installed. Otherwise just
|
91
|
+
# yield to block.
|
92
|
+
def dist_if_not_installed?( pkgs, chk, opts, &block )
|
93
|
+
if chk
|
94
|
+
qry = "yum list -C -q installed #{pkgs.join ' '}"
|
95
|
+
cnt = qry + " | tail -n +2 | wc -l"
|
96
|
+
cond = %Q{if [ "$(#{cnt})" != "#{pkgs.count}" ]; then}
|
97
|
+
sudo( cond, opts.merge( close: 'fi' ), &block )
|
98
|
+
else
|
99
|
+
block.call
|
79
100
|
end
|
80
101
|
end
|
81
102
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You may
|
@@ -99,6 +99,15 @@ module SyncWrap
|
|
99
99
|
set_sudoers( u )
|
100
100
|
end
|
101
101
|
|
102
|
+
# Some distro's, like Debian, don't come with rsync installed so
|
103
|
+
# need to install it here. For backward compatibly, only do
|
104
|
+
# this if dist_install is defined (i.e. Distro component before
|
105
|
+
# self.)
|
106
|
+
if !users.empty? && respond_to?( :dist_install )
|
107
|
+
dist_install( 'rsync',
|
108
|
+
ssh_flags.merge( minimal: true, check_install: true ) )
|
109
|
+
end
|
110
|
+
|
102
111
|
users.each do |u|
|
103
112
|
sync_home_files( u )
|
104
113
|
end
|
data/lib/syncwrap/context.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You
|
@@ -82,6 +82,12 @@ module SyncWrap
|
|
82
82
|
@default_options[ :verbose ]
|
83
83
|
end
|
84
84
|
|
85
|
+
# Return any value of :check_install set in constructed default
|
86
|
+
# options.
|
87
|
+
def check_install?
|
88
|
+
@default_options[ :check_install ]
|
89
|
+
end
|
90
|
+
|
85
91
|
# See Component#sh for interface details
|
86
92
|
def sh( command, opts = {} )
|
87
93
|
opts = @default_options.merge( opts )
|
@@ -150,6 +156,10 @@ module SyncWrap
|
|
150
156
|
if maybes.empty?
|
151
157
|
changes = rsync( plains, target, opts ) unless plains.empty?
|
152
158
|
else
|
159
|
+
if ssh_host_name == 'localhost' && opts[ :user ]
|
160
|
+
# tmpdir needs to be visable to alt. opts[ :user ]
|
161
|
+
opts[ :tmpdir_mode ] = 0755
|
162
|
+
end
|
153
163
|
process_templates( maybes, opts ) do |processed|
|
154
164
|
unless processed.empty? || plains.empty?
|
155
165
|
opts = opts.dup
|
data/lib/syncwrap/distro.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You may
|
@@ -41,15 +41,20 @@ module SyncWrap
|
|
41
41
|
#
|
42
42
|
# ==== Options
|
43
43
|
#
|
44
|
-
# :
|
45
|
-
#
|
44
|
+
# :check_install:: Short-circuit if all packages already
|
45
|
+
# installed. Thus no upgrades will be performed.
|
46
46
|
#
|
47
|
-
# :
|
47
|
+
# :succeed:: Deprecated, use check_install instead
|
48
|
+
#
|
49
|
+
# :minimal:: Avoid additional "optional" packages when possible
|
50
|
+
#
|
51
|
+
# Additional options are passed to the sudo calls.
|
48
52
|
def dist_install( *pkgs )
|
49
53
|
raise "Include a distro-specific component, e.g. Debian, RHEL"
|
50
54
|
end
|
51
55
|
|
52
|
-
# Uninstall the specified package names.
|
56
|
+
# Uninstall the specified package names. A trailing hash is
|
57
|
+
# interpreted as options, passed to the sudo calls.
|
53
58
|
def dist_uninstall( *pkgs )
|
54
59
|
raise "Include a distro-specific component, e.g. Debian, RHEL"
|
55
60
|
end
|
data/lib/syncwrap/formatter.rb
CHANGED
data/lib/syncwrap/git_help.rb
CHANGED
data/lib/syncwrap/host.rb
CHANGED
data/lib/syncwrap/main.rb
CHANGED
data/lib/syncwrap/path_util.rb
CHANGED
data/lib/syncwrap/rsync.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You may
|
@@ -169,7 +169,7 @@ module SyncWrap
|
|
169
169
|
def process_templates( srcs, opts ) # :doc:
|
170
170
|
bnd = opts[ :erb_binding ] or raise "required :erb_binding param missing"
|
171
171
|
erb_mode = opts[ :erb_mode ] || '<>' #Trim new line on "<% ... %>\n"
|
172
|
-
mktmpdir(
|
172
|
+
mktmpdir( opts ) do |tmp_dir|
|
173
173
|
processed_sources = []
|
174
174
|
out_dir = File.join( tmp_dir, 'd' ) #for default perms
|
175
175
|
srcs.each do |src|
|
@@ -196,23 +196,14 @@ module SyncWrap
|
|
196
196
|
end
|
197
197
|
end
|
198
198
|
|
199
|
-
#
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
newdir = nil
|
204
|
-
if defined?( JRUBY_VERSION ) && JRUBY_VERSION =~ /^1.6/
|
205
|
-
old_env_tmpdir = ENV['TMPDIR']
|
206
|
-
newdir = "/tmp/syncwrap.#{ENV['USER']}"
|
207
|
-
FileUtils.mkdir_p( newdir, mode: 0700 )
|
208
|
-
ENV['TMPDIR'] = newdir
|
209
|
-
end
|
210
|
-
Dir.mktmpdir( prefix ) do |tmp_dir|
|
211
|
-
yield tmp_dir
|
199
|
+
# Like Dir.mktmpdir but with option to specify :tmpdir_mode.
|
200
|
+
def mktmpdir( opts ) # :doc:
|
201
|
+
path = Dir::Tmpname.create( 'syncwrap-' ) do |n|
|
202
|
+
Dir.mkdir( n, opts[ :tmpdir_mode ] || 0700 )
|
212
203
|
end
|
204
|
+
yield path
|
213
205
|
ensure
|
214
|
-
FileUtils.
|
215
|
-
ENV['TMPDIR'] = old_env_tmpdir if old_env_tmpdir
|
206
|
+
FileUtils.remove_entry( path ) if path
|
216
207
|
end
|
217
208
|
|
218
209
|
def find_source_erbs( sources ) # :doc:
|
data/lib/syncwrap/shell.rb
CHANGED
data/lib/syncwrap/systemd.rb
CHANGED
data/lib/syncwrap/user_data.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
|
+
# may not use this file except in compliance with the License. You may
|
6
|
+
# obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
13
|
+
# implied. See the License for the specific language governing
|
14
|
+
# permissions and limitations under the License.
|
15
|
+
#++
|
16
|
+
|
17
|
+
module SyncWrap
|
18
|
+
|
19
|
+
# Utility for balancing new hosts accross multiple (AWS)
|
20
|
+
# availability zones for fault tolarance.
|
21
|
+
module ZoneBalancer
|
22
|
+
|
23
|
+
# Returns a ruby Proc which when called will return the best
|
24
|
+
# pick of availability zone, via ::next_zone. This variant
|
25
|
+
# uses Space.current within a Space#with block.
|
26
|
+
def self.zone( zones, roles )
|
27
|
+
space = Space.current
|
28
|
+
lambda do
|
29
|
+
next_zone( space, zones, roles )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return the next best zone from zones Array<String>, preferring
|
34
|
+
# the least frequent :availability_zone of existing hosts in the
|
35
|
+
# specified space and roles (Array<Symbol>, if empty all hosts).
|
36
|
+
def self.next_zone( space, zones, roles = [] )
|
37
|
+
if zones
|
38
|
+
hosts = filter_hosts( space.hosts, roles )
|
39
|
+
zfreqs = {}
|
40
|
+
zones.each { |z| zfreqs[z] = 0 }
|
41
|
+
czones = hosts.map { |h| h[:availability_zone] }.compact
|
42
|
+
czones.each { |z| zfreqs[z] += 1 if zfreqs.has_key?( z ) }
|
43
|
+
|
44
|
+
# Sort by ascending frequency (lowest first). Keep order stable
|
45
|
+
# from original zones, when frequency tied.
|
46
|
+
# Return the first (least frequent, zones stable) zone.
|
47
|
+
n = 0
|
48
|
+
zfreqs.sort_by { |_,f| [ f, (n+=1) ] }.first[0]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def self.filter_hosts( hosts, roles )
|
55
|
+
unless roles.empty?
|
56
|
+
hosts = hosts.select do |h|
|
57
|
+
h.roles.any? { |r| roles.include?( r ) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
hosts
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
data/lib/syncwrap.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c) 2011-
|
2
|
+
# Copyright (c) 2011-2016 David Kellum
|
3
3
|
#
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License"); you
|
5
5
|
# may not use this file except in compliance with the License. You may
|
@@ -22,6 +22,7 @@ require 'syncwrap/context'
|
|
22
22
|
require 'syncwrap/host'
|
23
23
|
require 'syncwrap/formatter'
|
24
24
|
require 'syncwrap/path_util'
|
25
|
+
require 'syncwrap/version_support.rb'
|
25
26
|
|
26
27
|
module SyncWrap
|
27
28
|
|
@@ -51,6 +52,7 @@ module SyncWrap
|
|
51
52
|
# level #execute.
|
52
53
|
class Space
|
53
54
|
include PathUtil
|
55
|
+
include VersionSupport
|
54
56
|
|
55
57
|
# Return the current space, as setup within a Space#with block, or
|
56
58
|
# raise something fierce.
|
@@ -92,11 +94,11 @@ module SyncWrap
|
|
92
94
|
def load_sync_file( filename )
|
93
95
|
require 'syncwrap/main'
|
94
96
|
with do
|
95
|
-
load( filename,
|
96
|
-
#
|
97
|
-
#
|
98
|
-
# binding scheme of components. If not done,
|
99
|
-
# methods/vars in sync.rb would have precidents over
|
97
|
+
load( filename, wrap_sync_load? )
|
98
|
+
# Should wrap to avoid pollution of sync namespace, but there
|
99
|
+
# are jruby bugs to workaround. This is particularly important
|
100
|
+
# given the dynamic binding scheme of components. If not done,
|
101
|
+
# top-level methods/vars in sync.rb would have precidents over
|
100
102
|
# component methods.
|
101
103
|
end
|
102
104
|
end
|
@@ -291,6 +293,16 @@ module SyncWrap
|
|
291
293
|
|
292
294
|
private
|
293
295
|
|
296
|
+
# Return true if wrapped load should be attempted on this ruby
|
297
|
+
# Avoid this only on JRuby 9.0.0-9.0.4, which will fail hard.
|
298
|
+
#
|
299
|
+
# See https://github.com/jruby/jruby/issues/3180
|
300
|
+
def wrap_sync_load?
|
301
|
+
( !defined?( JRUBY_VERSION ) ||
|
302
|
+
version_lt?( JRUBY_VERSION, [9] ) ||
|
303
|
+
version_gte?( JRUBY_VERSION, [9,0,5] ) )
|
304
|
+
end
|
305
|
+
|
294
306
|
def execute_host( host, component_plan = [], opts = {} )
|
295
307
|
comp_roles = opts[ :comp_roles ]
|
296
308
|
comps = if comp_roles && !comp_roles.empty?
|
@@ -413,5 +425,6 @@ module SyncWrap
|
|
413
425
|
autoload :AmazonEC2, 'syncwrap/amazon_ec2'
|
414
426
|
autoload :GitHelp, 'syncwrap/git_help'
|
415
427
|
autoload :UserData, 'syncwrap/user_data'
|
428
|
+
autoload :ZoneBalancer, 'syncwrap/zone_balancer'
|
416
429
|
|
417
430
|
end
|