ssh wrong number of arguments - ruby

Referencing the net-ssh API, what's the "best" way to pass connection parameters which come from a yaml?
error:
thufir#dur:~/ruby$
thufir#dur:~/ruby$ ruby ssh.rb
{:host=>"localhost", :user=>"me", :port=>123, :password=>"mypassword"}
/home/thufir/.rvm/gems/ruby-2.0.0-p247/gems/net-ssh-2.6.8/lib/net/ssh.rb:165:in `start': wrong number of arguments (1 for 2..3) (ArgumentError)
from ssh.rb:14:in `<main>'
thufir#dur:~/ruby$
code:
#!/usr/bin/env ruby
require 'rubygems'
require 'net/ssh'
require 'yaml'
require 'pry'
conn = YAML.load_file('conn.yml')
params = {:host => conn['host'], :user => conn['user'],
:port => conn['port'],:password => conn['password']}
puts params
Net::SSH.start(params) do |ssh|
puts 'hi'
end
yaml:
user: me
password: mypassword
port: 123
host: localhost
is it possible to just pass one monolithic object? Or, do you have to break it up into host, user, et. al.?

The host and user arguments must be specified as positional arguments, not as part of the options hash. Thus:
Net::SSH.start(conn['host'], conn['user'], port: conn['port'], password: conn['password']) do |ssh|
# ...
end
Or you can just pass through all the YAML key-value pairs directly:
Net::SSH.start(conn.delete('host'), conn.delete('user'), conn) do |ssh|
# ...
end

Related

Rspec for ssh connection

I am trying to write rspec to test ssh connection. In my spec file even though I have enetered incorrect server password it still says 0 examples, 0 failures. Can someone exmplain me why am I seeing that whereas I am expected to see at least one failure message.
Below is the piece of code of my ssh_host.rb and ssh_host_spec.rb files.
require "java"
require "highline/import"
require 'open-uri'
require 'socket'
require 'rubygems'
require 'net/ssh'
require 'stringio'
require 'net/scp'
require 'colorize'
module SshMod
class SshHost
attr_accessor :hostname, :username, :password
def initialize(host, user, password)
#hostname = host
#username = user
#password = password
#ssh = Net::SSH.start(#hostname, #username, :password => #password)
puts "\t Connection established for #{#hostname}...".blue
end
end
end
Rspec Class:
#!/usr/bin/env rspec
require 'spec_helper'
require 'ssh_host.rb'
describe SshMod::SshHost do
before :each do
#ssh = SshMod::SshHost.new "servername", "user", "wrong_password"
end
end
describe "#new" do
it "takes three parameters and returns sshhostobject" do
#ssh.should_be_an_instance_of SshHost
end
end
ssh_mock = double()
expect(SSH).to receive(:start).and_return(ssh_mock)
There are a number of things wrong with your spec file. your test for new should be within the context of your SshMod::SshHost describe otherwise it doesn't have access to the ssh instance variable. Also, your code should throw some errors because except isn't defined in Kernel it's within the context of an Rspec object. You most likely want to put it in your before.
Regarding your requires in your ruby class, I'd get rid of everything that you don't need (for example, why the explicit inclusion of socket when using net-ssh?).
I believe however, that you're running into the issue where no tests are running most likely due to your project structure (but that's only a guess since you haven't listed it). Rspec by default looks for spec files listed under spec/**/*_spec.rb which you can override with the --pattern flag. See rspec --help for more info.
Here's a working example of your code with a bunch of things cleaned up. I put the source of your code in lib assuming you're making something like a gem.
Gemfile:
source "https://rubygems.org"
gem "colorize"
gem "rspec"
gem "net-ssh"
lib/ssh_host.rb
require 'net/ssh'
require 'colorize'
module SshMod
class SshHost
attr_accessor :hostname, :username, :password
def initialize(host, user, password)
#hostname = host
#username = user
#password = password
#ssh = Net::SSH.start(#hostname, #username, password: #password)
puts "\t Connection established for #{#hostname}...".blue
end
end
end
spec/spec_helper.rb
$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
require 'rspec'
RSpec.configure do |config|
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
end
spec/ssh_host_spec.rb
require 'spec_helper'
require 'ssh_host'
describe SshMod::SshHost do
let (:ssh) { SshMod::SshHost.new "servername", "user", "wrong_password" }
before :each do
allow(Net::SSH).to receive(:start).and_return(double("connection"))
end
describe "#new" do
it "takes three parameters and returns sshhostobject" do
expect(ssh).to be_a SshMod::SshHost
end
end
end

Error using gem net/ssh <= Net::SSH::AuthenticationFailed

While using the gem net/ssh I'm getting the error:
/usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.23/lib/net/ssh.rb:192:in
`start': Net::SSH::AuthenticationFailed (Net::SSH::AuthenticationFailed)
I don't really understand what's going on..? I've done my research and discovered this but it doesn't really answer my question..
Is there a specific reason why the authentication is failing? All I'm doing is sshing to different servers, is there something specific I need to change?
Source:
require 'rubygems'
require 'net/ssh'
require 'etc'
print "Enter password: "
system "stty -echo"
#password = gets.chomp
system "stty echo"
def logged_in(server)
cmd = `who`.gsub(/[ \t].*/,"").gsub(/\A.*\n/,'')
check = Net::SSH.start(#host, #username, :password => #password) do |ssh|
ssh.exec!(cmd)
end
end
#host = %w(server_names_here) do |server|
logged_in(server)
end
#username = Etc.getlogin
I thought it might be the wrong password so I tried entering the password with the echo "on" and I am entering the correct password, I also thought maybe it's not pulling my username so I used: #username = 'my_username' I am still receiving the same error
Edit:
Found the problem, it had to do with where the #username was placed
The problem had to do with where #username was placed.
require 'rubygems'
require 'net/ssh'
require 'etc'
print "Enter password: "
system "stty -echo"
#password = gets.chomp
system "stty echo"
#username = Etc.getlogin #<= YAY!
def logged_in(server)
cmd = `who`.gsub(/[ \t].*/,"").gsub(/\A.*\n/,'')
check = Net::SSH.start(#host, #username, :password => #password) do |ssh|
ssh.exec!(cmd)
end
end
#host = %w(server_names_here) do |server|
logged_in(server)
end

AuthenticationFailed net-ssh ruby

When I'm trying to Net::SSH.start to my debian ssh server and transfer a files, every time I've a very strange error message - `start': Net::SSH::AuthenticationFailed, but all the authentication data are correct, I don't know what a problem is. Does anyone faced same problem?
The code was written on ruby and net/ssh module are in use, here is a code:
require 'rubygems'
require 'net/ssh'
def copy_file(session, source_path, destination_path=nil)
destination_path ||= source_path
cmd = %{cat > "#{destination_path.gsub('"', '\"')}"}
session.process.popen3(cmd) do |i, o, e|
puts "Copying #{source_path} to #{destination_path}... "
open(source_path) { |f| i.write(f.read) }
puts 'Done.'
end
end
Net::SSH.start("192.168.112.129",
:username=>'username',
:password=>'password') do |session|
copy_file(session, 'D:/test/1.txt')
copy_file(session, '/home/timur/Documents/new_file.rb"')
end
There is no :username option in net/ssh 2.6, you can set it like parameter:
Net::SSH.start('192.168.112.129', 'username', password: 'password') do |ssh|
foo
end

Accessing variables from inside a block with Mail gem

I have a problem with accessing the content of some variables. I'm using the Mail gem and have the following code:
class Email
attr_accessor :server, :port, :username, :password, :ssl
def check_mail
# puts server ---> imap.googlemail.com ---> work
Mail.defaults do
# puts server ---> nil ---> not work
retriever_method :imap, address: server, #---> obviously not work
port: port,
user_name: username,
password: password,
enable_ssl: ssl
end
end
end
def account
acc = Email.new
acc.server = 'imap.googlemail.com'
acc.port = '993'
acc.username = 'xxx'
acc.password = 'xxx'
acc.ssl = 'true'
acc.check_mail
end
I can not access the variables from within Mail.default do, I guess it will be a class problem.
It's probable that the block Mail is given is executed in another context and the variables are not available in that scope. This sometimes happens in certain "Domain Specific Languages" (DSLs) written in Ruby.
You'll need to bridge over whatever data you want to use. This would be possible if you create a namespace for your configuration:
Mail.defaults do
retriever_method :...,
:address => MyModule.address,
# ...
end
Those modules can be easily created with mattr_accessor if you have that.
It might also be possible to use a sort of closure to achieve this:
this = self
Mail.defaults do
retriever_method :...,
:address => this.address,
# ...
end

Daemonizing Mailman app

Starting my mailman app by running rails runner lib/daemons/mailman_server.rb works fine.
When starting with my daemon script and command bundle exec rails runner script/daemon run mailman_server.rb, the script generates an error:
.rvm/gems/ruby-1.9.3-p194/gems/mailman-0.5.3/lib/mailman/route/conditions.rb:21:in `match': undefined method `each' for nil:NilClass (NoMethodError)
My code is as follows:
lib/daemons/mailman_server.rb
require 'mailman'
# Config Mailman
Mailman.config.ignore_stdin = false
Mailman.config.graceful_death = true
Mailman.config.poll_interval = 15
Mailman.config.logger = Logger.new File.expand_path("../../../log/mailman.log", __FILE__)
Mailman.config.pop3 = {
:username => 'alias#mygoogleapp.com',
:password => 'password',
:server => 'pop.gmail.com',
:port => 995,
:ssl => true
}
# Run the mailman
Mailman::Application.run do
from('%email%').to('alias+q%id%#mygoogleapp.com') do |email, id|
begin
# Get message without headers to pass to add_answer_from_email
if message.multipart?
reply = message.text_part.body.decoded
else
reply = message.body.decoded
end
# Call upon the question to add answer to his set
Question.find(id).add_answer_from_email(email, reply)
rescue Exception => e
Mailman.logger.error "Exception occured while receiving message:\n#{message}"
Mailman.logger.error [e, *e.backtrace].join("\n")
end
end
end
and my script/daemon file is:
#!/usr/bin/env ruby
require 'rubygems'
require "bundler/setup"
require 'daemons'
ENV["APP_ROOT"] ||= File.expand_path("#{File.dirname(__FILE__)}/..")
script = "#{ENV["APP_ROOT"]}/lib/daemons/#{ARGV[1]}"
Daemons.run(script, dir_mode: :normal, dir: "#{ENV["APP_ROOT"]}/tmp/pids")
Any insight as to why it fails as a daemon?

Resources