avodeploy 0.4 → 0.4.1
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 +4 -4
- data/CHANGELOG +14 -0
- data/README.md +8 -5
- data/avodeploy.gemspec +3 -4
- data/bin/avo +14 -12
- data/lib/avodeploy.rb +29 -0
- data/lib/{avocado → avodeploy}/bootstrap.rb +24 -30
- data/lib/{avocado → avodeploy}/command_execution_result.rb +1 -1
- data/lib/{avocado → avodeploy}/config.rb +8 -4
- data/lib/{avocado → avodeploy}/core_ext/hash_insert_at.rb +0 -0
- data/lib/{avocado → avodeploy}/core_ext/string_colors.rb +0 -0
- data/lib/{avocado → avodeploy}/deployment.rb +3 -3
- data/lib/{avocado → avodeploy}/multi_io.rb +1 -1
- data/lib/avodeploy/scm_provider/git_scm_provider.rb +73 -0
- data/lib/avodeploy/scm_provider/scm_provider.rb +70 -0
- data/lib/{avocado → avodeploy}/skel/manifest_template.rb.erb +1 -1
- data/lib/{avocado → avodeploy}/strategy/base.rb +1 -1
- data/lib/avodeploy/strategy/local_copy.rb +101 -0
- data/lib/{avocado → avodeploy}/target.rb +3 -1
- data/lib/avodeploy/task/local_task_execution_environment.rb +127 -0
- data/lib/avodeploy/task/remote_task_execution_environment.rb +114 -0
- data/lib/avodeploy/task/task.rb +76 -0
- data/lib/{avocado → avodeploy}/task/task_dependency.rb +8 -6
- data/lib/avodeploy/task/task_execution_environment.rb +88 -0
- data/lib/avodeploy/task/task_manager.rb +185 -0
- data/lib/{avocado → avodeploy}/version.rb +2 -2
- metadata +27 -40
- data/lib/avocado/Gemfile +0 -9
- data/lib/avocado/scm_provider/git_scm_provider.rb +0 -71
- data/lib/avocado/scm_provider/scm_provider.rb +0 -68
- data/lib/avocado/strategy/local_copy.rb +0 -99
- data/lib/avocado/task/local_task_execution_environment.rb +0 -127
- data/lib/avocado/task/remote_task_execution_environment.rb +0 -112
- data/lib/avocado/task/task.rb +0 -84
- data/lib/avocado/task/task_execution_environment.rb +0 -86
- data/lib/avocado/task/task_manager.rb +0 -183
data/lib/avocado/Gemfile
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
AVOCADO
|
3
|
-
The flexible and easy to use deployment framework for web applications
|
4
|
-
|
5
|
-
This program is free software; you can redistribute it and/or
|
6
|
-
modify it under the terms of the GNU General Public License Version 2
|
7
|
-
as published by the Free Software Foundation.
|
8
|
-
|
9
|
-
This program is distributed in the hope that it will be useful,
|
10
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
GNU General Public License for more details.
|
13
|
-
|
14
|
-
You should have received a copy of the GNU General Public License
|
15
|
-
along with this program; if not, write to the Free Software
|
16
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
-
=end
|
18
|
-
|
19
|
-
module Avocado
|
20
|
-
class GitScmProvider
|
21
|
-
|
22
|
-
# Initializes the provider
|
23
|
-
#
|
24
|
-
# @param env [TaskExecutionEnvironment] Environment for the commands to be executed in
|
25
|
-
def initialize(env)
|
26
|
-
raise ArgumentError, "env must be a TaskExecutionEnvironment" unless env.kind_of?(TaskExecutionEnvironment)
|
27
|
-
|
28
|
-
@env = env
|
29
|
-
end
|
30
|
-
|
31
|
-
# Checks out repository code from a system and switches to the given branch
|
32
|
-
#
|
33
|
-
# @param url [String] the repository location
|
34
|
-
# @param local_dir [String] path to the working copy
|
35
|
-
# @param branch [String] the branch to check out
|
36
|
-
def checkout_from_remote(url, local_dir, branch)
|
37
|
-
res = @env.command("git clone #{url} #{local_dir}")
|
38
|
-
raise RuntimeError, "Could not clone from git url #{url}" unless res.retval == 0
|
39
|
-
|
40
|
-
@env.chdir(local_dir)
|
41
|
-
res = @env.command("git checkout #{branch}")
|
42
|
-
@env.chdir('../')
|
43
|
-
|
44
|
-
raise RuntimeError, "could not switch to branch #{branch}" unless res.retval == 0
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns the current revision of the working copy
|
48
|
-
#
|
49
|
-
# @return [String] the current revision of the working copy
|
50
|
-
def revision
|
51
|
-
res = @env.command("git rev-parse HEAD")
|
52
|
-
|
53
|
-
res.stdout.gsub("\n", "")
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns scm files to be executed in the deployment process
|
57
|
-
#
|
58
|
-
# @return [Array] array of scm control files
|
59
|
-
def scm_files
|
60
|
-
[ '.git', '.gitignore' ]
|
61
|
-
end
|
62
|
-
|
63
|
-
# Returns the scm tools that have to be installed on specific systems
|
64
|
-
#
|
65
|
-
# @return [Array] array of utilities
|
66
|
-
def cli_utils
|
67
|
-
[ 'git' ]
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
AVOCADO
|
3
|
-
The flexible and easy to use deployment framework for web applications
|
4
|
-
|
5
|
-
This program is free software; you can redistribute it and/or
|
6
|
-
modify it under the terms of the GNU General Public License Version 2
|
7
|
-
as published by the Free Software Foundation.
|
8
|
-
|
9
|
-
This program is distributed in the hope that it will be useful,
|
10
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
GNU General Public License for more details.
|
13
|
-
|
14
|
-
You should have received a copy of the GNU General Public License
|
15
|
-
along with this program; if not, write to the Free Software
|
16
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
-
=end
|
18
|
-
|
19
|
-
module Avocado
|
20
|
-
# scm provider facade
|
21
|
-
class ScmProvider
|
22
|
-
|
23
|
-
# Initializes the scm provider
|
24
|
-
#
|
25
|
-
# @param env [TaskExecutionEnvironment] env for the commands to be executed in
|
26
|
-
# @param scm [Symbol] the scm provider to user
|
27
|
-
def initialize(env, scm)
|
28
|
-
raise ArgumentError, 'env must be a TaskExecutionEnvironment' unless env.is_a?(TaskExecutionEnvironment)
|
29
|
-
|
30
|
-
@env = env
|
31
|
-
@real_provider = nil
|
32
|
-
|
33
|
-
if scm == :git
|
34
|
-
@real_provider = GitScmProvider.new(env)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Checks out repository code from a system and switches to the given branch
|
39
|
-
#
|
40
|
-
# @param url [String] the repository location
|
41
|
-
# @param local_dir [String] path to the working copy
|
42
|
-
# @param branch [String] the branch to check out
|
43
|
-
def checkout_from_remote(url, local_dir, branch)
|
44
|
-
@real_provider.checkout_from_remote(url, local_dir, branch)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns the current revision of the working copy
|
48
|
-
#
|
49
|
-
# @return [String] the current revision of the working copy
|
50
|
-
def scm_files
|
51
|
-
@real_provider.scm_files
|
52
|
-
end
|
53
|
-
|
54
|
-
# Returns scm files to be executed in the deployment process
|
55
|
-
#
|
56
|
-
# @return [Array] array of scm control files
|
57
|
-
def cli_utils
|
58
|
-
@real_provider.cli_utils
|
59
|
-
end
|
60
|
-
|
61
|
-
# Returns the scm tools that have to be installed on specific systems
|
62
|
-
#
|
63
|
-
# @return [Array] array of utilities
|
64
|
-
def revision
|
65
|
-
@real_provider.revision
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,99 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
AVOCADO
|
3
|
-
The flexible and easy to use deployment framework for web applications
|
4
|
-
|
5
|
-
This program is free software; you can redistribute it and/or
|
6
|
-
modify it under the terms of the GNU General Public License Version 2
|
7
|
-
as published by the Free Software Foundation.
|
8
|
-
|
9
|
-
This program is distributed in the hope that it will be useful,
|
10
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
GNU General Public License for more details.
|
13
|
-
|
14
|
-
You should have received a copy of the GNU General Public License
|
15
|
-
along with this program; if not, write to the Free Software
|
16
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
-
=end
|
18
|
-
|
19
|
-
Avocado::Deployment.configure do
|
20
|
-
|
21
|
-
task :check_local_tools, before: :deploy, scope: :local, visibility: :private do
|
22
|
-
check_util_availability [ 'tar' ].concat(@scm.cli_utils)
|
23
|
-
end
|
24
|
-
|
25
|
-
task :check_remote_system, before: :deploy, scope: :remote, visibility: :private do
|
26
|
-
check_util_availability [ 'tar' ]
|
27
|
-
end
|
28
|
-
|
29
|
-
task :check_temp_existance, visibility: :private, after: :deploy, scope: :local do
|
30
|
-
if File.exist?('.avocado-tmp')
|
31
|
-
raise RuntimeError, 'The avocado tmp directory (.avocado-tmp) does already exist. That may indicate that another deployment is already running.'
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
task :switch_to_temp_dir, visibility: :private, after: :check_temp_existance, scope: :local do
|
36
|
-
command "mkdir .avocado-tmp/"
|
37
|
-
chdir(".avocado-tmp/")
|
38
|
-
end
|
39
|
-
|
40
|
-
task :checkout_from_scm, visibility: :private, after: :switch_to_temp_dir, scope: :local do
|
41
|
-
@scm.checkout_from_remote(get(:repo_url), 'working-copy', get(:branch))
|
42
|
-
end
|
43
|
-
|
44
|
-
task :get_scm_info, visibility: :private, after: :checkout_from_scm, scope: :local do
|
45
|
-
chdir("working-copy/")
|
46
|
-
|
47
|
-
set(:revision, @scm.revision)
|
48
|
-
|
49
|
-
chdir("../")
|
50
|
-
end
|
51
|
-
|
52
|
-
task :delete_ignored_files, visibility: :private, after: :get_scm_info, scope: :local do
|
53
|
-
if get(:ignore_files).concat(@scm.scm_files).size > 0
|
54
|
-
chdir("working-copy/")
|
55
|
-
command "rm -rfv #{get(:ignore_files).concat(@scm.scm_files).join(' ')}"
|
56
|
-
chdir("../")
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
task :create_revision_file, visibility: :private, after: :delete_ignored_files, scope: :local do
|
61
|
-
chdir("working-copy/")
|
62
|
-
command "echo '#{get(:revision)}' > REVISION"
|
63
|
-
chdir("../")
|
64
|
-
end
|
65
|
-
|
66
|
-
task :create_deployment_tarball, visibility: :private, after: :create_revision_file, scope: :local do
|
67
|
-
chdir("working-copy/")
|
68
|
-
command "tar cvfz ../deploy.tar.gz ."
|
69
|
-
chdir("../")
|
70
|
-
end
|
71
|
-
|
72
|
-
task :upload, visibility: :private, after: :create_deployment_tarball, scope: :local do
|
73
|
-
targets.each_pair do |key, target|
|
74
|
-
copy_to_target(target, 'deploy.tar.gz', '/tmp/deploy.tar.gz')
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
task :create_deploy_dir, visibility: :private, after: :upload, scope: :remote do
|
79
|
-
command "if [ ! -d '#{get(:deploy_dir)}' ]; then mkdir -p #{get(:deploy_dir)}; fi"
|
80
|
-
end
|
81
|
-
|
82
|
-
task :unpack, visibility: :private, after: :create_deploy_dir, scope: :remote do
|
83
|
-
command "tar xvfz /tmp/deploy.tar.gz -C #{get(:deploy_dir)}/"
|
84
|
-
end
|
85
|
-
|
86
|
-
task :cleanup_remote, visibility: :private, after: :unpack, scope: :remote do
|
87
|
-
command "rm /tmp/deploy.tar.gz"
|
88
|
-
end
|
89
|
-
|
90
|
-
task :log_deployment, visibility: :private, after: :cleanup_remote, scope: :remote do
|
91
|
-
command "echo '[#{ Time.now.strftime('%Y-%m-%d %H-%M-%S')}] revision #{get(:revision)} deployed by #{ENV['USER']}' >> #{get(:log_file)}"
|
92
|
-
end
|
93
|
-
|
94
|
-
task :cleanup_local, visibility: :private, after: :cleanup_remote, scope: :local do
|
95
|
-
chdir("../")
|
96
|
-
command "rm -rf .avocado-tmp"
|
97
|
-
end
|
98
|
-
|
99
|
-
end
|
@@ -1,127 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
AVOCADO
|
3
|
-
The flexible and easy to use deployment framework for web applications
|
4
|
-
|
5
|
-
This program is free software; you can redistribute it and/or
|
6
|
-
modify it under the terms of the GNU General Public License Version 2
|
7
|
-
as published by the Free Software Foundation.
|
8
|
-
|
9
|
-
This program is distributed in the hope that it will be useful,
|
10
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
GNU General Public License for more details.
|
13
|
-
|
14
|
-
You should have received a copy of the GNU General Public License
|
15
|
-
along with this program; if not, write to the Free Software
|
16
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
-
=end
|
18
|
-
|
19
|
-
module Avocado
|
20
|
-
class LocalTaskExecutionEnvironment < TaskExecutionEnvironment
|
21
|
-
|
22
|
-
# Initialized the environment
|
23
|
-
#
|
24
|
-
# @param config [Hash] deployment configuration
|
25
|
-
def initialize(config)
|
26
|
-
super
|
27
|
-
|
28
|
-
@dir = Dir.pwd
|
29
|
-
end
|
30
|
-
|
31
|
-
# Checks, if all utilities are available for the deployment process
|
32
|
-
# to be executed
|
33
|
-
#
|
34
|
-
# @param utils [Array] array with utilities to check
|
35
|
-
def check_util_availability(utils)
|
36
|
-
super(utils, 'locally')
|
37
|
-
end
|
38
|
-
|
39
|
-
# Changes the directory for commands to be executed in
|
40
|
-
#
|
41
|
-
# @param dir [String] the directory to change to
|
42
|
-
def chdir(dir)
|
43
|
-
log.debug "changing directory [#{dir.yellow}] " + "locally".cyan
|
44
|
-
|
45
|
-
Dir.chdir(dir)
|
46
|
-
@dir = Dir.pwd
|
47
|
-
end
|
48
|
-
|
49
|
-
# Returns the current working directory
|
50
|
-
#
|
51
|
-
# @return [String] current working directory
|
52
|
-
def cwd
|
53
|
-
@dir
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns all target systems to deploy to
|
57
|
-
#
|
58
|
-
# @return [Hash] hash of target systems
|
59
|
-
def targets
|
60
|
-
Avocado::Deployment.instance.config.targets
|
61
|
-
end
|
62
|
-
|
63
|
-
# Copies a file to a remote system (= target)
|
64
|
-
#
|
65
|
-
# @param target [Target] the target system to deploy to
|
66
|
-
# @param file [String] the local file to upload
|
67
|
-
# @param remote [String] path on the remote system
|
68
|
-
def copy_to_target(target, file, remote)
|
69
|
-
log = Avocado::Deployment.instance.log
|
70
|
-
|
71
|
-
log.info "started upload of file #{file} to #{target.name}"
|
72
|
-
|
73
|
-
Net::SSH.start(
|
74
|
-
target.config[:host],
|
75
|
-
target.config[:user]
|
76
|
-
) do |session|
|
77
|
-
session.scp.upload!(file, remote, :recursive => true) do |ch, name, sent, total|
|
78
|
-
percentage = 0
|
79
|
-
|
80
|
-
begin
|
81
|
-
percentage = (sent.to_f * 100 / total.to_f).to_i
|
82
|
-
rescue Exception => e
|
83
|
-
Avocado::Deployment.instance.handle_abort(e)
|
84
|
-
end
|
85
|
-
|
86
|
-
#log.info "\r#{name}: #{percentage}%"
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
log.info "upload completed"
|
91
|
-
end
|
92
|
-
|
93
|
-
# Executes a command locally in the current directory
|
94
|
-
#
|
95
|
-
# @param cmd [String] the command to execute
|
96
|
-
# @return [CommandExecutionResult] result of the command exection
|
97
|
-
def command(cmd)
|
98
|
-
log = Avocado::Deployment.instance.log
|
99
|
-
|
100
|
-
log.info "Executing [" + cmd.yellow + "] " + "locally".cyan
|
101
|
-
|
102
|
-
result = Avocado::CommandExecutionResult.new
|
103
|
-
|
104
|
-
begin
|
105
|
-
stdout, stderr, status = ::Open3.capture3(cmd, :chdir => cwd())
|
106
|
-
|
107
|
-
result.stdin = cmd
|
108
|
-
result.stdout = stdout
|
109
|
-
result.stderr = stderr
|
110
|
-
result.retval = status.exitstatus
|
111
|
-
|
112
|
-
if result.stdout.nil? == false && result.stdout.empty? == false
|
113
|
-
log.debug "Stdout: " + result.stdout.green
|
114
|
-
end
|
115
|
-
|
116
|
-
if result.stderr.nil? == false && result.stderr.empty? == false
|
117
|
-
log.debug "Stderr: " + result.stderr.red
|
118
|
-
end
|
119
|
-
rescue Exception => e
|
120
|
-
handle_abort e
|
121
|
-
end
|
122
|
-
|
123
|
-
result
|
124
|
-
end
|
125
|
-
|
126
|
-
end
|
127
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
=begin
|
2
|
-
AVOCADO
|
3
|
-
The flexible and easy to use deployment framework for web applications
|
4
|
-
|
5
|
-
This program is free software; you can redistribute it and/or
|
6
|
-
modify it under the terms of the GNU General Public License Version 2
|
7
|
-
as published by the Free Software Foundation.
|
8
|
-
|
9
|
-
This program is distributed in the hope that it will be useful,
|
10
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
-
GNU General Public License for more details.
|
13
|
-
|
14
|
-
You should have received a copy of the GNU General Public License
|
15
|
-
along with this program; if not, write to the Free Software
|
16
|
-
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
17
|
-
=end
|
18
|
-
|
19
|
-
module Avocado
|
20
|
-
class RemoteTaskExecutionEnvironment < TaskExecutionEnvironment
|
21
|
-
|
22
|
-
attr_accessor :config
|
23
|
-
|
24
|
-
# Creates a connection between the local and the remote system over ssh
|
25
|
-
def establish_connection
|
26
|
-
Avocado::Deployment.instance.log.info "connecting to #{get(:user)}@#{get(:host)}..."
|
27
|
-
|
28
|
-
begin
|
29
|
-
@session = ::Net::SSH.start(get(:host), get(:user))
|
30
|
-
rescue ::Net::SSH::AuthenticationFailed => e
|
31
|
-
handle_abort e
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# Checks, if all utilities are available for the deployment process
|
36
|
-
# to be executed
|
37
|
-
#
|
38
|
-
# @param utils [Array] array with utilities to check
|
39
|
-
def check_util_availability(utils)
|
40
|
-
super(utils, 'remotely')
|
41
|
-
end
|
42
|
-
|
43
|
-
# Executes a command via ssh
|
44
|
-
#
|
45
|
-
# @param ssh [Net::SSH::Connection::Session] ssh session
|
46
|
-
# @param command [String] the command to execute
|
47
|
-
def ssh_exec!(ssh, command)
|
48
|
-
stdout_data = ""
|
49
|
-
stderr_data = ""
|
50
|
-
exit_code = nil
|
51
|
-
exit_signal = nil
|
52
|
-
ssh.open_channel do |channel|
|
53
|
-
channel.exec(command) do |ch, success|
|
54
|
-
unless success
|
55
|
-
abort "FAILED: couldn't execute command (ssh.channel.exec)"
|
56
|
-
end
|
57
|
-
channel.on_data do |ch,data|
|
58
|
-
stdout_data+=data
|
59
|
-
end
|
60
|
-
|
61
|
-
channel.on_extended_data do |ch,type,data|
|
62
|
-
stderr_data+=data
|
63
|
-
end
|
64
|
-
|
65
|
-
channel.on_request("exit-status") do |ch,data|
|
66
|
-
exit_code = data.read_long
|
67
|
-
end
|
68
|
-
|
69
|
-
channel.on_request("exit-signal") do |ch, data|
|
70
|
-
exit_signal = data.read_long
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
ssh.loop
|
75
|
-
|
76
|
-
result = Avocado::CommandExecutionResult.new
|
77
|
-
result.stdin = command
|
78
|
-
result.stdout = stdout_data
|
79
|
-
result.stderr = stderr_data
|
80
|
-
result.retval = exit_code
|
81
|
-
|
82
|
-
result
|
83
|
-
end
|
84
|
-
|
85
|
-
# Executes a command on the remote system
|
86
|
-
#
|
87
|
-
# @param cmd [String] the command to execute
|
88
|
-
# @return [CommandExecutionResult] result of the command exection
|
89
|
-
def command(cmd)
|
90
|
-
Avocado::Deployment.instance.log.info "Executing [" + cmd.yellow + "] on remote " + get(:ssh_host).cyan
|
91
|
-
|
92
|
-
result = Avocado::CommandExecutionResult.new
|
93
|
-
|
94
|
-
begin
|
95
|
-
result = ssh_exec!(@session, cmd)
|
96
|
-
|
97
|
-
if result.stdout.nil? == false && result.stdout.empty? == false
|
98
|
-
Avocado::Deployment.instance.log.debug "Stdout@#{get(:host)}: ".cyan + result.stdout.green
|
99
|
-
end
|
100
|
-
|
101
|
-
if result.stderr.nil? == false && result.stderr.empty? == false
|
102
|
-
Avocado::Deployment.instance.log.debug "Stderr@#{get(:host)}: ".cyan + result.stderr.red
|
103
|
-
end
|
104
|
-
rescue Exception => e
|
105
|
-
handle_abort e
|
106
|
-
end
|
107
|
-
|
108
|
-
result
|
109
|
-
end
|
110
|
-
|
111
|
-
end
|
112
|
-
end
|