sshwrap 0.0.2 → 0.0.3
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/LICENSE +1 -1
 - data/README.md +2 -1
 - data/bin/sshwrap +1 -0
 - data/lib/sshwrap/main.rb +44 -15
 - data/lib/sshwrap/prompter.rb +15 -0
 - data/lib/sshwrap/version.rb +1 -1
 - data/sshwrap.gemspec +1 -1
 - metadata +4 -3
 
    
        data/LICENSE
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,7 +1,8 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # SSHwrap
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            This provides a wrapper for ssh that execute a command on multiple machines,
         
     | 
| 
       4 
     | 
    
         
            -
            optionally in parallel, and handles any sudo prompts that 
     | 
| 
      
 4 
     | 
    
         
            +
            optionally in parallel, and handles any ssh and sudo password prompts that
         
     | 
| 
      
 5 
     | 
    
         
            +
            result.
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            ## Installation
         
     | 
| 
       7 
8 
     | 
    
         | 
    
        data/bin/sshwrap
    CHANGED
    
    
    
        data/lib/sshwrap/main.rb
    CHANGED
    
    | 
         @@ -1,24 +1,53 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'etc'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'yaml'
         
     | 
| 
       1 
3 
     | 
    
         
             
            require 'net/ssh'
         
     | 
| 
       2 
4 
     | 
    
         
             
            require 'highline/import'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'sshwrap/prompter'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            # Monkey patch our prompt method into Net::SSH
         
     | 
| 
      
 8 
     | 
    
         
            +
            module Net::SSH
         
     | 
| 
      
 9 
     | 
    
         
            +
              def KeyFactory.prompt(prompt, echo=true)
         
     | 
| 
      
 10 
     | 
    
         
            +
                @prompter ||= SSHwrap::Prompter.new
         
     | 
| 
      
 11 
     | 
    
         
            +
                @prompter.prompt(prompt + ' ', echo)
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
              module Authentication::Methods
         
     | 
| 
      
 14 
     | 
    
         
            +
                def KeyboardInteractive.prompt(prompt, echo=true)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @prompter ||= SSHwrap::Prompter.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @prompter.prompt(prompt + ' ', echo)
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
            end
         
     | 
| 
       3 
20 
     | 
    
         | 
| 
       4 
21 
     | 
    
         
             
            class SSHwrap::Main
         
     | 
| 
       5 
22 
     | 
    
         
             
              def initialize(options={})
         
     | 
| 
      
 23 
     | 
    
         
            +
                home = Dir.respond_to?(:home) ? Dir.home : ENV['HOME'] || ENV['LOGDIR']
         
     | 
| 
      
 24 
     | 
    
         
            +
                conffile = "#{home}/.sshwrap.yaml"
         
     | 
| 
      
 25 
     | 
    
         
            +
                if File.exist?(conffile)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  conf = YAML.load_file(conffile)
         
     | 
| 
      
 27 
     | 
    
         
            +
                else
         
     | 
| 
      
 28 
     | 
    
         
            +
                  conf = {}
         
     | 
| 
      
 29 
     | 
    
         
            +
                end
         
     | 
| 
      
 30 
     | 
    
         
            +
                
         
     | 
| 
       6 
31 
     | 
    
         
             
                @mutex = Mutex.new
         
     | 
| 
       7 
32 
     | 
    
         
             
                @max_workers = options[:max_workers] || 1
         
     | 
| 
       8 
33 
     | 
    
         
             
                @abort_on_failure = options[:abort_on_failure]
         
     | 
| 
       9 
34 
     | 
    
         
             
                @user = options[:user] || Etc.getlogin
         
     | 
| 
       10 
35 
     | 
    
         
             
                @ssh_key = options[:ssh_key]
         
     | 
| 
       11 
36 
     | 
    
         
             
                @debug = options[:debug]
         
     | 
| 
       12 
     | 
    
         
            -
                @ 
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
      
 37 
     | 
    
         
            +
                @prompter = SSHwrap::Prompter.new
         
     | 
| 
      
 38 
     | 
    
         
            +
                @ssh_prompt = "Password for #{@user}: "
         
     | 
| 
      
 39 
     | 
    
         
            +
                
         
     | 
| 
      
 40 
     | 
    
         
            +
                if conf['password_regexp']
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @password_regexp = Regexp.new('(' + conf['password_regexp'] + ')')
         
     | 
| 
      
 42 
     | 
    
         
            +
                elsif options[:password_regexp]
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @password_regexp = options[:password_regexp]
         
     | 
| 
      
 44 
     | 
    
         
            +
                else
         
     | 
| 
      
 45 
     | 
    
         
            +
                  # sudo on Mac OS X:
         
     | 
| 
      
 46 
     | 
    
         
            +
                  #   Password:
         
     | 
| 
      
 47 
     | 
    
         
            +
                  # sudo on Red Hat, Debian, Ubuntu:
         
     | 
| 
      
 48 
     | 
    
         
            +
                  #   [sudo] password for <user>:
         
     | 
| 
      
 49 
     | 
    
         
            +
                  @password_regexp = /(Password: |\[sudo\] password for .*: )/
         
     | 
| 
       20 
50 
     | 
    
         
             
                end
         
     | 
| 
       21 
     | 
    
         
            -
                @password
         
     | 
| 
       22 
51 
     | 
    
         
             
              end
         
     | 
| 
       23 
52 
     | 
    
         | 
| 
       24 
53 
     | 
    
         
             
              def ssh_execute(cmd, target)
         
     | 
| 
         @@ -31,9 +60,9 @@ class SSHwrap::Main 
     | 
|
| 
       31 
60 
     | 
    
         
             
                  params[:keys] = [@ssh_key]
         
     | 
| 
       32 
61 
     | 
    
         
             
                end
         
     | 
| 
       33 
62 
     | 
    
         
             
                using_password = false
         
     | 
| 
       34 
     | 
    
         
            -
                if @ 
     | 
| 
      
 63 
     | 
    
         
            +
                if @prompter.passwords[@ssh_prompt]
         
     | 
| 
       35 
64 
     | 
    
         
             
                  using_password = true
         
     | 
| 
       36 
     | 
    
         
            -
                  params[:password] = @ 
     | 
| 
      
 65 
     | 
    
         
            +
                  params[:password] = @prompter.passwords[@ssh_prompt]
         
     | 
| 
       37 
66 
     | 
    
         
             
                end
         
     | 
| 
       38 
67 
     | 
    
         | 
| 
       39 
68 
     | 
    
         
             
                begin
         
     | 
| 
         @@ -63,9 +92,9 @@ class SSHwrap::Main 
     | 
|
| 
       63 
92 
     | 
    
         
             
                        # if it's a password prompt, and interactively return data if so
         
     | 
| 
       64 
93 
     | 
    
         
             
                        # (see request_pty above).
         
     | 
| 
       65 
94 
     | 
    
         
             
                        channel.on_data do |ch_data, data|
         
     | 
| 
       66 
     | 
    
         
            -
                           
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                            channel.send_data "#{ 
     | 
| 
      
 95 
     | 
    
         
            +
                          if data =~ @password_regexp
         
     | 
| 
      
 96 
     | 
    
         
            +
                            prompt = $1
         
     | 
| 
      
 97 
     | 
    
         
            +
                            channel.send_data "#{@prompter.prompt(prompt)}\n"
         
     | 
| 
       69 
98 
     | 
    
         
             
                          else
         
     | 
| 
       70 
99 
     | 
    
         
             
                            stdout << data unless (data.nil? or data.empty?)
         
     | 
| 
       71 
100 
     | 
    
         
             
                          end
         
     | 
| 
         @@ -85,7 +114,7 @@ class SSHwrap::Main 
     | 
|
| 
       85 
114 
     | 
    
         
             
                  end
         
     | 
| 
       86 
115 
     | 
    
         
             
                rescue Net::SSH::AuthenticationFailed
         
     | 
| 
       87 
116 
     | 
    
         
             
                  if !using_password
         
     | 
| 
       88 
     | 
    
         
            -
                     
     | 
| 
      
 117 
     | 
    
         
            +
                    @prompter.prompt(@ssh_prompt)
         
     | 
| 
       89 
118 
     | 
    
         
             
                    return ssh_execute(cmd, target)
         
     | 
| 
       90 
119 
     | 
    
         
             
                  else
         
     | 
| 
       91 
120 
     | 
    
         
             
                    stderr << "Authentication failed to #{target}"
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class SSHwrap::Prompter
         
     | 
| 
      
 2 
     | 
    
         
            +
              attr_reader :passwords
         
     | 
| 
      
 3 
     | 
    
         
            +
              def initialize
         
     | 
| 
      
 4 
     | 
    
         
            +
                @mutex = Mutex.new
         
     | 
| 
      
 5 
     | 
    
         
            +
                @passwords = {}
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
              def prompt(prompt, echo=false)
         
     | 
| 
      
 8 
     | 
    
         
            +
                @mutex.synchronize do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  if !@passwords[prompt]
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @passwords[prompt] = ask(prompt) { |q| q.echo = echo }
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
                @passwords[prompt]
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/sshwrap/version.rb
    CHANGED
    
    
    
        data/sshwrap.gemspec
    CHANGED
    
    | 
         @@ -4,7 +4,7 @@ require File.expand_path('../lib/sshwrap/version', __FILE__) 
     | 
|
| 
       4 
4 
     | 
    
         
             
            Gem::Specification.new do |gem|
         
     | 
| 
       5 
5 
     | 
    
         
             
              gem.authors       = ['Jason Heiss']
         
     | 
| 
       6 
6 
     | 
    
         
             
              gem.email         = ['jheiss@aput.net']
         
     | 
| 
       7 
     | 
    
         
            -
              gem.description   = 'This provides a wrapper for ssh that execute a command on multiple machines, optionally in parallel, and handles any sudo prompts that result.'
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem.description   = 'This provides a wrapper for ssh that execute a command on multiple machines, optionally in parallel, and handles any ssh and sudo password prompts that result.'
         
     | 
| 
       8 
8 
     | 
    
         
             
              gem.summary       = 'Perform batch SSH operations, handling sudo prompts'
         
     | 
| 
       9 
9 
     | 
    
         
             
              gem.homepage      = 'https://github.com/jheiss/sshwrap'
         
     | 
| 
       10 
10 
     | 
    
         | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: sshwrap
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.0.3
         
     | 
| 
       5 
5 
     | 
    
         
             
              prerelease: 
         
     | 
| 
       6 
6 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       7 
7 
     | 
    
         
             
            authors:
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2013-03- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2013-03-14 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: net-ssh
         
     | 
| 
         @@ -44,7 +44,7 @@ dependencies: 
     | 
|
| 
       44 
44 
     | 
    
         
             
                  - !ruby/object:Gem::Version
         
     | 
| 
       45 
45 
     | 
    
         
             
                    version: '0'
         
     | 
| 
       46 
46 
     | 
    
         
             
            description: This provides a wrapper for ssh that execute a command on multiple machines,
         
     | 
| 
       47 
     | 
    
         
            -
              optionally in parallel, and handles any sudo prompts that result.
         
     | 
| 
      
 47 
     | 
    
         
            +
              optionally in parallel, and handles any ssh and sudo password prompts that result.
         
     | 
| 
       48 
48 
     | 
    
         
             
            email:
         
     | 
| 
       49 
49 
     | 
    
         
             
            - jheiss@aput.net
         
     | 
| 
       50 
50 
     | 
    
         
             
            executables:
         
     | 
| 
         @@ -61,6 +61,7 @@ files: 
     | 
|
| 
       61 
61 
     | 
    
         
             
            - bin/sshwrap
         
     | 
| 
       62 
62 
     | 
    
         
             
            - lib/sshwrap.rb
         
     | 
| 
       63 
63 
     | 
    
         
             
            - lib/sshwrap/main.rb
         
     | 
| 
      
 64 
     | 
    
         
            +
            - lib/sshwrap/prompter.rb
         
     | 
| 
       64 
65 
     | 
    
         
             
            - lib/sshwrap/version.rb
         
     | 
| 
       65 
66 
     | 
    
         
             
            - sshwrap.gemspec
         
     | 
| 
       66 
67 
     | 
    
         
             
            - test/test_options.rb
         
     |