sprinkle 0.4.2 → 0.5.0.rc1
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.
- data/.gitignore +8 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +54 -0
- data/README.markdown +178 -166
- data/Rakefile +4 -28
- data/bin/sprinkle +14 -1
- data/lib/sprinkle.rb +5 -1
- data/lib/sprinkle/actors/actors.rb +20 -5
- data/lib/sprinkle/actors/capistrano.rb +62 -36
- data/lib/sprinkle/actors/dummy.rb +127 -0
- data/lib/sprinkle/actors/local.rb +59 -17
- data/lib/sprinkle/actors/ssh.rb +189 -107
- data/lib/sprinkle/actors/vlad.rb +51 -32
- data/lib/sprinkle/configurable.rb +2 -1
- data/lib/sprinkle/deployment.rb +22 -2
- data/lib/sprinkle/errors/pretty_failure.rb +41 -0
- data/lib/sprinkle/errors/remote_command_failure.rb +24 -0
- data/lib/sprinkle/errors/transfer_failure.rb +28 -0
- data/lib/sprinkle/installers/apt.rb +17 -16
- data/lib/sprinkle/installers/binary.rb +23 -8
- data/lib/sprinkle/installers/brew.rb +17 -10
- data/lib/sprinkle/installers/bsd_port.rb +10 -6
- data/lib/sprinkle/installers/deb.rb +3 -10
- data/lib/sprinkle/installers/freebsd_pkg.rb +5 -11
- data/lib/sprinkle/installers/freebsd_portinstall.rb +8 -2
- data/lib/sprinkle/installers/gem.rb +9 -3
- data/lib/sprinkle/installers/group.rb +28 -4
- data/lib/sprinkle/installers/installer.rb +58 -7
- data/lib/sprinkle/installers/mac_port.rb +13 -6
- data/lib/sprinkle/installers/npm.rb +42 -0
- data/lib/sprinkle/installers/openbsd_pkg.rb +4 -11
- data/lib/sprinkle/installers/opensolaris_pkg.rb +7 -13
- data/lib/sprinkle/installers/package_installer.rb +33 -0
- data/lib/sprinkle/installers/pacman.rb +5 -13
- data/lib/sprinkle/installers/pear.rb +40 -0
- data/lib/sprinkle/installers/push_text.rb +18 -5
- data/lib/sprinkle/installers/rake.rb +7 -2
- data/lib/sprinkle/installers/reconnect.rb +29 -0
- data/lib/sprinkle/installers/replace_text.rb +11 -2
- data/lib/sprinkle/installers/rpm.rb +8 -6
- data/lib/sprinkle/installers/runner.rb +41 -16
- data/lib/sprinkle/installers/smart.rb +6 -17
- data/lib/sprinkle/installers/source.rb +22 -10
- data/lib/sprinkle/installers/thor.rb +7 -0
- data/lib/sprinkle/installers/transfer.rb +62 -41
- data/lib/sprinkle/installers/user.rb +34 -4
- data/lib/sprinkle/installers/yum.rb +10 -10
- data/lib/sprinkle/installers/zypper.rb +4 -15
- data/lib/sprinkle/package.rb +81 -98
- data/lib/sprinkle/policy.rb +11 -4
- data/lib/sprinkle/utility/log_recorder.rb +33 -0
- data/lib/sprinkle/verifiers/directory.rb +1 -1
- data/lib/sprinkle/verifiers/executable.rb +1 -1
- data/lib/sprinkle/verifiers/file.rb +11 -2
- data/lib/sprinkle/verifiers/package.rb +2 -14
- data/lib/sprinkle/verifiers/permission.rb +40 -0
- data/lib/sprinkle/verifiers/symlink.rb +2 -2
- data/lib/sprinkle/verifiers/test.rb +21 -0
- data/lib/sprinkle/verify.rb +3 -3
- data/lib/sprinkle/version.rb +3 -0
- data/spec/fixtures/my_file.txt +1 -0
- data/spec/sprinkle/actors/capistrano_spec.rb +16 -3
- data/spec/sprinkle/actors/local_spec.rb +24 -6
- data/spec/sprinkle/actors/ssh_spec.rb +38 -0
- data/spec/sprinkle/installers/apt_spec.rb +23 -2
- data/spec/sprinkle/installers/binary_spec.rb +22 -14
- data/spec/sprinkle/installers/brew_spec.rb +4 -4
- data/spec/sprinkle/installers/installer_spec.rb +36 -7
- data/spec/sprinkle/installers/npm_spec.rb +16 -0
- data/spec/sprinkle/installers/pear_spec.rb +16 -0
- data/spec/sprinkle/installers/push_text_spec.rb +23 -1
- data/spec/sprinkle/installers/rpm_spec.rb +5 -0
- data/spec/sprinkle/installers/runner_spec.rb +27 -11
- data/spec/sprinkle/installers/smart_spec.rb +60 -0
- data/spec/sprinkle/installers/source_spec.rb +4 -4
- data/spec/sprinkle/installers/transfer_spec.rb +31 -16
- data/spec/sprinkle/package_spec.rb +10 -2
- data/spec/sprinkle/policy_spec.rb +6 -0
- data/spec/sprinkle/verify_spec.rb +18 -4
- data/sprinkle.gemspec +22 -158
- metadata +178 -96
- data/TODO +0 -56
- data/VERSION +0 -1
- data/lib/sprinkle/verifiers/apt.rb +0 -21
- data/lib/sprinkle/verifiers/brew.rb +0 -21
- data/lib/sprinkle/verifiers/rpm.rb +0 -21
- data/lib/sprinkle/verifiers/users_groups.rb +0 -33
data/bin/sprinkle
CHANGED
@@ -20,7 +20,10 @@ ARGV.each do |arg|
|
|
20
20
|
ENV[$1] = $2 if arg =~ /^(\w+)=(.*)$/
|
21
21
|
end
|
22
22
|
|
23
|
+
require File.dirname(__FILE__) + '/../lib/sprinkle/version'
|
24
|
+
|
23
25
|
parser = OptionParser.new do |opts|
|
26
|
+
opts.version = Sprinkle::Version
|
24
27
|
opts.banner = <<BANNER
|
25
28
|
Sprinkle
|
26
29
|
========
|
@@ -44,6 +47,8 @@ BANNER
|
|
44
47
|
opts.separator ""
|
45
48
|
opts.on("-s", "--script=PATH", String,
|
46
49
|
"Path to a sprinkle script to run") { |v| OPTIONS[:path] = v }
|
50
|
+
opts.on("--only [ROLE]", String,
|
51
|
+
"Only run sprinkle policies for the specified role") { |v| OPTIONS[:only_role] = v }
|
47
52
|
opts.on("-t", "--test",
|
48
53
|
"Process but don't perform any actions") { |v| OPTIONS[:testing] = v }
|
49
54
|
opts.on("-v", "--verbose",
|
@@ -61,6 +66,12 @@ BANNER
|
|
61
66
|
end
|
62
67
|
end
|
63
68
|
|
69
|
+
def only_role(options)
|
70
|
+
role=OPTIONS[:only_role]
|
71
|
+
Sprinkle::OPTIONS[:only_role] = role
|
72
|
+
puts "Only running policies for :#{role}"
|
73
|
+
end
|
74
|
+
|
64
75
|
def force_mode(options)
|
65
76
|
Sprinkle::OPTIONS[:force] = OPTIONS[:force] || false
|
66
77
|
end
|
@@ -78,7 +89,8 @@ def verbosity(options)
|
|
78
89
|
end
|
79
90
|
|
80
91
|
def log_level(options)
|
81
|
-
|
92
|
+
severity = ActiveSupport::BufferedLogger::Severity
|
93
|
+
Object.logger.level = options[:verbose] ? severity::DEBUG : severity::INFO
|
82
94
|
end
|
83
95
|
|
84
96
|
require File.dirname(__FILE__) + '/../lib/sprinkle'
|
@@ -91,5 +103,6 @@ operation_mode(OPTIONS)
|
|
91
103
|
powder_cloud(OPTIONS)
|
92
104
|
log_level(OPTIONS)
|
93
105
|
verbosity(OPTIONS)
|
106
|
+
only_role(OPTIONS)
|
94
107
|
|
95
108
|
Sprinkle::Script.sprinkle File.read(powder), powder
|
data/lib/sprinkle.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'active_support'
|
2
|
+
require 'active_support/all'
|
3
3
|
|
4
4
|
# Use active supports auto load mechanism
|
5
5
|
require 'active_support/version'
|
@@ -14,10 +14,14 @@ end
|
|
14
14
|
#ActiveSupport::Dependencies::RAILS_DEFAULT_LOGGER = Logger.new($stdout)
|
15
15
|
#ActiveSupport::Dependencies.log_activity = true
|
16
16
|
|
17
|
+
require File.dirname(__FILE__) + "/sprinkle/version.rb"
|
18
|
+
|
17
19
|
# Load up extensions to existing classes
|
18
20
|
Dir[File.dirname(__FILE__) + '/sprinkle/extensions/*.rb'].each { |e| require e }
|
19
21
|
# Load up the verifiers so they can register themselves
|
20
22
|
Dir[File.dirname(__FILE__) + '/sprinkle/verifiers/*.rb'].each { |e| require e }
|
23
|
+
# Load up the installers so they can register themselves
|
24
|
+
Dir[File.dirname(__FILE__) + '/sprinkle/installers/*.rb'].each { |e| require e }
|
21
25
|
|
22
26
|
# Configuration options
|
23
27
|
module Sprinkle
|
@@ -6,12 +6,27 @@
|
|
6
6
|
#++
|
7
7
|
|
8
8
|
module Sprinkle
|
9
|
-
# An actor is a method of command delivery to a remote machine.
|
10
|
-
# layer between
|
11
|
-
#
|
9
|
+
# An actor is a method of command delivery to a remote machine. Actors are the
|
10
|
+
# layer setting between Sprinkle and the systems you and wanting to apply
|
11
|
+
# policies to.
|
12
12
|
#
|
13
|
-
#
|
14
|
-
#
|
13
|
+
# Sprinkle ships with actors for Capistrano, Vlad, localhost and pure SSH.
|
14
|
+
# 99% of the time these should be sufficient but you can always write your
|
15
|
+
# own actor otherwise.
|
16
|
+
#
|
17
|
+
# == Writing an actor
|
18
|
+
#
|
19
|
+
# Actors must provide only 3 methods:
|
20
|
+
#
|
21
|
+
# * install (installer, roles, options)
|
22
|
+
# * verify (verifier, roles, options)
|
23
|
+
# * transfer (source, destination, roles, options)
|
24
|
+
#
|
25
|
+
# Hopefully these methods are kind of fairly obvious. They should return true
|
26
|
+
# to indicate success and false to indicate failure.
|
27
|
+
# The actual commands you need to execute can be retrived from
|
28
|
+
# +installer.install_sequence+ and +verifier.commands+.
|
29
|
+
|
15
30
|
module Actors
|
16
31
|
end
|
17
32
|
end
|
@@ -2,16 +2,15 @@ require 'capistrano/cli'
|
|
2
2
|
|
3
3
|
module Sprinkle
|
4
4
|
module Actors
|
5
|
-
#
|
5
|
+
# The Capistrano actor uses Capistrano to define your roles and deliver
|
6
|
+
# commands to your remote servers. You'll need the capistrano gem installed.
|
6
7
|
#
|
7
|
-
#
|
8
|
-
# box with Sprinkle. If you have the capistrano gem install, you may use
|
9
|
-
# this delivery. The only configuration option available, and which is
|
10
|
-
# mandatory to include is +recipes+. An example:
|
8
|
+
# The only configuration option is to specify a recipe.
|
11
9
|
#
|
12
10
|
# deployment do
|
13
11
|
# delivery :capistrano do
|
14
|
-
#
|
12
|
+
# recipe 'deploy'
|
13
|
+
# recipe 'more'
|
15
14
|
# end
|
16
15
|
# end
|
17
16
|
#
|
@@ -47,52 +46,79 @@ module Sprinkle
|
|
47
46
|
#
|
48
47
|
# deployment do
|
49
48
|
# delivery :capistrano do
|
50
|
-
#
|
51
|
-
# recipes 'magic_beans'
|
49
|
+
# recipe 'deploy'
|
50
|
+
# recipes 'magic_beans', 'normal_beans'
|
52
51
|
# end
|
53
52
|
# end
|
54
|
-
def
|
53
|
+
def recipe(scripts)
|
55
54
|
@loaded_recipes ||= []
|
56
|
-
|
57
|
-
|
55
|
+
Array(scripts).each do |script|
|
56
|
+
@config.load script
|
57
|
+
@loaded_recipes << script
|
58
|
+
end
|
58
59
|
end
|
59
|
-
|
60
|
-
def
|
60
|
+
|
61
|
+
def recipes(scripts) #:nodoc:
|
62
|
+
recipe(scripts)
|
63
|
+
end
|
64
|
+
|
65
|
+
def install(installer, roles, opts = {}) #:nodoc:
|
66
|
+
@installer = installer
|
67
|
+
process(installer.package.name, installer.install_sequence, roles, opts)
|
68
|
+
rescue ::Capistrano::CommandError => e
|
69
|
+
raise_error(e)
|
70
|
+
ensure
|
71
|
+
@installer = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def verify(verifier, roles, opts = {}) #:nodoc:
|
75
|
+
process(verifier.package.name, verifier.commands, roles,
|
76
|
+
:suppress_and_return_failures => true)
|
77
|
+
end
|
78
|
+
|
79
|
+
def process(name, commands, roles, opts = {}) #:nodoc:
|
80
|
+
inst=@installer
|
81
|
+
@log_recorder = log_recorder = Sprinkle::Utility::LogRecorder.new
|
61
82
|
define_task(name, roles) do
|
62
83
|
via = fetch(:run_method, :sudo)
|
63
84
|
commands.each do |command|
|
64
|
-
|
85
|
+
if command == :TRANSFER
|
86
|
+
opts.reverse_merge!(:recursive => true)
|
87
|
+
upload inst.sourcepath, inst.destination, :via => :scp,
|
88
|
+
:recursive => opts[:recursive]
|
89
|
+
elsif command == :RECONNECT
|
90
|
+
teardown_connections_to(sessions.keys)
|
91
|
+
else
|
92
|
+
# this reset the log
|
93
|
+
log_recorder.reset command
|
94
|
+
invoke_command(command, {:via => via}) do |c,s,d|
|
95
|
+
# record the stream and data
|
96
|
+
log_recorder.log(s, d)
|
97
|
+
end
|
98
|
+
end
|
65
99
|
end
|
66
100
|
end
|
67
|
-
|
68
|
-
begin
|
69
|
-
run(name)
|
70
|
-
return true
|
71
|
-
rescue ::Capistrano::CommandError => e
|
72
|
-
return false if suppress_and_return_failures
|
73
|
-
|
74
|
-
# Reraise error if we're not suppressing it
|
75
|
-
raise
|
76
|
-
end
|
101
|
+
run_task(name, opts)
|
77
102
|
end
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
def raise_error(e)
|
107
|
+
details={:command => @log_recorder.command, :code => "??",
|
108
|
+
:message => e.message,
|
109
|
+
:hosts => e.hosts,
|
110
|
+
:error => @log_recorder.err, :stdout => @log_recorder.out}
|
111
|
+
raise Sprinkle::Errors::RemoteCommandFailure.new(@installer, details, e)
|
82
112
|
end
|
83
|
-
|
84
|
-
|
85
|
-
run(
|
113
|
+
|
114
|
+
def run_task(task, opts={})
|
115
|
+
run(task)
|
86
116
|
return true
|
87
117
|
rescue ::Capistrano::CommandError => e
|
88
|
-
return false if suppress_and_return_failures
|
89
|
-
|
118
|
+
return false if opts[:suppress_and_return_failures]
|
90
119
|
# Reraise error if we're not suppressing it
|
91
120
|
raise
|
92
121
|
end
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
122
|
|
97
123
|
# REVISIT: can we set the description somehow?
|
98
124
|
def define_task(name, roles, &block)
|
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'capistrano/cli'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
module Sprinkle
|
5
|
+
module Actors
|
6
|
+
# = Capistrano Delivery Method
|
7
|
+
#
|
8
|
+
# Capistrano is one of the delivery method options available out of the
|
9
|
+
# box with Sprinkle. If you have the capistrano gem install, you may use
|
10
|
+
# this delivery. The only configuration option available, and which is
|
11
|
+
# mandatory to include is +recipes+. An example:
|
12
|
+
#
|
13
|
+
# deployment do
|
14
|
+
# delivery :capistrano do
|
15
|
+
# recipes 'deploy'
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# Recipes is given a list of files which capistrano will include and load.
|
20
|
+
# These recipes are mainly to set variables such as :user, :password, and to
|
21
|
+
# set the app domain which will be sprinkled.
|
22
|
+
class Dummy #:nodoc:
|
23
|
+
attr_accessor :config, :loaded_recipes #:nodoc:
|
24
|
+
|
25
|
+
def initialize(&block) #:nodoc:
|
26
|
+
# @config.set(:_sprinkle_actor, self)
|
27
|
+
@roles={}
|
28
|
+
self.instance_eval &block
|
29
|
+
end
|
30
|
+
|
31
|
+
# Defines a recipe file which will be included by capistrano. Use these
|
32
|
+
# recipe files to set capistrano specific configurations. Default recipe
|
33
|
+
# included is "deploy." But if any other recipe is specified, it will
|
34
|
+
# include that instead. Multiple recipes may be specified through multiple
|
35
|
+
# recipes calls, an example:
|
36
|
+
#
|
37
|
+
# deployment do
|
38
|
+
# delivery :capistrano do
|
39
|
+
# recipes 'deploy'
|
40
|
+
# recipes 'magic_beans'
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# def recipes(script)
|
44
|
+
# end
|
45
|
+
|
46
|
+
def role(role, server, opts={})
|
47
|
+
@roles[role]||=[]
|
48
|
+
@roles[role] << [ server, opts ]
|
49
|
+
end
|
50
|
+
|
51
|
+
def install(installer, roles, opts={})
|
52
|
+
if per_host=opts.delete(:per_host)
|
53
|
+
servers_per_role(roles).each do |server|
|
54
|
+
installer.reconfigure_for(server)
|
55
|
+
installer.announce
|
56
|
+
process(installer.package.name, installer.install_sequence, server, opts)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
process(installer.package, installer.install_sequence, roles, opts)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def verify(verifier, roles, opts = {})
|
64
|
+
process(verifier.package.name, verifier.commands, roles, opts = {})
|
65
|
+
end
|
66
|
+
|
67
|
+
def servers_per_role(role)
|
68
|
+
@roles[role]
|
69
|
+
end
|
70
|
+
|
71
|
+
def process(name, commands, roles, opts = {}) #:nodoc:
|
72
|
+
# puts "PROCESS: #{name} on #{roles}"
|
73
|
+
pp commands
|
74
|
+
# return false if suppress_and_return_failures
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def transfer(name, source, destination, roles, recursive = true, suppress_and_return_failures = false)
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# REVISIT: can we set the description somehow?
|
85
|
+
def define_task(name, roles, &block)
|
86
|
+
@config.task task_sym(name), :roles => roles, &block
|
87
|
+
end
|
88
|
+
|
89
|
+
def run(task)
|
90
|
+
@config.send task_sym(task)
|
91
|
+
end
|
92
|
+
|
93
|
+
def task_sym(name)
|
94
|
+
"install_#{name.to_task_name}".to_sym
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
=begin
|
102
|
+
|
103
|
+
# channel: the SSH channel object used for this response
|
104
|
+
# stream: either :err or :out, for stderr or stdout responses
|
105
|
+
# output: the text that the server is sending, might be in chunks
|
106
|
+
run "apt-get update" do |channel, stream, output|
|
107
|
+
if output =~ /Are you sure?/
|
108
|
+
answer = Capistrano::CLI.ui.ask("Are you sure: ")
|
109
|
+
channel.send_data(answer + "\n")
|
110
|
+
else
|
111
|
+
# allow the default callback to be processed
|
112
|
+
Capistrano::Configuration.default_io_proc.call[channel, stream, output]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
You can tell subversion to use a different username+password by
|
119
|
+
setting a couple variables:
|
120
|
+
set :svn_username, "my svn username"
|
121
|
+
set :svn_password, "my svn password"
|
122
|
+
If you don't want to set the password explicitly in your recipe like
|
123
|
+
that, you can make capistrano prompt you for it like this:
|
124
|
+
set(:svn_password) { Capistrano::CLI.password_prompt("Subversion
|
125
|
+
password: ") }
|
126
|
+
- Jamis
|
127
|
+
=end
|
@@ -1,37 +1,79 @@
|
|
1
|
+
require 'open4'
|
2
|
+
|
1
3
|
module Sprinkle
|
2
4
|
module Actors
|
3
|
-
#
|
5
|
+
# The local actor executes all commands on your local system, as opposed to other
|
6
|
+
# implementations that generally run commands on a remote system over the
|
7
|
+
# network.
|
4
8
|
#
|
5
|
-
# This
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# This is useful if you'd like to use Sprinkle to provision your local machine.
|
10
|
-
# To enable this actor, in your Sprinkle script specify the :local delivery mechanism.
|
9
|
+
# This could be useful if you'd like to use Sprinkle to provision your
|
10
|
+
# local machine. To enable this actor, in your Sprinkle script specify
|
11
|
+
# the :local delivery mechanism.
|
11
12
|
#
|
12
13
|
# deployment do
|
13
14
|
# delivery :local
|
14
15
|
# end
|
15
16
|
#
|
16
|
-
# Note
|
17
|
-
#
|
17
|
+
# Note: The local actor completely ignores roles and behaves as if your
|
18
|
+
# local system was a member of all roles defined.
|
18
19
|
class Local
|
19
20
|
|
20
|
-
|
21
|
+
class LocalCommandError < StandardError; end
|
22
|
+
|
23
|
+
def install(installer, roles, opts = {}) #:nodoc:
|
24
|
+
# all local installer cares about is the commands
|
25
|
+
@installer = installer
|
26
|
+
process(installer.package.name, installer.install_sequence, roles)
|
27
|
+
rescue LocalCommandError => e
|
28
|
+
raise_error(e)
|
29
|
+
ensure
|
30
|
+
@installer = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def verify(verifier, roles, opts = {}) #:nodoc:
|
34
|
+
process(verifier.package.name, verifier.commands, roles, :suppress_and_return_failures => true)
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def process(name, commands, roles, opts = {}) #:nodoc:
|
40
|
+
@log_recorder = Sprinkle::Utility::LogRecorder.new
|
21
41
|
commands.each do |command|
|
22
|
-
|
23
|
-
|
42
|
+
if command == :RECONNECT
|
43
|
+
return true
|
44
|
+
elsif command == :TRANSFER
|
45
|
+
res = transfer(@installer.sourcepath, @installer.destination, roles,
|
46
|
+
:recursive => @installer.options[:recursive])
|
47
|
+
raise LocalCommandError if res != 0
|
48
|
+
else
|
49
|
+
res = run_command command
|
50
|
+
raise LocalCommandError if res != 0 and not opts[:suppress_and_return_failures]
|
51
|
+
end
|
24
52
|
end
|
25
53
|
return true
|
26
54
|
end
|
27
55
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
56
|
+
def run_command(cmd)
|
57
|
+
@log_recorder.reset cmd
|
58
|
+
pid, stdin, out, err = Open4.popen4(cmd)
|
59
|
+
ignored, status = Process::waitpid2 pid
|
60
|
+
@log_recorder.log :err, err.read
|
61
|
+
@log_recorder.log :out, out.read
|
62
|
+
@log_recorder.code = status.to_i
|
63
|
+
end
|
64
|
+
|
65
|
+
def raise_error(e)
|
66
|
+
raise Sprinkle::Errors::RemoteCommandFailure.new(@installer, @log_recorder.hash, e)
|
67
|
+
end
|
68
|
+
|
69
|
+
def transfer(source, destination, roles, opts ={}) #:nodoc:
|
70
|
+
opts.reverse_merge!(:recursive => true)
|
71
|
+
flags = "-R " if opts[:recursive]
|
32
72
|
|
33
|
-
|
73
|
+
run_command "cp #{flags}#{source} #{destination}"
|
34
74
|
end
|
75
|
+
|
76
|
+
|
35
77
|
end
|
36
78
|
end
|
37
79
|
end
|