syncwrap 1.5.2 → 2.0.0

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