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.
- checksums.yaml +7 -0
- data/History.rdoc +19 -0
- data/Manifest.txt +82 -34
- data/README.rdoc +96 -48
- data/Rakefile +0 -65
- data/bin/syncwrap +27 -0
- data/examples/LAYOUT.rdoc +70 -0
- data/examples/Rakefile +16 -0
- data/examples/ec2.rb +44 -0
- data/examples/hello.rb +14 -0
- data/examples/hello_binding.rb +27 -0
- data/examples/jruby.rb +11 -0
- data/examples/private/aws.json +4 -0
- data/examples/rput.rb +24 -0
- data/examples/sync/home/bob/.ssh/authorized_keys +1 -0
- data/examples/sync/tmp/sample.erb +3 -0
- data/lib/syncwrap/amazon_ec2.rb +236 -0
- data/lib/syncwrap/amazon_ws.rb +308 -0
- data/lib/syncwrap/base.rb +4 -2
- data/lib/syncwrap/cli.rb +328 -0
- data/lib/syncwrap/component.rb +443 -0
- data/lib/syncwrap/components/commercial_jdk.rb +76 -0
- data/lib/syncwrap/components/cruby_vm.rb +144 -0
- data/lib/syncwrap/components/etc_hosts.rb +44 -0
- data/lib/syncwrap/{geminabox.rb → components/geminabox.rb} +12 -17
- data/lib/syncwrap/components/hashdot.rb +97 -0
- data/lib/syncwrap/components/iyyov.rb +144 -0
- data/lib/syncwrap/components/iyyov_daemon.rb +125 -0
- data/lib/syncwrap/components/jruby_vm.rb +122 -0
- data/lib/syncwrap/components/mdraid.rb +204 -0
- data/lib/syncwrap/components/network.rb +99 -0
- data/lib/syncwrap/components/open_jdk.rb +70 -0
- data/lib/syncwrap/components/postgresql.rb +159 -0
- data/lib/syncwrap/components/qpid.rb +303 -0
- data/lib/syncwrap/components/rhel.rb +71 -0
- data/lib/syncwrap/components/run_user.rb +99 -0
- data/lib/syncwrap/components/ubuntu.rb +85 -0
- data/lib/syncwrap/components/users.rb +200 -0
- data/lib/syncwrap/context.rb +260 -0
- data/lib/syncwrap/distro.rb +53 -60
- data/lib/syncwrap/formatter.rb +149 -0
- data/lib/syncwrap/host.rb +134 -0
- data/lib/syncwrap/main.rb +62 -0
- data/lib/syncwrap/path_util.rb +55 -0
- data/lib/syncwrap/rsync.rb +227 -0
- data/lib/syncwrap/ruby_support.rb +110 -0
- data/lib/syncwrap/shell.rb +207 -0
- data/lib/syncwrap.rb +367 -1
- data/{etc → sync/etc}/gemrc +1 -3
- data/sync/etc/hosts.erb +8 -0
- data/{etc/init.d/iyyov → sync/etc/init.d/iyyov.erb} +35 -7
- data/sync/etc/sysconfig/pgsql/postgresql.erb +2 -0
- data/sync/src/hashdot/Makefile.erb +98 -0
- data/sync/src/hashdot/profiles/default.hdp.erb +25 -0
- data/sync/src/hashdot/profiles/jruby-common.hdp +28 -0
- data/sync/src/hashdot/profiles/jruby-shortlived.hdp +9 -0
- data/sync/src/hashdot/profiles/jruby.hdp.erb +13 -0
- data/sync/src/hashdot/profiles/shortlived.hdp +6 -0
- data/sync/var/iyyov/default/config.rb +1 -0
- data/sync/var/iyyov/default/daemon.rb.erb +15 -0
- data/sync/var/iyyov/jobs.rb.erb +4 -0
- data/test/muddled_sync.rb +13 -0
- data/test/setup.rb +39 -0
- data/test/sync/d1/bar +1 -0
- data/test/sync/d1/foo.erb +1 -0
- data/test/sync/d3/d2/bar +1 -0
- data/test/sync/d3/d2/foo.erb +1 -0
- data/test/test_components.rb +108 -0
- data/test/test_context.rb +107 -0
- data/test/test_context_rput.rb +289 -0
- data/test/test_rsync.rb +138 -0
- data/test/test_shell.rb +233 -0
- data/test/test_space.rb +218 -0
- data/test/test_space_main.rb +40 -0
- data/test/zfile +1 -0
- metadata +204 -71
- data/etc/sysconfig/pgsql/postgresql +0 -2
- data/lib/syncwrap/aws.rb +0 -448
- data/lib/syncwrap/common.rb +0 -161
- data/lib/syncwrap/ec2.rb +0 -59
- data/lib/syncwrap/hashdot.rb +0 -70
- data/lib/syncwrap/iyyov.rb +0 -139
- data/lib/syncwrap/java.rb +0 -61
- data/lib/syncwrap/jruby.rb +0 -118
- data/lib/syncwrap/postgresql.rb +0 -135
- data/lib/syncwrap/qpid.rb +0 -251
- data/lib/syncwrap/remote_task.rb +0 -199
- data/lib/syncwrap/rhel.rb +0 -67
- data/lib/syncwrap/ubuntu.rb +0 -78
- data/lib/syncwrap/user_run.rb +0 -102
- data/test/test_syncwrap.rb +0 -202
- data/var/iyyov/jobs.rb +0 -11
- /data/{etc → sync/etc}/corosync/corosync.conf +0 -0
- /data/{etc → sync/etc}/corosync/uidgid.d/qpid +0 -0
- /data/{etc → sync/etc}/init.d/qpidd +0 -0
- /data/{etc → sync/etc}/sysctl.d/61-postgresql-shm.conf +0 -0
- /data/{usr/local → sync/jruby}/bin/jgem +0 -0
- /data/{postgresql → sync/postgresql}/rhel/pg_hba.conf +0 -0
- /data/{postgresql → sync/postgresql}/rhel/pg_ident.conf +0 -0
- /data/{postgresql → sync/postgresql}/rhel/postgresql.conf +0 -0
- /data/{postgresql → sync/postgresql}/ubuntu/environment +0 -0
- /data/{postgresql → sync/postgresql}/ubuntu/pg_ctl.conf +0 -0
- /data/{postgresql → sync/postgresql}/ubuntu/pg_hba.conf +0 -0
- /data/{postgresql → sync/postgresql}/ubuntu/pg_ident.conf +0 -0
- /data/{postgresql → sync/postgresql}/ubuntu/postgresql.conf +0 -0
- /data/{postgresql → sync/postgresql}/ubuntu/start.conf +0 -0
- /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
|