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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/History.rdoc +44 -0
  3. data/Manifest.txt +2 -0
  4. data/README.rdoc +3 -3
  5. data/bin/syncwrap +1 -1
  6. data/lib/syncwrap/amazon_ec2.rb +1 -1
  7. data/lib/syncwrap/amazon_ws.rb +51 -17
  8. data/lib/syncwrap/base.rb +2 -2
  9. data/lib/syncwrap/cli.rb +1 -1
  10. data/lib/syncwrap/component.rb +6 -1
  11. data/lib/syncwrap/components/amazon_linux.rb +1 -1
  12. data/lib/syncwrap/components/arch.rb +48 -5
  13. data/lib/syncwrap/components/bundle.rb +1 -1
  14. data/lib/syncwrap/components/bundled_iyyov_daemon.rb +1 -1
  15. data/lib/syncwrap/components/bundler_gem.rb +1 -1
  16. data/lib/syncwrap/components/centos.rb +1 -1
  17. data/lib/syncwrap/components/commercial_jdk.rb +2 -1
  18. data/lib/syncwrap/components/cruby_vm.rb +15 -11
  19. data/lib/syncwrap/components/debian.rb +46 -10
  20. data/lib/syncwrap/components/etc_hosts.rb +1 -1
  21. data/lib/syncwrap/components/geminabox.rb +1 -1
  22. data/lib/syncwrap/components/hashdot.rb +2 -2
  23. data/lib/syncwrap/components/iyyov.rb +1 -1
  24. data/lib/syncwrap/components/iyyov_daemon.rb +1 -1
  25. data/lib/syncwrap/components/jruby_vm.rb +13 -7
  26. data/lib/syncwrap/components/lvm_cache.rb +1 -1
  27. data/lib/syncwrap/components/mdraid.rb +1 -1
  28. data/lib/syncwrap/components/network.rb +1 -1
  29. data/lib/syncwrap/components/open_jdk.rb +1 -1
  30. data/lib/syncwrap/components/postgresql.rb +24 -4
  31. data/lib/syncwrap/components/puma.rb +1 -1
  32. data/lib/syncwrap/components/qpid.rb +1 -1
  33. data/lib/syncwrap/components/rake_gem.rb +1 -1
  34. data/lib/syncwrap/components/rhel.rb +38 -17
  35. data/lib/syncwrap/components/run_user.rb +1 -1
  36. data/lib/syncwrap/components/source_tree.rb +1 -1
  37. data/lib/syncwrap/components/tarpit_gem.rb +1 -1
  38. data/lib/syncwrap/components/ubuntu.rb +1 -1
  39. data/lib/syncwrap/components/users.rb +10 -1
  40. data/lib/syncwrap/context.rb +11 -1
  41. data/lib/syncwrap/distro.rb +10 -5
  42. data/lib/syncwrap/formatter.rb +1 -1
  43. data/lib/syncwrap/git_help.rb +1 -1
  44. data/lib/syncwrap/hash_support.rb +1 -1
  45. data/lib/syncwrap/host.rb +1 -1
  46. data/lib/syncwrap/main.rb +1 -1
  47. data/lib/syncwrap/path_util.rb +1 -1
  48. data/lib/syncwrap/rsync.rb +8 -17
  49. data/lib/syncwrap/ruby_support.rb +1 -1
  50. data/lib/syncwrap/shell.rb +1 -1
  51. data/lib/syncwrap/systemd.rb +1 -1
  52. data/lib/syncwrap/user_data.rb +1 -1
  53. data/lib/syncwrap/version_support.rb +1 -1
  54. data/lib/syncwrap/zone_balancer.rb +65 -0
  55. data/lib/syncwrap.rb +19 -6
  56. data/sync/postgresql/postgresql.conf.erb +27 -5
  57. data/test/setup.rb +1 -1
  58. data/test/test_components.rb +3 -1
  59. data/test/test_context.rb +1 -1
  60. data/test/test_context_rput.rb +1 -1
  61. data/test/test_rsync.rb +1 -1
  62. data/test/test_shell.rb +1 -1
  63. data/test/test_space.rb +1 -1
  64. data/test/test_space_main.rb +9 -2
  65. data/test/test_version_support.rb +1 -1
  66. data/test/test_zone_balancer.rb +48 -0
  67. metadata +4 -2
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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) (PG Default: 3)
154
- attr_accessor :checkpoint_segments
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 = 3
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-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
- # Other options will be ignored.
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
- if opts[ :succeed ]
56
- sudo "yum install -q -y #{pkgs.join( ' ' )} || true"
57
- else
58
- sudo "yum install -q -y #{pkgs.join( ' ' )}"
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
- # Other options will be ignored.
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
- if opts[ :succeed ]
72
- sudo <<-SH
73
- if yum list -q installed #{pkgs.join( ' ' )} >/dev/null 2>&1; then
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-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
- # :succeed:: Always succeed (useful for local rpms which might
45
- # already be installed.
44
+ # :check_install:: Short-circuit if all packages already
45
+ # installed. Thus no upgrades will be performed.
46
46
  #
47
- # :minimal:: Avoid additional "optional" packages when possible.
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
data/lib/syncwrap/host.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
data/lib/syncwrap/main.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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( 'syncwrap-' ) do |tmp_dir|
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
- # Just like Dir.mktmpdir but with an attempt to workaround a JRuby
200
- # 1.6.x bug. See https://jira.codehaus.org/browse/JRUBY-5678
201
- def mktmpdir( prefix ) # :doc:
202
- old_env_tmpdir = nil
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.rmdir( newdir ) if newdir
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:
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -1,5 +1,5 @@
1
1
  #--
2
- # Copyright (c) 2011-2015 David Kellum
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
@@ -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-2015 David Kellum
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, true )
96
- # This is true -> wrapped to avoid pollution of sync
97
- # namespace. This is particularly important given the dynamic
98
- # binding scheme of components. If not done, top-level
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