do 0.0.3 → 0.1.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.
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in do.gemspec
3
+ gem 'rspec'
4
+
4
5
  gemspec
data/README.md CHANGED
@@ -11,14 +11,31 @@ So why another one? Basically I need:
11
11
  * see perfectly what's happening on my remote servers
12
12
  * highly focus on smart actions, upload, download, sudo, replace.
13
13
  * manage easily more than one server at same time
14
- * use same syntax to manage local tasks
14
+ * a use same syntax to manage local tasks
15
+
16
+ What really is *DO* ?
17
+
18
+ * some like brew
19
+ * some like rake
20
+ * some like capistrano
21
+
22
+ All togheter mixed to make your life easier.
23
+
24
+ As mentioned before do is a fun mix of capistrano, rake, thor and brew.
25
+
26
+ With *DO* you are be able to do easily common task on your local or remote machine.
27
+ The aim of *DO* is to become the unique and universal tool language that permit you to make
28
+ your own _brew_, _apt-get_ or _yum_ package, same syntax for all your machine.
15
29
 
16
30
  ## DO - Installation and Setup
17
31
 
18
32
  ```sh
19
33
  $ sudo gem install do
20
- $ doit setup # setup DO directory
21
- $ doit -T # show DO tasks
34
+ $ doit download # download a new recipe with --url=
35
+ $ doit setup # setup a working home directory
36
+ $ doit version # show version number
37
+ $ doit list # show task list
38
+ $ doit help # show help message
22
39
  ```
23
40
 
24
41
  Now you can edit your `~/.do/dorc` adding your **servers** or **plugins**.
@@ -135,7 +152,7 @@ plugin :vim, 'https://raw.github.com/DAddYE/.do/master/vim.rake'
135
152
  However we have a `doit` command for that:
136
153
 
137
154
  ```sh
138
- $ doit download[https://raw.github.com/DAddYE/.do/master/l.rake]
155
+ $ doit download --url https://raw.github.com/DAddYE/.do/master/l.rake
139
156
  ```
140
157
 
141
158
  This command add for you a new line in your `~/.do/dorc` and perform:
@@ -150,11 +167,7 @@ file.
150
167
  Once this happen you are be able to see new tasks:
151
168
 
152
169
  ```sh
153
- $ doit -T
154
-
155
- ************************************************************
156
- * DO - IT! *
157
- ************************************************************
170
+ $ doit list
158
171
 
159
172
  doit plugin:vim # install vim plugin
160
173
  doit setup # setup a working home directory
@@ -184,7 +197,7 @@ I've also some recipes in my `~/.do` path:
184
197
  # ~/.do/configure.rake
185
198
  namespace :configure
186
199
  desc "upgrade rubygems and install useful gems"
187
- task :gems => :ree do
200
+ task :gems => :ree, :in => :web do
188
201
  run "gem update --system" if yes?("Do you want to update rubygems?")
189
202
  run "gem install rake"
190
203
  run "gem install highline"
@@ -193,18 +206,18 @@ namespace :configure
193
206
  end
194
207
 
195
208
  desc "create motd for each server"
196
- task :motd do
209
+ task :motd, :in => :remote do
197
210
  replace :all, "Hey boss! Welcome to the \e[1m#{name}\e[0m of LipsiaSOFT s.r.l.\n", "/etc/motd"
198
211
  end
199
212
 
200
213
  desc "redirect emails to a real account"
201
- task :root_emails do
214
+ task :root_emails, :in => :remote do
202
215
  append "\nroot: servers@lipsiasoft.com", "/etc/aliases"
203
216
  run "newaliases"
204
217
  end
205
218
 
206
219
  desc "mysql basic configuration"
207
- task :mysql => :yum do
220
+ task :mysql => :yum, :in => :remote do
208
221
  run "yum install mysql-server mysql mysql-devel -y"
209
222
  run "chkconfig --level 2345 mysqld on"
210
223
  run "service mysqld restart"
@@ -228,14 +241,14 @@ $ doit configure:mysql
228
241
  any task, ex:
229
242
 
230
243
  ```rb
231
- task :mysql => :yum do; ...; end
244
+ task :mysql => :yum, :in => :remote do; ...; end
232
245
  ```
233
246
 
234
247
  That's are some local tasks:
235
248
 
236
249
  ```rb
237
250
  namespace :l do
238
- local :setup do
251
+ task :setup do
239
252
  name = File.basename(File.expand_path('.'))
240
253
  exit unless yes?('Do you want to setup "%s"?' % name)
241
254
  srv = nil
@@ -246,18 +259,18 @@ namespace :l do
246
259
 
247
260
  if File.exist?('.git')
248
261
  exit unless yes?('Project "%s" has already a working repo, do you want remove it?' % name)
249
- sh 'rm -rf .git'
262
+ run 'rm -rf .git'
250
263
  end
251
264
 
252
- sh 'git init'
253
- sh 'git remote add origin git@lipsiasoft.biz:/%s.git' % name
254
- Rake::Task['l:commit'].invoke if yes?("Are you ready to commit it, database, config etc is correct?")
265
+ run 'git init'
266
+ run 'git remote add origin git@lipsiasoft.biz:/%s.git' % name
267
+ run_task('l:commit') if yes?("Are you ready to commit it, database, config etc is correct?")
255
268
  end
256
269
 
257
- local :commit do
258
- sh 'git add .'
259
- sh 'git commit -a'
260
- sh 'git push origin master'
270
+ task :commit do
271
+ run 'git add .'
272
+ run 'git commit -a'
273
+ run 'git push origin master'
261
274
  end
262
275
  end
263
276
  ```
@@ -277,8 +290,8 @@ standard rake tasks. *DO* extend `Rake`.
277
290
  Sometimes you want to perform a task only on some servers:
278
291
 
279
292
  ```sh
280
- $ doit configure:new --only-srv1 --only-srv2
281
- $ doit configure:new --except-srv1
293
+ $ doit configure:new --srv1 # apply recipes only on srv1
294
+ $ doit configure:new --no-srv1 # apply recipes to all except srv1
282
295
  ```
283
296
 
284
297
  ## DO - Output (Awesome...)
data/Rakefile CHANGED
@@ -1,8 +1,14 @@
1
1
  #!/usr/bin/env rake
2
- require 'bundler/setup'
2
+ require 'rubygems' unless defined?(Gem)
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
5
 
6
+ RSpec::Core::RakeTask.new(:spec) do |t|
7
+ t.rspec_opts = %w(-fs --color --fail-fast)
8
+ end
9
+
10
+ task :default => :spec
11
+
6
12
  %w(install release).each do |task|
7
13
  Rake::Task[task].enhance do
8
14
  sh "rm -rf pkg"
@@ -20,12 +26,3 @@ task :bump do
20
26
  end
21
27
 
22
28
  task :release => :bump
23
-
24
- desc "Run complete application spec suite"
25
- RSpec::Core::RakeTask.new("spec") do |t|
26
- t.skip_bundler = true
27
- t.pattern = './spec/**/*_spec.rb'
28
- t.rspec_opts = %w(-fs --color --fail-fast)
29
- end
30
-
31
- task :default => :spec
data/bin/doit CHANGED
@@ -1,30 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  $:.push File.expand_path("../../lib", __FILE__)
3
3
  require 'rubygems' unless defined?(Gem)
4
- require 'rake/dsl_definition'
5
- require 'rake'
6
4
  require 'do'
7
5
 
8
- ARGV << "-T" if ARGV.empty?
9
-
10
- only = ARGV.map { |a| a =~ /--only-(.*)/ && $1.to_sym }.compact
11
- except = ARGV.map { |a| a =~ /--except-(.*)/ && $1.to_sym }.compact
12
-
13
- ARGV.delete_if { |a| a =~ /--(only|except)/ }
14
-
15
- puts "\e[32m"
16
- puts "*" * 60
17
- puts "*" + "DO - IT!".center(58) + "*"
18
- puts "*" * 60
19
- puts "\e[0m"
20
-
21
- Rake.application.init
22
- Rake.application.instance_variable_set(:@name, 'doit')
23
- load(File.expand_path('../../lib/do/commands.rb', __FILE__))
24
- DO.recipes.each { |recipe| Rake.application.add_import(recipe) }
25
- Rake.application.load_imports
26
-
27
- servers.delete_if { |server| !only.include?(server.name) } unless only.empty?
28
- servers.delete_if { |server| except.include?(server.name) }
29
-
30
- Rake.application.top_level
6
+ DO::CLI.start(*ARGV)
data/do.gemspec CHANGED
@@ -14,10 +14,8 @@ Gem::Specification.new do |gem|
14
14
  gem.name = "do"
15
15
  gem.require_paths = ['lib']
16
16
  gem.version = DO::VERSION
17
- gem.add_dependency "rake", "~>0.9.2"
18
17
  gem.add_dependency "net-ssh", "~>2.1.4"
19
18
  gem.add_dependency "net-sftp", "~>2.0.5"
20
- gem.add_development_dependency "rspec"
21
19
 
22
20
  gem.post_install_message = "\e[32m" + ("*" * 60) + "\n"
23
21
  gem.post_install_message += "*" + "DO - IT! $ doit setup".center(58) + "*" + "\n"
data/lib/do/cli.rb ADDED
@@ -0,0 +1,14 @@
1
+ module DO
2
+ module CLI
3
+ extend self
4
+
5
+ def start(*args)
6
+ DO::Commands.load_recipes
7
+ args.empty? ? DO::Commands.run_task(:help) : DO::Commands.task_run(*args)
8
+ rescue DO::Tasks::NotFound
9
+ puts "\e[31mSorry, \e[1m'%s'\e[0m\e[31m was not found, see available tasks:\e[0m" % args.join(' ')
10
+ puts
11
+ DO::Commands.run_task(:list)
12
+ end
13
+ end # CLI
14
+ end # DO
data/lib/do/commands.rb CHANGED
@@ -1,11 +1,10 @@
1
- require 'rake/dsl_definition'
2
- require 'rake'
3
-
4
1
  module DO
5
2
  module Commands
6
- include Rake::DSL
3
+ include DO::Tasks
7
4
  include DO::Utils
8
5
 
6
+ extend self
7
+
9
8
  ##
10
9
  # Array of DO::Server defined in our tasks
11
10
  #
@@ -13,11 +12,8 @@ module DO
13
12
  @_servers ||= []
14
13
  end
15
14
 
16
- ##
17
- # An array of DO::Server selected by our remote task
18
- #
19
- def servers_selected
20
- @_servers_selected ||=[]
15
+ def remote
16
+ servers.map(&:name)
21
17
  end
22
18
 
23
19
  ##
@@ -27,6 +23,40 @@ module DO
27
23
  @_current_server
28
24
  end
29
25
 
26
+ ##
27
+ # Set an option to the given value
28
+ #
29
+ def set(option, value)
30
+ define_method(option) { value }
31
+ end
32
+
33
+ ##
34
+ # DO loads rakefiles in these locations:
35
+ #
36
+ # ~/do/dorc
37
+ # ~/do/*.rake
38
+ # ./Do
39
+ # ./Dofile
40
+ #
41
+ # DO_PATH, default is ~/do.
42
+ #
43
+ def recipes
44
+ @_recipes ||= (
45
+ %w[dorc **/*.rake].map { |f| Dir[File.join(DO_PATH, f)] }.flatten +
46
+ %w[./Do ./Dofile].map { |f| File.expand_path(f) } <<
47
+ File.expand_path('../common.rb', __FILE__)
48
+ ).reject { |f| !File.exist?(f) }
49
+ end
50
+
51
+ def load_recipes
52
+ recipes.each { |f| load_recipe(f) }
53
+ end
54
+
55
+ def load_recipe(path)
56
+ instance_eval(File.read(path), __FILE__, __LINE__)
57
+ end
58
+ alias :load :load_recipe
59
+
30
60
  ##
31
61
  # This method define our servers
32
62
  #
@@ -39,7 +69,20 @@ module DO
39
69
  #
40
70
  def server(name, host, user, options={})
41
71
  servers.push(DO::Server.new(name, host, user, options))
42
- local(name) { servers_selected.replace(servers.select { |s| s.name == name }) }
72
+ task name do |opts, b|
73
+ allowed = opts.map { |k,v| k if remote.include?(k) && v }.compact
74
+ denied = opts.map { |k,v| k if remote.include?(k) && v == false }.compact
75
+ if (allowed.empty? && denied.empty?) ||
76
+ (!allowed.empty? && allowed.include?(name)) ||
77
+ (!denied.empty? && !denied.include?(name))
78
+ @_current_server = servers.find { |s| s.name == name }
79
+ begin
80
+ b.arity == 1 ? b.call(opts) : b.call
81
+ ensure
82
+ @_current_server = nil
83
+ end
84
+ end
85
+ end
43
86
  end
44
87
 
45
88
  ##
@@ -52,95 +95,33 @@ module DO
52
95
  #
53
96
  def plugin(name, repo)
54
97
  desc "install #{name} plugin"
55
- local("plugin:#{name}" => :setup) do
56
- log "\e[36m## Installing plugin %s\e[0m" % name
57
- Dir.mkdir(DO_PATH) unless File.exist?(DO_PATH)
58
- sh "curl --location --progress-bar #{repo} > #{File.join(DO_PATH, '%s.rake' % name)}"
98
+ namespace :plugin do
99
+ task(name => :setup) do
100
+ log "\e[36m## Installing plugin %s\e[0m" % name
101
+ Dir.mkdir(DO_PATH) unless File.exist?(DO_PATH)
102
+ path = File.join(DO_PATH, '%s.rake' % name)
103
+ sh :curl, '--location', '--progress-bar', repo, '>', path
104
+ load_recipe(path)
105
+ end
59
106
  end
60
107
  end
61
108
 
62
109
  ##
63
- # Execute DO::Server operations on remote defined servers.
64
- #
65
- # ==== Examples:
66
- # # Define our ssh connections
67
- # keys = %w[key1.pem key2.pem key3.pem key4.pem]
68
- # server :srv1, 's1.domain.local', 'user', :keys => keys
69
- # server :srv2, 's2.domain.local', 'user', :keys => keys
70
- # server :srv3, 's3.domain.local', 'user', :keys => keys
71
- # server :srv4, 's4.domain.local', 'user', :keys => keys
72
- #
73
- # # => Executes commands only to :srv1, :srv2, :srv3
74
- # remote :name => [:srv1, :srv2, :srv3] do; ...; end
75
- #
76
- # # => Same as above
77
- # task :name => [:srv1, :srv2, :srv3] do; ...; end
78
- #
79
- # # => Executes commands on all defined servers
80
- # remote :name => :servers do; ...; end
81
- # # => Same as above
82
- # remote :name => do; ...; end
83
- # # => Same as above
84
- # task :name do; ...; end
85
- # # => Same as above
86
- # local :name => :servers do; ...; end
87
- #
88
- # # => Execute the task on your machine
89
- # local :name do; sh 'uname'; end
90
- #
91
- # # => Execute commands both on servers side and local side
92
- # remote :name do |t|
93
- # t.run 'run this command on remote servers'
94
- # sh 'run this command on my local machine'
95
- # end
96
- #
97
- # # same of:
98
- #
99
- # task :name do |t|
100
- # t.run 'command on remote servers'
101
- # sh 'command on my local machine'
102
- # end
103
- #
104
- # # => Execute command only on remote server srv1
105
- # task :name => :srv1 do
106
- # run 'command only on remote server srv1'
107
- # end
110
+ # Log text under current_server if available
108
111
  #
109
- def remote(args, &block)
110
- args = { args => :servers } unless args.is_a?(Hash)
111
- local(args) do
112
- name = args.is_a?(Hash) ? args.keys[0] : args
113
- servers_selected.each do |current|
114
- begin
115
- server_was, @_current_server = @_current_server, current
116
- self.class.send(:define_method, name, &block)
117
- method = self.class.instance_method(name)
118
- self.class.send(:remove_method, name)
119
- block.arity == 1 ? method.bind(self).call(current) : method.bind(current).call
120
- ensure
121
- @_current_server = server_was
122
- end # begin
123
- end # servers
124
- end # local
112
+ def log(text="", new_line=true)
113
+ current_server ? current_server.log(text, new_line) : super(text, new_line)
125
114
  end
126
115
 
127
- alias_method :local, :task
128
- alias_method :task, :remote
129
-
130
116
  ##
131
- # Log text under current_server if available
117
+ # Run commands on current_server if available
132
118
  #
133
- def log(text="", new_line=true)
134
- if current_server
135
- current_server.log(text, new_line)
136
- else
137
- text += "\n" if new_line && text[-1] != ?\n
138
- print(text)
139
- end
119
+ def run(*args)
120
+ current_server ? current_server.run(*args) : super(*args)
121
+ end
122
+
123
+ def method_missing(method, *args, &block)
124
+ current_server && current_server.respond_to?(method) ? current_server.send(method, *args) : super(method, *args, &block)
140
125
  end
141
126
  end # Commands
142
127
  end # DO
143
-
144
- self.extend DO::Commands
145
-
146
- load(File.expand_path('../common.rb', __FILE__))
data/lib/do/common.rb CHANGED
@@ -1,41 +1,40 @@
1
1
  ##
2
2
  # Common tasks performed by doit
3
3
  #
4
-
5
- local :servers do
6
- servers_selected.replace(servers)
7
- end
8
-
9
- local :download, [:recipe] => :setup do |t, options|
10
- if options[:recipe]
11
- name = File.basename(options[:recipe], '.rake')
4
+ desc "download a new recipe with --url="
5
+ task :download => :setup do |options|
6
+ if options[:url]
7
+ name = File.basename(options[:url], '.rake')
12
8
  rc = File.join(DO_PATH, 'dorc')
13
9
  buf = File.read(rc)
14
10
 
15
- if buf.include?(options[:recipe])
16
- log "\e[31mYour '\e[1m%s\e[31m' already has the plugin '\e[1m%s\e[0m'" % [rc, options[:recipe]]
11
+ if buf.include?(options[:url])
12
+ log "'\e[1m%s\e[0m' already has plugin '\e[1m%s\e[0m'" % [rc, options[:url]]
13
+ log
17
14
  log "Please run: $ doit plugin:%s" % name
18
15
  exit
19
16
  else
20
- plugin = "plugin :%s, '%s'\n" % [name, options[:recipe]]
17
+ plugin = "plugin :%s, '%s'\n" % [name, options[:url]]
21
18
  File.open(rc, 'a') { |f| f.write plugin }
22
- load(rc)
23
- Rake::Task['plugin:%s' % name].invoke
19
+ load_recipe(rc)
20
+ task_run('plugin:%s' % name)
24
21
  end
25
22
  else
26
23
  log "\e[31mYou must provide a recipe path ex:\e[0m"
27
24
  log
28
- log " $ doit download[https://raw.github.com/DAddYE/.do/master/l.rake]"
25
+ log " $ doit download --url=https://raw.github.com/DAddYE/.do/master/l.rake"
29
26
  log
30
27
  end
31
28
  end
32
29
 
33
30
  desc "setup a working home directory"
34
- local :setup do
31
+ task :setup do |options|
35
32
  Dir.mkdir(DO_PATH) unless File.exist?(DO_PATH)
36
33
  hrc = File.expand_path("~/.dorc")
37
34
  orc = File.join(DO_PATH, 'dorc')
38
- unless File.exist?(orc)
35
+ if File.exist?(orc)
36
+ log "Config already exist in your %s path" % DO_PATH unless options[:dependency]
37
+ else
39
38
  template = <<-RUBY.gsub(/^ {6}/, '')
40
39
  ##
41
40
  # Server definitions
@@ -54,3 +53,35 @@ local :setup do
54
53
  end
55
54
  sh 'ln -s %s %s' % [orc, hrc] unless File.exist?(hrc)
56
55
  end
56
+
57
+ desc "show version number"
58
+ task :version do
59
+ log "\e[1mDO\e[0m version %s" % DO::VERSION
60
+ end
61
+
62
+ desc "show task list"
63
+ task :list do
64
+ formatted = tasks.map { |t| ["\e[1mdoit\e[0m\e[34m %s:%s\e[0m" % [t[:namespace], t[:name]], t[:desc]] }
65
+ formatted.each { |f| f[0].gsub!(/\s:/, ' ') }
66
+ formatted.reject! { |t, desc| desc == '' }
67
+ max = formatted.max { |a,b| a[0].size <=> b[0].size }[0].size
68
+ log formatted.map { |t, desc| "%s \e[0m# %s" % [t.ljust(max+2), desc] }.join("\n")
69
+ end
70
+
71
+ desc "show help message"
72
+ task :help do
73
+ log <<-TEXT.gsub(/^ {4}/, '')
74
+ Usage \e[1mdoit\e[0m task [options]
75
+
76
+ Available Tasks:
77
+
78
+ TEXT
79
+
80
+ run_task(:list)
81
+
82
+ log <<-TEXT.gsub(/^ {4}/, '')
83
+
84
+ Options:
85
+ Each task can accept multiple options
86
+ TEXT
87
+ end
data/lib/do/parser.rb ADDED
@@ -0,0 +1,38 @@
1
+ module DO
2
+ class Parser < Hash
3
+
4
+ def initialize(*args)
5
+ options = {}
6
+ args.each_with_index do |arg, i|
7
+ case arg
8
+ # --foo=bar
9
+ when /=/
10
+ key, value = *arg.split("=")
11
+ options[key.sub(/^-{1,2}/,'').to_sym] = value
12
+ # --no-foo
13
+ when /^-{1,2}no-(.+)/
14
+ options[$1.to_sym] = false
15
+ # --foo bar
16
+ # --foo
17
+ # -foo
18
+ when /^-{1,2}(.+)/
19
+ value = args[i+1] && args[i+1] != /^--/ ? args.delete_at(i+1) : true
20
+ options[$1.to_sym] = value
21
+ end
22
+ end
23
+
24
+ # Automatically map values
25
+ options.each do |k, v|
26
+ case v
27
+ when /^true$/i then options[k] = true
28
+ when /^false$/i then options[k] = false
29
+ when /^\d+$/ then options[k] = v.to_i
30
+ when /^[\d\.]+$/ then options[k] = v.to_f
31
+ when /,/ then options[k] = v.split(",")
32
+ end
33
+ end
34
+
35
+ self.replace(options)
36
+ end
37
+ end # Parser
38
+ end # DO
data/lib/do/server.rb CHANGED
@@ -5,10 +5,7 @@ module DO
5
5
  class Server
6
6
  include DO::Utils
7
7
 
8
- LOG_FORMAT = "\e[36m%s\e[33m@\e[31m%s \e[33m~ \e[35m#\e[0m %s" unless defined?(LOG_FORMAT)
9
-
10
8
  attr_reader :name, :host, :user, :options
11
- attr_accessor :logger
12
9
 
13
10
  ##
14
11
  # Initialize a new DO Server
@@ -20,16 +17,14 @@ module DO
20
17
  #
21
18
  # ==== Examples:
22
19
  # srv1 = DO::Server.new(:srv1, 'srv1.lipsiasoft.biz', 'root', :keys => %w[/path/to/key.pem]
23
- # srv1.logger = StringIO.new # default is STDOUT
24
20
  #
25
21
  def initialize(name, host, user, options={})
26
22
  @name, @host, @user, @options = name, host, user, options
27
- @logger = STDOUT
28
23
  end
29
24
 
30
25
  ##
31
26
  # Method used to print a formatted version of our commands
32
- # using DO::Server::LOG_FORMAT, by default we have a nice
27
+ # using DO::Server::DO_LOGGER_FORMAT, by default we have a nice
33
28
  # colored version like:
34
29
  #
35
30
  # srv1@root ~ # ls -al
@@ -37,11 +32,10 @@ module DO
37
32
  # If you don't like colors or our format feel free to edit:
38
33
  #
39
34
  # ==== Examples:
40
- # DO::Server::LOG_FORMAT = "%s@%s$ %s"
35
+ # DO::Server::DO_LOGGER_FORMAT = "%s@%s$ %s"
41
36
  #
42
37
  def log(text="", new_line=true)
43
- text += "\n" if new_line && text[-1] != ?\n
44
- logger.print LOG_FORMAT % [user, name, text]
38
+ super(DO_LOGGER_FORMAT % [user, name, text], new_line)
45
39
  end
46
40
 
47
41
  ##
@@ -76,21 +70,34 @@ module DO
76
70
  def run(*args)
77
71
  options = args.last.is_a?(Hash) ? args.pop : {}
78
72
  cmd = args.join(" ")
79
- cmd = "su #{options[:as]} -c '#{cmd.gsub(/'/, "\'")}'" if options[:as]
73
+ if options[:as]
74
+ if options[:as] == 'root'
75
+ cmd = "sudo #{cmd.gsub(/'/, "\'")}"
76
+ else
77
+ cmd = "su #{options[:as]} -c '#{cmd.gsub(/'/, "\'")}'"
78
+ end
79
+ end
80
80
  log cmd
81
81
  result = ""
82
- ssh.exec!(cmd) do |channel, stream, data|
83
- result << data
84
- logger.print(data) unless options[:silent]
85
- if options[:input]
86
- match = options[:match] || /^Enter password:/
87
- if data =~ match
88
- options[:input] += "\n" if options[:input][-1] != ?\n
89
- channel.send_data(options[:input])
90
- logger.puts(options[:input]) unless options[:silent]
82
+ ssh.open_channel do |channel|
83
+ channel.request_pty do |c, success|
84
+ raise "could not request pty" unless success
85
+ channel.exec cmd
86
+ channel.on_data do |c_, data|
87
+ result << data
88
+ DO_LOGGER.print(data) unless options[:silent]
89
+ if options[:input]
90
+ match = options[:match] || /password:/i
91
+ if data =~ match
92
+ options[:input] += "\n" if options[:input][-1] != ?\n
93
+ channel.send_data(options[:input])
94
+ DO_LOGGER.puts(options[:input]) unless options[:silent] || data =~ /password:/i
95
+ end
96
+ end
91
97
  end
92
98
  end
93
99
  end
100
+ ssh.loop
94
101
  result.chomp
95
102
  end
96
103