summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2012-11-01 01:08:04 -0700
committerelijah <elijah@riseup.net>2012-11-01 01:08:04 -0700
commite42be7b98bcf600d60f5bfb0b037f270ae74f2fa (patch)
treee3520013568990e3b0c1d32669081c1be330bec0
parent57287ae1d4151ec453ec9d33fafe4f1a4ced37e0 (diff)
more complete rsync compatibility with Net::SSH options
-rw-r--r--vendor/supply_drop/lib/supply_drop/rsync.rb133
1 files changed, 124 insertions, 9 deletions
diff --git a/vendor/supply_drop/lib/supply_drop/rsync.rb b/vendor/supply_drop/lib/supply_drop/rsync.rb
index 3030038..6d561ea 100644
--- a/vendor/supply_drop/lib/supply_drop/rsync.rb
+++ b/vendor/supply_drop/lib/supply_drop/rsync.rb
@@ -24,23 +24,138 @@ module SupplyDrop
next unless value
#
- # for a list of the options normally support by Net::SSH (and thus Capistrano), see
+ # Convert Net::SSH options into OpenSSH options.
+ #
+ # For a list of the options normally support by Net::SSH (and thus Capistrano), see
# http://net-ssh.github.com/net-ssh/classes/Net/SSH.html#method-c-start
#
+ # Also, to see how Net::SSH does the opposite of the conversion we are doing here, check out:
+ # https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/config.rb
+ #
+ # API mismatch:
+ #
+ # * many OpenSSH options not supported
+ # * some options only make sense for Net::SSH
+ # * compression: for Net::SSH, this option is supposed to accept true, false, or algorithm. OpenSSH accepts 'yes' or 'no'
+ #
+ #
case key
- when :keys then [value].flatten.select { |k| File.exist?(k) }.map { |k| "-i #{k}" }
- when :config then "-F #{value}"
- when :port then "-p #{value}"
- when :user_known_hosts_file then "-o 'UserKnownHostsFile=#{value}'"
- when :global_known_hosts_file then "-o 'GlobalKnownHostsFile=#{value}'"
- when :host_key_alias then "-o 'HostKeyAlias=#{value}'"
- when :paranoid then "-o 'StrictHostKeyChecking=yes'"
- when :host_name then "-o 'HostName=#{value}'"
+ when :auth_methods then opt_auth_methods(value)
+ when :bind_address then opt('BindAddress', value)
+ when :compression then opt('Compression', value ? 'yes' : 'no')
+ when :compression_level then opt('CompressionLevel', value.to_i)
+ when :config then "-F '#{value}'"
+ when :encryption then opt('Ciphers', [value].flatten.join(','))
+ when :forward_agent then opt('ForwardAgent', value)
+ when :global_known_hosts_file then opt('GlobalKnownHostsFile', value)
+ when :hmac then opt('MACs', [value].flatten.join(','))
+ when :host_key then opt('HostKeyAlgorithms', [value].flatten.join(','))
+ when :host_key_alias then opt('HostKeyAlias', value)
+ when :host_name then opt('HostName', value)
+ when :kex then opt('KexAlgorithms', [value].flatten.join(','))
+ when :key_data then nil # not supported
+ when :keys then [value].flatten.select { |k| File.exist?(k) }.map { |k| "-i #{k}" }
+ when :keys_only then opt('IdentitiesOnly', value ? 'yes' : 'no')
+ when :languages then nil # not applicable
+ when :logger then nil # not applicable
+ when :paranoid then opt('StrictHostKeyChecking', value ? 'yes' : 'no')
+ when :passphrase then nil # not supported
+ when :password then nil # not supported
+ when :port then "-p #{value.to_i}"
+ when :properties then nil # not applicable
+ when :proxy then nil # not applicable
+ when :rekey_blocks_limit then nil # not supported
+ when :rekey_limit then opt('RekeyLimit', reverse_interpret_size(value))
+ when :rekey_packet_limit then nil # not supported
+ when :timeout then opt('ConnectTimeout', value.to_i)
+ when :user then "-l #{value}"
+ when :user_known_hosts_file then opt('UserKnownHostsFile', value)
+ when :verbose then opt('LogLevel', interpret_log_level(value))
end
end.compact
%[-e "ssh #{mapped_options.join(' ')}"] unless mapped_options.empty?
end
+
+ private
+
+ def opt(option_name, option_value)
+ "-o #{option_name}='#{option_value}'"
+ end
+
+ #
+ # In OpenSSH, password and pubkey default to 'yes', hostbased defaults to 'no'.
+ # Regardless, if :auth_method is configured, then we explicitly set the auth method.
+ #
+ def opt_auth_methods(value)
+ value = [value].flatten
+ opts = []
+ if value.any?
+ if value.include? 'password'
+ opts << opt('PasswordAuthentication', 'yes')
+ else
+ opts << opt('PasswordAuthentication', 'no')
+ end
+ if value.include? 'publickey'
+ opts << opt('PubkeyAuthentication', 'yes')
+ else
+ opts << opt('PubkeyAuthentication', 'no')
+ end
+ if value.include? 'hostbased'
+ opts << opt('HostbasedAuthentication', 'yes')
+ else
+ opts << opt('HostbasedAuthentication', 'no')
+ end
+ end
+ if opts.any?
+ return opts.join(' ')
+ else
+ nil
+ end
+ end
+
+ #
+ # Converts the given integer size in bytes into a string with 'K', 'M', 'G' suffix, as appropriate.
+ #
+ # reverse of interpret_size in https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/config.rb
+ #
+ def reverse_interpret_size(size)
+ size = size.to_i
+ if size < 1024
+ "#{size}"
+ elsif size < 1024 * 1024
+ "#{size/1024}K"
+ elsif size < 1024 * 1024 * 1024
+ "#{size/(1024*1024)}M"
+ else
+ "#{size/(1024*1024*1024)}G"
+ end
+ end
+
+ def interpret_log_level(level)
+ if level.is_a? Symbol
+ case level
+ when :debug then "DEBUG"
+ when :info then "INFO"
+ when :warn then "ERROR"
+ when :error then "ERROR"
+ when :fatal then "FATAL"
+ else "INFO"
+ end
+ elsif level.is_a? Integer
+ case level
+ when Logger::DEBUG then "DEBUG"
+ when Logger::INFO then "INFO"
+ when Logger::WARN then "ERROR"
+ when Logger::ERROR then "ERROR"
+ when Logger::FATAL then "FATAL"
+ else "INFO"
+ end
+ else
+ "INFO"
+ end
+ end
+
end
end
end