sshkit-sudo 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b5d6298a3efbd2224bec41000feb3bc4700a0506
4
- data.tar.gz: 17be3a66b0d57e0588c07358d6ec6a23bf402d5a
3
+ metadata.gz: 584ff1236a17ccb0e7a8d86879c20507500d27cc
4
+ data.tar.gz: 6ff19bcecb8f204277a21447d1a6723252b68a7e
5
5
  SHA512:
6
- metadata.gz: 7e49ef8108a412566391395ddc4fa48bf080bc643c5cad8bab12197741ba043f7e648dc564f51c7dcecdef4a05b064fc77b074c08648b08d03444cfc6e4843c2
7
- data.tar.gz: e6eef7349a71a7c2c83208a2b25dda19b94d4aa13ebbcbd7b8aaeda692cdd13440ae2ff8f1e243385bcc9e89113aaa418ce0bd0d74a4f0e1e8d90185eae39855
6
+ metadata.gz: 94eb893a96ad4aa5e66f776629e24e50d2ce02e4940ff4dddbf7eec0bd139110d0f2368e014aa9aff6ddf246b217112669bad7bcb04a98683a5d35b9d43572ff
7
+ data.tar.gz: af0359eb6962017f05967396c10f844a03e5fde4abd0a56ae12f721cf70e554d004dbf78c8ef03006ea820459c5e17d6c77ad09864df2395833f2aefd0379dc4
data/README.md CHANGED
@@ -75,6 +75,50 @@ namespace :prov do
75
75
  end
76
76
  ```
77
77
 
78
+ ### Configuration
79
+ Available in sshkit-sudo 0.1.0 and later.
80
+
81
+ #### Same password across servers
82
+ If you are using a same password across all servers, you can skip inputting the password for the second server or after
83
+ by using `use_same_password!` method in your `deploy.rb` as follows:
84
+ ```ruby
85
+ class SSHKit::Sudo::InteractionHandler
86
+ use_same_password!
87
+ end
88
+ ```
89
+
90
+ #### Password prompt and wrong password matchers
91
+ You can set your own matchers in your `deploy.rb` as follows:
92
+ ```ruby
93
+ class SSHKit::Sudo::InteractionHandler
94
+ password_prompt_regexp /[Pp]assword.*:/
95
+ wrong_password_regexp /Sorry.*\stry\sagain/
96
+ end
97
+ ```
98
+
99
+ #### Making your own handler
100
+ You can write your own handler in your `deploy.rb` as follows:
101
+ ```ruby
102
+ class SSHKit::Sudo::InteractionHandler
103
+ def on_data(command, stream_name, data, channel)
104
+ if data =~ wrong_password
105
+ SSHKit::Sudo.password_cache[password_cache_key(command.host)] = nil
106
+ end
107
+ if data =~ password_prompt
108
+ key = password_cache_key(command.host)
109
+ pass = SSHKit::Sudo.password_cache[key]
110
+ unless pass
111
+ print data
112
+ pass = $stdin.noecho(&:gets)
113
+ puts ''
114
+ SSHKit::Sudo.password_cache[key] = pass
115
+ end
116
+ channel.send_data(pass)
117
+ end
118
+ end
119
+ end
120
+ ```
121
+
78
122
  ## Contributing
79
123
 
80
124
  1. Fork it ( https://github.com/[my-github-username]/sshkit-sudo/fork )
@@ -1,8 +1,8 @@
1
1
  require "sshkit/sudo/version"
2
2
  require 'sshkit'
3
- require "sshkit/sudo/backends_ext/printer"
4
- require "sshkit/sudo/backends_ext/netssh"
5
- require "sshkit/sudo/backends_ext/local"
3
+ require 'sshkit/sudo/interaction_handler'
4
+ require 'sshkit/sudo/backends/abstract'
5
+ require 'sshkit/sudo/backends/netssh'
6
6
 
7
7
  module SSHKit
8
8
  module Sudo
@@ -10,4 +10,7 @@ module SSHKit
10
10
  @password_cache ||= {}
11
11
  end
12
12
  end
13
+
14
+ Backend::Abstract.send(:include, ::SSHKit::Sudo::Backend::Abstract)
15
+ Backend::Netssh.send(:include, ::SSHKit::Sudo::Backend::Netssh)
13
16
  end
@@ -0,0 +1,26 @@
1
+ module SSHKit
2
+ module Sudo
3
+ module Backend
4
+ module Abstract
5
+ def sudo(*args)
6
+ execute!(:sudo, *args)
7
+ end
8
+
9
+ def execute!(*args)
10
+ options = args.extract_options!
11
+ options[:interaction_handler] ||= SSHKit::Sudo::InteractionHandler.new
12
+ create_command_and_execute!(args, options).success?
13
+ end
14
+
15
+ private
16
+ def execute_command!(*args)
17
+ execute_command(*args)
18
+ end
19
+
20
+ def create_command_and_execute!(args, options)
21
+ command(args, options).tap { |cmd| execute_command!(cmd) }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,57 @@
1
+ module SSHKit
2
+ module Sudo
3
+ module Backend
4
+ module Netssh
5
+ private
6
+ def execute_command!(cmd)
7
+ output.log_command_start(cmd)
8
+ cmd.started = true
9
+ exit_status = nil
10
+ with_ssh do |ssh|
11
+ ssh.open_channel do |chan|
12
+ chan.request_pty
13
+ chan.exec cmd.to_command do |_ch, _success|
14
+ chan.on_data do |ch, data|
15
+ cmd.on_stdout(ch, data)
16
+ output.log_command_data(cmd, :stdout, data)
17
+ end
18
+ chan.on_extended_data do |ch, _type, data|
19
+ cmd.on_stderr(ch, data)
20
+ output.log_command_data(cmd, :stderr, data)
21
+ end
22
+ chan.on_request("exit-status") do |_ch, data|
23
+ exit_status = data.read_long
24
+ end
25
+ #chan.on_request("exit-signal") do |ch, data|
26
+ # # TODO: This gets called if the program is killed by a signal
27
+ # # might also be a worthwhile thing to report
28
+ # exit_signal = data.read_string.to_i
29
+ # warn ">>> " + exit_signal.inspect
30
+ # output.log_command_killed(cmd, exit_signal)
31
+ #end
32
+ chan.on_open_failed do |_ch|
33
+ # TODO: What do do here?
34
+ # I think we should raise something
35
+ end
36
+ chan.on_process do |_ch|
37
+ # TODO: I don't know if this is useful
38
+ end
39
+ chan.on_eof do |_ch|
40
+ # TODO: chan sends EOF before the exit status has been
41
+ # writtend
42
+ end
43
+ end
44
+ chan.wait
45
+ end
46
+ ssh.loop
47
+ end
48
+ # Set exit_status and log the result upon completion
49
+ if exit_status
50
+ cmd.exit_status = exit_status
51
+ output.log_command_exit(cmd)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,61 @@
1
+ module SSHKit
2
+ module Sudo
3
+ class DefaultInteractionHandler
4
+ def wrong_password; self.class.wrong_password; end
5
+ def password_prompt; self.class.password_prompt; end
6
+
7
+ def on_data(command, stream_name, data, channel)
8
+ if data =~ wrong_password
9
+ puts data if defined?(Airbrussh) and
10
+ Airbrussh.configuration.command_output != :stdout and
11
+ data !~ password_prompt
12
+ SSHKit::Sudo.password_cache[password_cache_key(command.host)] = nil
13
+ end
14
+ if data =~ password_prompt
15
+ key = password_cache_key(command.host)
16
+ pass = SSHKit::Sudo.password_cache[key]
17
+ unless pass
18
+ print data
19
+ pass = $stdin.noecho(&:gets)
20
+ puts ''
21
+ SSHKit::Sudo.password_cache[key] = pass
22
+ end
23
+ channel.send_data(pass)
24
+ end
25
+ end
26
+
27
+ def password_cache_key(host)
28
+ "#{host.user}@#{host.hostname}"
29
+ end
30
+
31
+ class << self
32
+ def wrong_password
33
+ @wrong_password ||= /Sorry.*\stry\sagain/
34
+ end
35
+
36
+ def password_prompt
37
+ @password_prompt ||= /[Pp]assword.*:/
38
+ end
39
+
40
+ def wrong_password_regexp(regexp)
41
+ @wrong_password = regexp
42
+ end
43
+
44
+ def password_prompt_regexp(regexp)
45
+ @password_prompt = regexp
46
+ end
47
+
48
+ def use_same_password!
49
+ class_eval <<-METHOD, __FILE__, __LINE__ + 1
50
+ def password_cache_key(host)
51
+ '0'
52
+ end
53
+ METHOD
54
+ end
55
+ end
56
+ end
57
+
58
+ class InteractionHandler < DefaultInteractionHandler
59
+ end
60
+ end
61
+ end
@@ -1,5 +1,5 @@
1
1
  module SSHKit
2
2
  module Sudo
3
- VERSION = "0.0.5"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = ">= 1.9.3"
22
22
 
23
- spec.add_dependency "sshkit", "< 1.8"
23
+ spec.add_dependency "sshkit", "~> 1.8"
24
24
  spec.add_development_dependency "bundler", "~> 1.7"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sshkit-sudo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kentaro Imai
@@ -14,14 +14,14 @@ dependencies:
14
14
  name: sshkit
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "<"
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "<"
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.8'
27
27
  - !ruby/object:Gem::Dependency
@@ -65,9 +65,9 @@ files:
65
65
  - README.md
66
66
  - Rakefile
67
67
  - lib/sshkit/sudo.rb
68
- - lib/sshkit/sudo/backends_ext/local.rb
69
- - lib/sshkit/sudo/backends_ext/netssh.rb
70
- - lib/sshkit/sudo/backends_ext/printer.rb
68
+ - lib/sshkit/sudo/backends/abstract.rb
69
+ - lib/sshkit/sudo/backends/netssh.rb
70
+ - lib/sshkit/sudo/interaction_handler.rb
71
71
  - lib/sshkit/sudo/version.rb
72
72
  - sshkit-sudo.gemspec
73
73
  homepage: ''
@@ -1,11 +0,0 @@
1
- module SSHKit
2
- module Backend
3
- class Local < Printer
4
- def sudo(*args)
5
- _execute(:sudo, *args).success?
6
- end
7
-
8
- alias execute! execute
9
- end
10
- end
11
- end
@@ -1,88 +0,0 @@
1
- require 'io/console'
2
-
3
- module SSHKit
4
- module Backend
5
-
6
- class Netssh < Printer
7
- def sudo(*args)
8
- _execute!(:sudo, *args).success?
9
- end
10
-
11
- def execute!(*args)
12
- _execute!(*args).success?
13
- end
14
-
15
- private
16
-
17
- def _execute!(*args)
18
- command(*args).tap do |cmd|
19
- output << cmd
20
- cmd.started = true
21
- exit_status = nil
22
- with_ssh do |ssh|
23
- ssh.open_channel do |chan|
24
- chan.request_pty
25
- chan.exec cmd.to_command do |ch, success|
26
- chan.on_data do |ch, data|
27
- cmd.stdout = data
28
- cmd.full_stdout += data
29
- output << cmd
30
- if data =~ /Sorry.*\stry\sagain/
31
- SSHKit::Sudo.password_cache[password_cache_key(cmd.host)] = nil
32
- end
33
- if data =~ /[Pp]assword.*:/
34
- key = password_cache_key(cmd.host)
35
- pass = SSHKit::Sudo.password_cache[key]
36
- unless pass
37
- pass = $stdin.noecho(&:gets)
38
- SSHKit::Sudo.password_cache[key] = pass
39
- end
40
- ch.send_data(pass)
41
- end
42
- end
43
- chan.on_extended_data do |ch, type, data|
44
- cmd.stderr = data
45
- cmd.full_stderr += data
46
- output << cmd
47
- end
48
- chan.on_request("exit-status") do |ch, data|
49
- exit_status = data.read_long
50
- end
51
- #chan.on_request("exit-signal") do |ch, data|
52
- # # TODO: This gets called if the program is killed by a signal
53
- # # might also be a worthwhile thing to report
54
- # exit_signal = data.read_string.to_i
55
- # warn ">>> " + exit_signal.inspect
56
- # output << cmd
57
- #end
58
- chan.on_open_failed do |ch|
59
- # TODO: What do do here?
60
- # I think we should raise something
61
- end
62
- chan.on_process do |ch|
63
- # TODO: I don't know if this is useful
64
- end
65
- chan.on_eof do |ch|
66
- # TODO: chan sends EOF before the exit status has been
67
- # writtend
68
- end
69
- end
70
- chan.wait
71
- end
72
- ssh.loop
73
- end
74
- # Set exit_status and log the result upon completion
75
- if exit_status
76
- cmd.exit_status = exit_status
77
- output << cmd
78
- end
79
- end
80
- end
81
-
82
- def password_cache_key(host)
83
- "#{host.user}@#{host.hostname}"
84
- end
85
- end
86
- end
87
-
88
- end
@@ -1,13 +0,0 @@
1
- module SSHKit
2
- module Backend
3
- class Printer < Abstract
4
- def sudo(*args)
5
- command(:sudo, *args).tap do |cmd|
6
- output << cmd
7
- end
8
- end
9
-
10
- alias execute! execute
11
- end
12
- end
13
- end