added ssh library
This commit is contained in:
parent
72b15af79f
commit
8c0359ed4c
4
Rakefile
4
Rakefile
|
@ -11,7 +11,7 @@ begin
|
||||||
gem.homepage = "http://github.com/ngauthier/hydra"
|
gem.homepage = "http://github.com/ngauthier/hydra"
|
||||||
gem.authors = ["Nick Gauthier"]
|
gem.authors = ["Nick Gauthier"]
|
||||||
gem.add_development_dependency "shoulda", "= 2.10.3"
|
gem.add_development_dependency "shoulda", "= 2.10.3"
|
||||||
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
gem.add_dependency "net-ssh", "= 2.0.19"
|
||||||
end
|
end
|
||||||
Jeweler::GemcutterTasks.new
|
Jeweler::GemcutterTasks.new
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
|
@ -34,7 +34,7 @@ begin
|
||||||
end
|
end
|
||||||
rescue LoadError
|
rescue LoadError
|
||||||
task :rcov do
|
task :rcov do
|
||||||
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
abort "RCov is not available. In order to run rcov, you must: gem install rcov"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
# Generated by jeweler
|
||||||
|
# DO NOT EDIT THIS FILE DIRECTLY
|
||||||
|
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
|
||||||
|
Gem::Specification.new do |s|
|
||||||
|
s.name = %q{hydra}
|
||||||
|
s.version = "0.0.0"
|
||||||
|
|
||||||
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||||
|
s.authors = ["Nick Gauthier"]
|
||||||
|
s.date = %q{2010-01-26}
|
||||||
|
s.description = %q{TODO: longer description of your gem}
|
||||||
|
s.email = %q{nick@smartlogicsolutions.com}
|
||||||
|
s.extra_rdoc_files = [
|
||||||
|
"LICENSE",
|
||||||
|
"README.rdoc"
|
||||||
|
]
|
||||||
|
s.files = [
|
||||||
|
".document",
|
||||||
|
".gitignore",
|
||||||
|
"LICENSE",
|
||||||
|
"README.rdoc",
|
||||||
|
"Rakefile",
|
||||||
|
"VERSION",
|
||||||
|
"lib/hydra.rb",
|
||||||
|
"lib/hydra/pipe.rb",
|
||||||
|
"lib/hydra/ssh.rb",
|
||||||
|
"test/echo_the_dolphin.rb",
|
||||||
|
"test/helper.rb",
|
||||||
|
"test/test_pipe.rb",
|
||||||
|
"test/test_ssh.rb"
|
||||||
|
]
|
||||||
|
s.homepage = %q{http://github.com/ngauthier/hydra}
|
||||||
|
s.rdoc_options = ["--charset=UTF-8"]
|
||||||
|
s.require_paths = ["lib"]
|
||||||
|
s.rubygems_version = %q{1.3.5}
|
||||||
|
s.summary = %q{Distributed testing toolkit}
|
||||||
|
s.test_files = [
|
||||||
|
"test/test_ssh.rb",
|
||||||
|
"test/helper.rb",
|
||||||
|
"test/test_pipe.rb",
|
||||||
|
"test/echo_the_dolphin.rb"
|
||||||
|
]
|
||||||
|
|
||||||
|
if s.respond_to? :specification_version then
|
||||||
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||||
|
s.specification_version = 3
|
||||||
|
|
||||||
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||||
|
s.add_development_dependency(%q<shoulda>, ["= 2.10.3"])
|
||||||
|
s.add_runtime_dependency(%q<net-ssh>, ["= 2.0.19"])
|
||||||
|
else
|
||||||
|
s.add_dependency(%q<shoulda>, ["= 2.10.3"])
|
||||||
|
s.add_dependency(%q<net-ssh>, ["= 2.0.19"])
|
||||||
|
end
|
||||||
|
else
|
||||||
|
s.add_dependency(%q<shoulda>, ["= 2.10.3"])
|
||||||
|
s.add_dependency(%q<net-ssh>, ["= 2.0.19"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
require 'hydra/pipe'
|
require 'hydra/pipe'
|
||||||
|
require 'hydra/ssh'
|
||||||
|
|
|
@ -16,8 +16,13 @@ module Hydra #:nodoc:
|
||||||
#
|
#
|
||||||
# A pipe is actually two pipes:
|
# A pipe is actually two pipes:
|
||||||
#
|
#
|
||||||
# Parent === Pipe 1 ==> Child
|
# Parent == Pipe 1 ==> Child
|
||||||
# Parent <== Pipe 2 === Child
|
# Parent <== Pipe 2 == Child
|
||||||
|
#
|
||||||
|
# It's like if you had two cardboard tubes and you were using
|
||||||
|
# them to drop balls with messages in them between processes.
|
||||||
|
# One tube is for sending from parent to child, and the other
|
||||||
|
# tube is for sending from child to parent.
|
||||||
class Pipe
|
class Pipe
|
||||||
# Creates a new uninitialized pipe pair.
|
# Creates a new uninitialized pipe pair.
|
||||||
def initialize
|
def initialize
|
||||||
|
@ -43,15 +48,6 @@ module Hydra #:nodoc:
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns true if there is nothing to read (right now). However it is
|
|
||||||
# not exactly eof, if the other side writes, this will return false.
|
|
||||||
#
|
|
||||||
# It's a good way to tell if there is anything to process right now,
|
|
||||||
# otherwise, you can sleep.
|
|
||||||
def eof?
|
|
||||||
@reader.eof?
|
|
||||||
end
|
|
||||||
|
|
||||||
# Identify this side of the pipe as the child.
|
# Identify this side of the pipe as the child.
|
||||||
def identify_as_child
|
def identify_as_child
|
||||||
@parent_write.close
|
@parent_write.close
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
require 'open3'
|
||||||
|
module Hydra #:nodoc:
|
||||||
|
# Read and write with an ssh connection. For example:
|
||||||
|
# @ssh = Hydra::SSH.new('nick@nite')
|
||||||
|
# @ssh.write("echo hi")
|
||||||
|
# puts @ssh.gets
|
||||||
|
# => hi
|
||||||
|
#
|
||||||
|
# You can also use this to launch an interactive process. For
|
||||||
|
# example:
|
||||||
|
# @ssh = Hydra::SSH.new('nick@nite')
|
||||||
|
# @ssh.write('irb')
|
||||||
|
# @ssh.write("5+3")
|
||||||
|
# @ssh.gets
|
||||||
|
# => "5+3\n" # because irb echoes commands
|
||||||
|
# @ssh.gets
|
||||||
|
# => "8" # the output from irb
|
||||||
|
class SSH
|
||||||
|
include Open3
|
||||||
|
|
||||||
|
# Initialize new SSH connection. The single parameters is passed
|
||||||
|
# directly to ssh for starting a connection. So you can do:
|
||||||
|
# Hydra::SSH.new('localhost')
|
||||||
|
# Hydra::SSH.new('user@server.com')
|
||||||
|
# Hydra::SSH.new('-p 3022 user@server.com')
|
||||||
|
# etc..
|
||||||
|
def initialize(connection_options)
|
||||||
|
@stdin, @stdout, @stderr = popen3("ssh #{connection_options}")
|
||||||
|
end
|
||||||
|
|
||||||
|
# Write a string to ssh. This method returns the string passed to
|
||||||
|
# ssh. Note that if you do not add a newline at the end, it adds
|
||||||
|
# one for you, and the modified string is returned
|
||||||
|
def write(str)
|
||||||
|
unless str =~ /\n$/
|
||||||
|
str += "\n"
|
||||||
|
end
|
||||||
|
@stdin.write(str)
|
||||||
|
return str
|
||||||
|
end
|
||||||
|
|
||||||
|
# Read a line from ssh. This call blocks when there is nothing
|
||||||
|
# to read.
|
||||||
|
def gets
|
||||||
|
@stdout.gets.chomp
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
# read lines from stdin
|
||||||
|
# echo each line back
|
||||||
|
# on EOF, quit nicely
|
||||||
|
|
||||||
|
$stdout.sync = true
|
||||||
|
|
||||||
|
while line = $stdin.gets
|
||||||
|
$stdout.write(line)
|
||||||
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
require 'helper'
|
require File.join(File.dirname(__FILE__), 'helper')
|
||||||
|
|
||||||
class TestPipeDream < Test::Unit::TestCase
|
class TestPipe < Test::Unit::TestCase
|
||||||
context "a pipe" do
|
context "a pipe" do
|
||||||
setup do
|
setup do
|
||||||
@pipe = Hydra::Pipe.new
|
@pipe = Hydra::Pipe.new
|
||||||
|
@ -16,9 +16,7 @@ class TestPipeDream < Test::Unit::TestCase
|
||||||
@pipe.identify_as_parent
|
@pipe.identify_as_parent
|
||||||
@pipe.write "Test Message\n"
|
@pipe.write "Test Message\n"
|
||||||
assert_equal "Message Received\n", @pipe.gets
|
assert_equal "Message Received\n", @pipe.gets
|
||||||
assert !@pipe.eof?
|
|
||||||
assert_equal "Second Message\n", @pipe.gets
|
assert_equal "Second Message\n", @pipe.gets
|
||||||
assert @pipe.eof?
|
|
||||||
assert_raise Hydra::PipeError::Broken do
|
assert_raise Hydra::PipeError::Broken do
|
||||||
@pipe.write "anybody home?"
|
@pipe.write "anybody home?"
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
require File.join(File.dirname(__FILE__), 'helper')
|
||||||
|
|
||||||
|
class TestSSH < Test::Unit::TestCase
|
||||||
|
context "an ssh connection" do
|
||||||
|
setup do
|
||||||
|
@ssh = Hydra::SSH.new('localhost')
|
||||||
|
end
|
||||||
|
should "be able to execute a command" do
|
||||||
|
@ssh.write "echo hi"
|
||||||
|
assert_equal "hi", @ssh.gets
|
||||||
|
end
|
||||||
|
should "be able to execute a command with a newline" do
|
||||||
|
@ssh.write "echo hi\n"
|
||||||
|
assert_equal "hi", @ssh.gets
|
||||||
|
end
|
||||||
|
should "be able to communicate with a process" do
|
||||||
|
pwd = File.dirname(__FILE__)
|
||||||
|
echo_the_dolphin = File.expand_path(
|
||||||
|
File.join(File.dirname(__FILE__), 'echo_the_dolphin.rb')
|
||||||
|
)
|
||||||
|
@ssh.write('ruby -e "puts \'Hello\'"')
|
||||||
|
assert_equal "Hello", @ssh.gets
|
||||||
|
|
||||||
|
@ssh.write("ruby #{echo_the_dolphin}")
|
||||||
|
@ssh.write("Hello Echo!")
|
||||||
|
assert_equal "Hello Echo!", @ssh.gets
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue