sshkit-sudo 0.0.5 → 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.
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