syncwrap 1.5.2 → 2.0.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 (107) hide show
  1. checksums.yaml +7 -0
  2. data/History.rdoc +19 -0
  3. data/Manifest.txt +82 -34
  4. data/README.rdoc +96 -48
  5. data/Rakefile +0 -65
  6. data/bin/syncwrap +27 -0
  7. data/examples/LAYOUT.rdoc +70 -0
  8. data/examples/Rakefile +16 -0
  9. data/examples/ec2.rb +44 -0
  10. data/examples/hello.rb +14 -0
  11. data/examples/hello_binding.rb +27 -0
  12. data/examples/jruby.rb +11 -0
  13. data/examples/private/aws.json +4 -0
  14. data/examples/rput.rb +24 -0
  15. data/examples/sync/home/bob/.ssh/authorized_keys +1 -0
  16. data/examples/sync/tmp/sample.erb +3 -0
  17. data/lib/syncwrap/amazon_ec2.rb +236 -0
  18. data/lib/syncwrap/amazon_ws.rb +308 -0
  19. data/lib/syncwrap/base.rb +4 -2
  20. data/lib/syncwrap/cli.rb +328 -0
  21. data/lib/syncwrap/component.rb +443 -0
  22. data/lib/syncwrap/components/commercial_jdk.rb +76 -0
  23. data/lib/syncwrap/components/cruby_vm.rb +144 -0
  24. data/lib/syncwrap/components/etc_hosts.rb +44 -0
  25. data/lib/syncwrap/{geminabox.rb → components/geminabox.rb} +12 -17
  26. data/lib/syncwrap/components/hashdot.rb +97 -0
  27. data/lib/syncwrap/components/iyyov.rb +144 -0
  28. data/lib/syncwrap/components/iyyov_daemon.rb +125 -0
  29. data/lib/syncwrap/components/jruby_vm.rb +122 -0
  30. data/lib/syncwrap/components/mdraid.rb +204 -0
  31. data/lib/syncwrap/components/network.rb +99 -0
  32. data/lib/syncwrap/components/open_jdk.rb +70 -0
  33. data/lib/syncwrap/components/postgresql.rb +159 -0
  34. data/lib/syncwrap/components/qpid.rb +303 -0
  35. data/lib/syncwrap/components/rhel.rb +71 -0
  36. data/lib/syncwrap/components/run_user.rb +99 -0
  37. data/lib/syncwrap/components/ubuntu.rb +85 -0
  38. data/lib/syncwrap/components/users.rb +200 -0
  39. data/lib/syncwrap/context.rb +260 -0
  40. data/lib/syncwrap/distro.rb +53 -60
  41. data/lib/syncwrap/formatter.rb +149 -0
  42. data/lib/syncwrap/host.rb +134 -0
  43. data/lib/syncwrap/main.rb +62 -0
  44. data/lib/syncwrap/path_util.rb +55 -0
  45. data/lib/syncwrap/rsync.rb +227 -0
  46. data/lib/syncwrap/ruby_support.rb +110 -0
  47. data/lib/syncwrap/shell.rb +207 -0
  48. data/lib/syncwrap.rb +367 -1
  49. data/{etc → sync/etc}/gemrc +1 -3
  50. data/sync/etc/hosts.erb +8 -0
  51. data/{etc/init.d/iyyov → sync/etc/init.d/iyyov.erb} +35 -7
  52. data/sync/etc/sysconfig/pgsql/postgresql.erb +2 -0
  53. data/sync/src/hashdot/Makefile.erb +98 -0
  54. data/sync/src/hashdot/profiles/default.hdp.erb +25 -0
  55. data/sync/src/hashdot/profiles/jruby-common.hdp +28 -0
  56. data/sync/src/hashdot/profiles/jruby-shortlived.hdp +9 -0
  57. data/sync/src/hashdot/profiles/jruby.hdp.erb +13 -0
  58. data/sync/src/hashdot/profiles/shortlived.hdp +6 -0
  59. data/sync/var/iyyov/default/config.rb +1 -0
  60. data/sync/var/iyyov/default/daemon.rb.erb +15 -0
  61. data/sync/var/iyyov/jobs.rb.erb +4 -0
  62. data/test/muddled_sync.rb +13 -0
  63. data/test/setup.rb +39 -0
  64. data/test/sync/d1/bar +1 -0
  65. data/test/sync/d1/foo.erb +1 -0
  66. data/test/sync/d3/d2/bar +1 -0
  67. data/test/sync/d3/d2/foo.erb +1 -0
  68. data/test/test_components.rb +108 -0
  69. data/test/test_context.rb +107 -0
  70. data/test/test_context_rput.rb +289 -0
  71. data/test/test_rsync.rb +138 -0
  72. data/test/test_shell.rb +233 -0
  73. data/test/test_space.rb +218 -0
  74. data/test/test_space_main.rb +40 -0
  75. data/test/zfile +1 -0
  76. metadata +204 -71
  77. data/etc/sysconfig/pgsql/postgresql +0 -2
  78. data/lib/syncwrap/aws.rb +0 -448
  79. data/lib/syncwrap/common.rb +0 -161
  80. data/lib/syncwrap/ec2.rb +0 -59
  81. data/lib/syncwrap/hashdot.rb +0 -70
  82. data/lib/syncwrap/iyyov.rb +0 -139
  83. data/lib/syncwrap/java.rb +0 -61
  84. data/lib/syncwrap/jruby.rb +0 -118
  85. data/lib/syncwrap/postgresql.rb +0 -135
  86. data/lib/syncwrap/qpid.rb +0 -251
  87. data/lib/syncwrap/remote_task.rb +0 -199
  88. data/lib/syncwrap/rhel.rb +0 -67
  89. data/lib/syncwrap/ubuntu.rb +0 -78
  90. data/lib/syncwrap/user_run.rb +0 -102
  91. data/test/test_syncwrap.rb +0 -202
  92. data/var/iyyov/jobs.rb +0 -11
  93. /data/{etc → sync/etc}/corosync/corosync.conf +0 -0
  94. /data/{etc → sync/etc}/corosync/uidgid.d/qpid +0 -0
  95. /data/{etc → sync/etc}/init.d/qpidd +0 -0
  96. /data/{etc → sync/etc}/sysctl.d/61-postgresql-shm.conf +0 -0
  97. /data/{usr/local → sync/jruby}/bin/jgem +0 -0
  98. /data/{postgresql → sync/postgresql}/rhel/pg_hba.conf +0 -0
  99. /data/{postgresql → sync/postgresql}/rhel/pg_ident.conf +0 -0
  100. /data/{postgresql → sync/postgresql}/rhel/postgresql.conf +0 -0
  101. /data/{postgresql → sync/postgresql}/ubuntu/environment +0 -0
  102. /data/{postgresql → sync/postgresql}/ubuntu/pg_ctl.conf +0 -0
  103. /data/{postgresql → sync/postgresql}/ubuntu/pg_hba.conf +0 -0
  104. /data/{postgresql → sync/postgresql}/ubuntu/pg_ident.conf +0 -0
  105. /data/{postgresql → sync/postgresql}/ubuntu/postgresql.conf +0 -0
  106. /data/{postgresql → sync/postgresql}/ubuntu/start.conf +0 -0
  107. /data/{usr → sync/usr}/local/etc/qpidd.conf +0 -0
@@ -0,0 +1,443 @@
1
+ #--
2
+ # Copyright (c) 2011-2014 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
6
+ # may 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
+ require 'syncwrap/context'
18
+
19
+ module SyncWrap
20
+
21
+ # Base class and primary interface for component implementation.
22
+ #
23
+ # Much of the protected interface is ultimately delegated to a
24
+ # _current_ Context (arranged via Context#with). Without this, many
25
+ # of these methods will raise a ContextError.
26
+ #
27
+ # Components that require installation should implement a public
28
+ # no-argument `install` method which performs the installation via
29
+ # #rput, #sh et al. Complex installations can be broken into
30
+ # multiple methods called from install. If these are public and
31
+ # no-argument, they may also be called from the CLI or other
32
+ # external integrating code for testing or short-circuit
33
+ # operation. In general however, install should be fast enough to
34
+ # repeat in complete form. All such methods should be idempotent.
35
+ #
36
+ # Components may expose other public no-argument methods for
37
+ # external use which are not called via install. For example,
38
+ # diagnostic methods or uninstall.
39
+ #
40
+ # Components may also expose public utility methods (with or without
41
+ # arguments) that will be dynamically bound and may be used by
42
+ # higher (later) component instances stacked on the same Host.
43
+ class Component
44
+
45
+ # Construct given options that are applied via same name setters
46
+ # on self.
47
+ def initialize( opts = {} )
48
+ super()
49
+ opts.each do |name,val|
50
+ send( name.to_s + '=', val )
51
+ end
52
+ end
53
+
54
+ protected
55
+
56
+ # Return the Host of the current Context.
57
+ def host
58
+ ctx.host
59
+ end
60
+
61
+ # Enqueue a bash shell command or script fragment to be run on the
62
+ # host of the current Context. Newlines in command are interpreted
63
+ # as per bash. For example, it is common to use a here-document
64
+ # for readability:
65
+ #
66
+ # sh <<-SH
67
+ # if [ ! -e /var/#{fname} ]; then
68
+ # touch /var/#{fname}
69
+ # fi
70
+ # SH
71
+ # #=> nil
72
+ #
73
+ # If the current context host name is 'localhost' then the command
74
+ # is executed locally, without ssh and any ssh options will not be
75
+ # used.
76
+ #
77
+ # Returns nil.
78
+ #
79
+ # See also #flush, in particular for possible collateral
80
+ # Exceptions.
81
+ #
82
+ # === Command Queue and Composition
83
+ #
84
+ # The provided options are enqueued along with the
85
+ # command/fragment for deferred execution. If a subsequent call
86
+ # uses the same options, then it is effectively joined using a
87
+ # newline with the prior commands in the queue. If a subsequent
88
+ # call changes options, than any current commands in the queue are
89
+ # executed (via #flush) before the current command is enqueued
90
+ # with the new options. It is possible for commands to be enqueued
91
+ # and joined across multiple Components within the same Context.
92
+ #
93
+ # For example the following will be executed as a single composed
94
+ # script fragment:
95
+ #
96
+ # sh "if [! -e /var/foobar]; then"
97
+ # sh " touch /var/foobar"
98
+ # sh "fi" #=> nil
99
+ #
100
+ # However the following will result in remote errors:
101
+ #
102
+ # sh "if [! -e /var/foobar]; then"
103
+ # sudo "touch /var/foobar" #=> CommandFailure
104
+ # sh "fi"
105
+ #
106
+ # ...since the initial fragment on the line 1 is incomplete,
107
+ # when it is flushed and executed, due to line 2 changing
108
+ # options (to user:root).
109
+ #
110
+ # When composing more elaborate conditionals or loops via local
111
+ # methods, it is better to use the block form of #sh with the
112
+ # :close option, like so:
113
+ #
114
+ # sh( "if [! -e /var/foobar]; then", close: "fi" ) do
115
+ # sudo "touch /var/foobar" #=> NestingError
116
+ # end
117
+ #
118
+ # While executing the block, #flush is _locked_. The above fails
119
+ # with a NestingError and accurate stack trace, without running
120
+ # any potentially dangerous, incomplete bash fragments on the
121
+ # remote side. Replace the call to sudo with sh above and the
122
+ # composed single fragment will execute without error. The block
123
+ # form may be nested to arbitrary depth.
124
+ #
125
+ # === Options
126
+ #
127
+ # :user:: Execute command via sudo as the specified user, for
128
+ # example: :root or "root". See also :ssh_user
129
+ #
130
+ # :sudo_flags:: Additional Array of arguments to sudo, if used
131
+ # (see :user) Default: []
132
+ #
133
+ # :ssh_flags:: Array of flags in addition to, or overridden by
134
+ # :ssh_options (-o), :ssh_user (-l) and :ssh_user_pem
135
+ # (-i).
136
+ #
137
+ # :ssh_options:: Hash of ssh option key, value strings.
138
+ #
139
+ # :ssh_user:: The ssh -l (login_name) flag.
140
+ #
141
+ # :ssh_user_pem:: The ssh -i (identity_file) flag.
142
+ #
143
+ # :dryrun:: Don't actually execute commands, via `bash -n` dry
144
+ # run mode. (default: false)
145
+ #
146
+ # :verbose:: Show STDOUT/STDERR from commands (default: false)
147
+ #
148
+ # :sh_verbose:: Option values :v (or true) and :x are passed as
149
+ # `bash -v` and `bash -x` respectively, in order to
150
+ # echo command lines, interleaved with any command
151
+ # output. In the :x case, command output will be
152
+ # post expanded. This option should generally be set
153
+ # even if :verbose if false, since it will still be
154
+ # useful to error output on a CommandFailure.
155
+ # Default: nil (but :v via Space.default_options)
156
+ #
157
+ # :coalesce:: Coalesce (or merge) STDOUT to STDERR either via ssh
158
+ # or bash, to avoid out-of-order verbose output (due
159
+ # to buffering/timing). STDERR is used to increase
160
+ # incremental output through ssh, which tends to
161
+ # buffer STDOUT.
162
+ # Default: false (but true via Space.default_options)
163
+ #
164
+ # :error:: Pass bash the -e option to terminate early on errors.
165
+ # Default: true
166
+ #
167
+ # :close:: An additional bash fragment to append after the
168
+ # provided shell command/fragment and block has been
169
+ # enqueued. See usage example above. Default: nil
170
+ #
171
+ # :accept:: An array of Integer exit codes that will be accepted,
172
+ # and not result in a CommandFailure being
173
+ # raised. Generally this is only used with
174
+ # #capture. Default: [0]
175
+ #
176
+ def sh( command, opts = {}, &block )
177
+ ctx.sh( command, opts, &block )
178
+ end
179
+
180
+ # Equivalent to `sh( command, user: :root )`
181
+ def sudo( command, opts = {}, &block )
182
+ sh( command, { user: :root }.merge( opts ), &block )
183
+ end
184
+
185
+ # Equivalent to `sh( command, user: run_user )` where run_user
186
+ # would typically come from the RunUser component.
187
+ def rudo( command, opts = {}, &block )
188
+ sh( command, { user: run_user }.merge( opts ), &block )
189
+ end
190
+
191
+ # Capture and return [exit_code, stdout] from command, where
192
+ # stdout is the entire stream read into a String. Any commands
193
+ # already queued via #sh are executed via #flush beforehand, to
194
+ # avoid ambiguous order of remote changes. Raises a CommandFailure
195
+ # if the resulting exit_code is outside the specified :accept
196
+ # option codes (by default, [0] only).
197
+ #
198
+ # Specify :coalesce if you want stderr merged with stdout in the
199
+ # return. See #sh for additional options. The options :coalesce,
200
+ # and :dryrun are not inherited from the Space/Context default
201
+ # options and must be explicitly passed.
202
+ #
203
+ # For the better performance achieved with larger script fragments
204
+ # and fewer ssh sessions, you should attempt to use #sh remote
205
+ # conditionals instead of testing with #capture on the local
206
+ # side. But sometimes this can't be easily avoided.
207
+ def capture( command, opts = {} )
208
+ ctx.capture( command, opts )
209
+ end
210
+
211
+ # Return true if the current Context is executing in dryrun mode,
212
+ # as per the :dryrun default option or via the command line
213
+ # --dryrun flag. This allows additional explicit testing and
214
+ # handling of this mode when necessary.
215
+ def dryrun?
216
+ ctx.dryrun?
217
+ end
218
+
219
+ # Return true if :verbose is set in default options.
220
+ def verbose?
221
+ ctx.verbose?
222
+ end
223
+
224
+ # Return the path to the the specified src, as first found in the
225
+ # :sync_paths option as per #rput, Source Resolution. Return nil
226
+ # if not found. This allows optional, local behavior based on the
227
+ # existance of optional sources.
228
+ def find_source( src, opts = {} )
229
+ ctx.find_source( src, opts )
230
+ end
231
+
232
+ # Execute and empty the queue of any previous commands added with
233
+ # #sh or its variants.
234
+ #
235
+ # A CommandFailure is raised if commands return an exit_code that
236
+ # is not accepted via the :accept option (by default,
237
+ # non-zero). See #sh options :accept and :error.
238
+ #
239
+ # A NestingError is raised if called from within a #sh block.
240
+ #
241
+ # Returns nil.
242
+ def flush
243
+ ctx.flush
244
+ end
245
+
246
+ # Transfer files or entire directories to host, each resolved to a
247
+ # source root directory, while transparently processing any ERB
248
+ # (.erb) templates.
249
+ #
250
+ # === Arguments
251
+ #
252
+ # rput( src..., dest, {options} )
253
+ # rput( src, {options} )
254
+ #
255
+ # A trailing hash is interpreted as options, see below.
256
+ #
257
+ # If there are two or more remaining arguments, the last is
258
+ # interpreted as the remote destination, and should be an absolute
259
+ # path. If there is a single src argument, the destination is
260
+ # implied by finding its base directory and prepending '/'. Thus
261
+ # for example:
262
+ #
263
+ # rput( 'etc/gemrc', user: :root )
264
+ #
265
+ # has an implied destination of: "/etc/". The src and destination
266
+ # directories are interpreted as by `rsync`: glob patterns are
267
+ # expanded and trailing '/' is significant.
268
+ #
269
+ # Each src is searched in :sync_paths. See Source Resolution
270
+ # below.
271
+ #
272
+ # === Execution
273
+ #
274
+ # Before execution, any commands queued via #sh are flushed to
275
+ # avoid ambiguous order of remote changes.
276
+ #
277
+ # If the current context host name is 'localhost' then perform a
278
+ # local-only transfer. This is not via ssh, so ssh options are not
279
+ # applicable. The :user option will still be applied as by local
280
+ # `sudo`.
281
+ #
282
+ # On success, returns an array of format [ [change_code,
283
+ # file_name] ] for files changed, as parsed from the rsync
284
+ # --itemize-changes.
285
+ #
286
+ # Raises SourceNotFound is any src argument is not found (per
287
+ # below). On rsync failure, raises a CommandFailure.
288
+ #
289
+ # === Source Resolution
290
+ #
291
+ # For each src path in arguments, interpret each as a relative path
292
+ # from any of the provided :sync_paths (see in Options below),
293
+ # searched in order. The first matching source found will be
294
+ # used. If no source is found (or if sync_paths is not provided
295
+ # or empty) then raise a SourceNotFound exception. Note that a src
296
+ # trailing '/' is significant both to rsync itself and that only
297
+ # source directories will be matched.
298
+ #
299
+ # If a src path does not have a trailing '/' or '.erb' suffix
300
+ # already, if the non-suffixed file is not found within a given
301
+ # sync_path; then '.erb' is appended and tested as well. Thus if a
302
+ # src "foo.erb" is given, the template must exist. If instead
303
+ # 'foo' is given, then 'foo.erb' will be processed, if and only
304
+ # if, 'foo' does not already exist in a given sync_path. See ERB
305
+ # processing below.
306
+ #
307
+ # === ERB processing
308
+ #
309
+ # By default, any source files with an '.erb' suffix will be
310
+ # interpreted as ERB templates, processed locally, and transferred
311
+ # to the destination "in place" but without the '.erb'
312
+ # suffix. This applies both to individually referenced source files
313
+ # (with or without '.erb' suffix, see above) and '.erb' suffixed
314
+ # files nested at any level within a source directory.
315
+ #
316
+ # ERB templates are passed a custom binding which gives access to
317
+ # this component's instance methods, including dynamic binding to
318
+ # same host, prior component instance methods. Additional
319
+ # variables may be passed via the :erb_vars option.
320
+ #
321
+ # See various options controlling ERB processing below.
322
+ #
323
+ # === Options
324
+ #
325
+ # :user:: Files should be owned on destination by a user other
326
+ # than installer (ex: 'root'). See also :ssh_user
327
+ #
328
+ # :ssh_flags:: Array of flags to ssh via rsync -e, in addition to
329
+ # or overridden by :ssh_options (-o), :ssh_user (-l)
330
+ # and :ssh_user_pem (-i).
331
+ #
332
+ # :ssh_options:: Hash of ssh option key, value strings.
333
+ #
334
+ # :ssh_user:: The ssh -l (login_name) flag.
335
+ #
336
+ # :ssh_user_pem:: The ssh -i (identity_file) flag.
337
+ #
338
+ # :dryrun:: Don't actually make any changes, but report files
339
+ # that would be changed. (default: false)
340
+ #
341
+ # :recursive:: Recurse into sub-directories (default: true)
342
+ #
343
+ # :links:: Recreate symlinks on the destination (default: true)
344
+ #
345
+ # :checksum:: Use MD5 to determine changes; not just size,time
346
+ # (default: true) This is more costly but gives a
347
+ # more accurate representation of real file changes.
348
+ #
349
+ # :backup:: Make backup files on remote (default: true)
350
+ #
351
+ # :excludes:: One or more rsync compatible `--exclude` values, or
352
+ # :dev which excludes common development tree
353
+ # droppings like '*~'. Note that if you exclude
354
+ # "*.erb" then you probably also want to pass
355
+ # `erb_process: false`
356
+ #
357
+ # :perms:: Permission handling. The default (:E) is as per the
358
+ # rsync `--executability` flag: Only local exec (or
359
+ # non-exec) state will be transferred to remote files
360
+ # (including those pre-existing). This is most
361
+ # compatible with the limited permission tracking of
362
+ # a (D)VCS like git. Follow with your own remote chmod
363
+ # commands for finer control.
364
+ #
365
+ # If set to :p, use `rsync --perms` instead (which
366
+ # transfers all permission bits.)
367
+ #
368
+ # If set to a String "VALUE", instead use
369
+ # `rsync --perms --chmod=VALUE`
370
+ #
371
+ # :sync_paths:: Array of one or more local directories in which to
372
+ # find source files.
373
+ # Effectively required.
374
+ #
375
+ # :verbose:: Output stdout/stderr from rsync (default: false)
376
+ #
377
+ # :erb_process:: If false, treat '.erb' suffixed files as normal
378
+ # files (default: true)
379
+ #
380
+ # :erb_mode:: The trim_mode options as documented in ERB::new
381
+ # (default: '<>' trim NEWLINE on /^<%...%>$/ lines)
382
+ #
383
+ # :erb_vars:: Hash of additional variable names/values to pass to
384
+ # ERBs. These names will override the default
385
+ # component binding.
386
+ #
387
+ # Note finally that the :coalesce option is explicitly ignored,
388
+ # since separating rsync STDOUT/STDERR is required for parsing
389
+ # changes correctly.
390
+ def rput( *args )
391
+ opts = args.last.is_a?( Hash ) && args.pop || {}
392
+ opts = opts.dup
393
+ opts[ :erb_binding ] = custom_binding( opts[ :erb_vars ] || {} )
394
+ ctx.rput( *args, opts )
395
+ end
396
+
397
+ # Attempt to dynamically bind and delegate missing methods to
398
+ # Components that were added before self to the same Host.
399
+ def method_missing( meth, *args, &block )
400
+ pc = prior_component
401
+ if pc && pc.respond_to?( meth )
402
+ pc.send( meth, *args, &block )
403
+ else
404
+ super
405
+ end
406
+ end
407
+
408
+ # Include the same dynamically bound, earlier component methods
409
+ # via hook to respond_to?
410
+ def respond_to_missing?( meth, include_private = false )
411
+ super || ( ( pc = prior_component ) && pc.respond_to?( meth ) )
412
+ end
413
+
414
+ private
415
+
416
+ def ctx
417
+ Context.current or raise "ctx called out of SyncWrap::Context"
418
+ end
419
+
420
+ # Return the prior (added before) component instance on the same
421
+ # host, or nil if either not in context, or no such component.
422
+ def prior_component
423
+ ( lc = Context.current ) && lc.host.prior_component( self )
424
+ end
425
+
426
+ def custom_binding( extra_vars = {} )
427
+ extra_vars.inject( clean_binding ) do |b,(k,v)|
428
+ # Can't yet rely on ruby 2.1 Binding#local_variable_set, so
429
+ # use this eval trick instead, to be able to set arbitrary value
430
+ # types.
431
+ ks = k.to_sym.to_s #for safety
432
+ b.eval("#{ks}=nil; lambda { |v| #{ks}=v }").call(v)
433
+ b
434
+ end
435
+ end
436
+
437
+ def clean_binding
438
+ Kernel.binding
439
+ end
440
+
441
+ end
442
+
443
+ end
@@ -0,0 +1,76 @@
1
+ #--
2
+ # Copyright (c) 2011-2014 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
+ require 'syncwrap/component'
18
+
19
+ module SyncWrap
20
+
21
+ # Provision a Commmercial (i.e. Oracle) JDK or "Server JRE" (jrs_)
22
+ # via an HTTP accessable binary repository of your making.
23
+ # Commercial usage terms generally preclude sharing a public binary
24
+ # repository for these. Given the size, check-in or pushing from a
25
+ # development workstation is likely also a bad idea, though not
26
+ # difficult to implement.
27
+ #
28
+ # Oracle and Java are registered trademarks of Oracle and/or its
29
+ # affiliates.
30
+ #
31
+ # Host component dependencies: <Distro>
32
+ class CommercialJDK < Component
33
+
34
+ # HTTP URL to repo base directory. Note that the default
35
+ # (http://localhost/repo) is unlikely to work here.
36
+ attr_accessor :java_repo_base_url
37
+
38
+ # The name of the JDK, which is used for download via
39
+ # java_repo_base_url/<name>.tar.gz and the expected top level
40
+ # directory when unpackaged.
41
+ attr_accessor :jdk_name
42
+
43
+ def initialize( opts = {} )
44
+ @java_repo_base_url = 'http://localhost/repo'
45
+ @jdk_name = 'jrs-ora-1.7.0_51-x64'
46
+
47
+ super
48
+ end
49
+
50
+ # Complete URL to the jdk tarball within the java/binary repo
51
+ def jdk_url
52
+ File.join( @java_repo_base_url, @jdk_name + '.tar.gz' )
53
+ end
54
+
55
+ # Local jdk directory, within local_root, to be installed
56
+ def jdk_dir
57
+ "#{local_root}/lib/#{jdk_name}"
58
+ end
59
+
60
+ def install
61
+ bins = %w[ java jmap jstack jstat jps jinfo jhat javac ].
62
+ map { |b| "../lib/java/bin/#{b}" }.
63
+ join( ' ' )
64
+
65
+ sudo <<-SH
66
+ if [ ! -d #{jdk_dir} ]; then
67
+ curl -sSL #{jdk_url} | tar -C #{local_root}/lib -zxf -
68
+ cd #{local_root}/lib && ln -sfn #{jdk_name} java
69
+ cd #{local_root}/bin && ln -sfn #{bins} .
70
+ fi
71
+ SH
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,144 @@
1
+ #--
2
+ # Copyright (c) 2011-2014 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
+ require 'syncwrap/component'
18
+ require 'syncwrap/components/rhel'
19
+ require 'syncwrap/ruby_support'
20
+
21
+ module SyncWrap
22
+
23
+ # Provision 'C' Ruby (ruby-lang.org - Matz Ruby Interpreter, MRI)
24
+ # from source code, compiled on the target host. This is currently
25
+ # the most reliable way for staying up-to-date on stable Ruby
26
+ # releases across the bulk of Linux server distros (which have
27
+ # conservative update policies).
28
+ #
29
+ # A reasonable alternative is to use distro provided packages. Since
30
+ # this varies so much based on distro particulars, but it is
31
+ # otherwise relatively easy to achieve (setup alt repos,
32
+ # dist_install, set alternatives) you are currently left to do this
33
+ # in your own component. Include RubySupport in that component for
34
+ # some common utility methods.
35
+ #
36
+ # Alternatives like RVM, rbenv, etc. are disfavored by this author
37
+ # for server provisioning because of their often arcane shell and
38
+ # environment modifications and obscure interations with non-/login
39
+ # or non-/interactive sessions. These are fine tools if needed for
40
+ # development however. Again you are currently on your own (beyond
41
+ # RubySupport) if you wish to go this route.
42
+ class CRubyVM < Component
43
+ include RubySupport
44
+
45
+ # The ruby version to install, like it appears in source packages
46
+ # from ruby-lang.org.
47
+ # (Default: 2.0.0-p353)
48
+ attr_accessor :ruby_version
49
+
50
+ # If true, attempt to uninstall any pre-existing distro packaged
51
+ # ruby, which might otherwise lead to errors and confusion.
52
+ # (Default: true)
53
+ attr_accessor :do_uninstall_distro_ruby
54
+
55
+ def initialize( opts = {} )
56
+ @ruby_version = "2.0.0-p353"
57
+ @do_uninstall_distro_ruby = true
58
+
59
+ super
60
+ end
61
+
62
+ def install
63
+ install_ruby
64
+ install_gemrc # from RubySupport
65
+ end
66
+
67
+ def ruby_command
68
+ "#{local_root}/bin/ruby"
69
+ end
70
+
71
+ def compact_version
72
+ ruby_version.sub( '-', '' )
73
+ end
74
+
75
+ # If the current ruby_command is not at the desired ruby_version,
76
+ # download source, configure, make and install.
77
+ def install_ruby
78
+ cond = <<-SH
79
+ rvr=`[ -x #{ruby_command} ] &&
80
+ #{ruby_command} -v | grep -o -E '[0-9]+(\\.[0-9]+)+(p[0-9]+)?' \
81
+ || true`
82
+ if [ "$rvr" != "#{compact_version}" ]; then
83
+ SH
84
+ sudo( cond, close: "fi" ) do
85
+ install_build_deps
86
+ make_and_install
87
+
88
+ # only after a successful source install:
89
+ uninstall_distro_ruby if do_uninstall_distro_ruby
90
+ end
91
+ end
92
+
93
+ def uninstall_distro_ruby
94
+ if distro.is_a?( RHEL )
95
+ dist_uninstall( %w[ ruby ruby18 ruby19 ruby20 ] )
96
+ else
97
+ dist_uninstall( %w[ ruby ruby1.8 ruby1.9 ruby1.9.1 ruby1.9.3 ruby2.0 ] )
98
+ end
99
+ end
100
+
101
+ alias :cruby_gem_install :gem_install
102
+
103
+ protected
104
+
105
+ def install_build_deps
106
+ if distro.is_a?( RHEL )
107
+ dist_install( %w[ gcc make autoconf zlib-devel
108
+ openssl-devel readline-devel libyaml-devel ] )
109
+ else
110
+ dist_install( %w[ gcc make autoconf zlib1g-dev
111
+ libssl-dev libreadline-dev libyaml-dev ] )
112
+ end
113
+ end
114
+
115
+ def make_and_install
116
+ # Arguably all but the final install should be run by an
117
+ # unprivileged user. But its more likely merged this way, and if
118
+ # "configure" or "make" can be exploited, so can "make install".
119
+ sudo <<-SH
120
+ [ -e /tmp/src ] && rm -rf /tmp/src || true
121
+ mkdir -p /tmp/src/ruby
122
+ cd /tmp/src/ruby
123
+ curl -sSL #{src_url} | tar -zxf -
124
+ cd ruby-#{ruby_version}
125
+ ./configure --prefix=#{local_root} #{redirect?}
126
+ make #{redirect?}
127
+ make install #{redirect?}
128
+ cd / && rm -rf /tmp/src
129
+ SH
130
+ end
131
+
132
+ def src_url
133
+ [ 'http://cache.ruby-lang.org/pub/ruby',
134
+ ruby_version =~ /^(\d+\.\d+)/ && $1,
135
+ "ruby-#{ruby_version}.tar.gz" ].join( '/' )
136
+ end
137
+
138
+ def redirect?
139
+ verbose? ? "" : ">/dev/null"
140
+ end
141
+
142
+ end
143
+
144
+ end