remote_executor 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +8 -7
- data/bin/remote_executor +11 -11
- data/lib/remote_executor.rb +2 -8
- data/lib/remote_executor/app.rb +5 -0
- data/lib/remote_executor/cli.rb +7 -12
- data/lib/remote_executor/config.rb +39 -20
- data/lib/remote_executor/options_parser.rb +4 -7
- data/lib/remote_executor/system.rb +4 -9
- data/lib/remote_executor/system_config.rb +9 -5
- data/lib/remote_executor/version.rb +8 -7
- data/test/unit/tc_cli.rb +18 -0
- data/test/unit/tc_config.rb +44 -0
- data/test/unit/tc_system.rb +35 -0
- data/test/unit/tc_system_config.rb +35 -0
- data/test/unit/ts_all.rb +24 -0
- metadata +24 -10
data/README.rdoc
CHANGED
@@ -24,17 +24,15 @@ An example may be the next. Launch the command 'hostname' over your production f
|
|
24
24
|
directory into the file ${HOME}/.remoteexecutorrc like this:
|
25
25
|
|
26
26
|
---
|
27
|
-
- :name: 'myFarm'
|
28
|
-
:
|
29
|
-
:user: admin
|
27
|
+
- :name: 'myFarm.development'
|
28
|
+
:user: 'admin'
|
30
29
|
:hosts:
|
31
30
|
- 'myHost1'
|
32
31
|
- 'myHost2'
|
33
32
|
- 'myHost3'
|
34
33
|
- 'myHost4'
|
35
|
-
- :name: 'myFarm'
|
36
|
-
:
|
37
|
-
:user: admin
|
34
|
+
- :name: 'myFarm.production'
|
35
|
+
:user: 'admin'
|
38
36
|
:hosts:
|
39
37
|
- 'myHost1'
|
40
38
|
- 'myHost2'
|
@@ -45,10 +43,13 @@ you need this minimal SSH configuration (${HOME}/.ssh/config) for the example
|
|
45
43
|
|
46
44
|
Host myHost1
|
47
45
|
HostName myhost1.example.com
|
46
|
+
|
48
47
|
Host myHost2
|
49
48
|
HostName myhost2.example.com
|
49
|
+
|
50
50
|
Host myHost3
|
51
51
|
HostName myhost3.example.com
|
52
|
+
|
52
53
|
Host myHost4
|
53
54
|
HostName myhost4.example.com
|
54
55
|
|
@@ -57,7 +58,7 @@ you need this minimal SSH configuration (${HOME}/.ssh/config) for the example
|
|
57
58
|
|
58
59
|
with this line:
|
59
60
|
|
60
|
-
remote_executor --system=
|
61
|
+
remote_executor --system=myFarmID --command='hostname'
|
61
62
|
|
62
63
|
|
63
64
|
=== Configuration
|
data/bin/remote_executor
CHANGED
@@ -5,19 +5,19 @@ $:.unshift File.join( File.dirname( __FILE__ ), %w[.. lib] )
|
|
5
5
|
require 'rubygems'
|
6
6
|
require 'remote_executor'
|
7
7
|
|
8
|
-
module
|
8
|
+
module RemoteExecutor
|
9
|
+
module CLIApplication
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
11
|
+
def self.run
|
12
|
+
Cli::execute(
|
13
|
+
Choice.choices[:system],
|
14
|
+
Choice.choices[:environment],
|
15
|
+
Choice.choices[:command]
|
16
|
+
)
|
17
|
+
end
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
21
|
##
|
22
22
|
# ::Main::
|
23
|
-
CLIApplication.
|
23
|
+
RemoteExecutor::CLIApplication.run
|
data/lib/remote_executor.rb
CHANGED
@@ -1,13 +1,7 @@
|
|
1
|
-
|
2
|
-
%w[rubygems yaml singleton choice net/ssh].each { |gem| require gem }
|
3
|
-
rescue LoadError => e
|
4
|
-
fail "Some gem dependencies can not be loaded: #{e.message}"
|
5
|
-
end
|
6
|
-
|
7
|
-
$:.unshift File.join( File.dirname( __FILE__), 'remote_executor' )
|
1
|
+
$:.unshift File.join( File.dirname( __FILE__ ), 'remote_executor' )
|
8
2
|
|
9
3
|
begin
|
10
|
-
%w[version config system_config system
|
4
|
+
%w[version app options_parser cli config system_config system cli].each { |lib| require lib }
|
11
5
|
rescue LoadError => e
|
12
6
|
fail "Some lib dependencies can not be loaded: #{e.message}"
|
13
7
|
end
|
data/lib/remote_executor/cli.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require 'rubygems'
|
2
|
+
require 'net/ssh'
|
3
|
+
|
4
|
+
|
5
|
+
module RemoteExecutor
|
6
6
|
class Cli
|
7
7
|
|
8
8
|
DEFAULT_SSH_OPTIONS = { :config=>true }
|
@@ -11,14 +11,9 @@ module RemoteExecutor
|
|
11
11
|
|
12
12
|
system = System.new( SystemConfig.instance.find_system( name ) )
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
system.hosts.each do |host|
|
14
|
+
system.hosts.each do |host|
|
17
15
|
|
18
|
-
|
19
|
-
end
|
20
|
-
else
|
21
|
-
raise BadEnvironment.new( "Bad environment: '#{system.environment}' for target: '#{system.name}'..." )
|
16
|
+
Net::SSH.start( host, system.user, ssh_options ) { |ssh| ssh.exec( "#{command}" ) }
|
22
17
|
end
|
23
18
|
end
|
24
19
|
end
|
@@ -1,34 +1,53 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'choice'
|
3
|
+
require 'yaml'
|
4
|
+
require 'app'
|
5
|
+
|
6
|
+
|
1
7
|
module RemoteExecutor
|
2
8
|
|
3
9
|
class YAMLFileNotFound < Exception
|
4
10
|
end
|
11
|
+
|
12
|
+
class ConfigurationNotLoaded < Exception
|
13
|
+
end
|
14
|
+
|
15
|
+
class ConfigurationError < Exception
|
16
|
+
end
|
5
17
|
|
6
18
|
class Config
|
7
|
-
|
8
|
-
|
9
|
-
# Get the default configuration over Choice, environment and user default settings
|
10
|
-
def self.get_config_file( config_key )
|
19
|
+
|
20
|
+
def load_config( config_file )
|
11
21
|
|
12
|
-
|
13
|
-
|
14
|
-
|
22
|
+
@config = YAML.load_file( config_file )
|
23
|
+
rescue Exception => e
|
24
|
+
raise YAMLFileNotFound.new( e.message )
|
25
|
+
end
|
15
26
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
27
|
+
public
|
28
|
+
def initialize
|
19
29
|
|
20
|
-
|
30
|
+
cli_cfn = Choice.choices[:config]
|
31
|
+
if( cli_cfn )
|
32
|
+
|
33
|
+
load_config( cli_cfn )
|
34
|
+
else
|
35
|
+
environment_cfn = ENV[CLIApplication::NAME.upcase]
|
21
36
|
|
22
|
-
|
37
|
+
if( environment_cfn && '' != environment_cfn )
|
38
|
+
|
39
|
+
load_config( environment_cfn )
|
40
|
+
else
|
41
|
+
user_cfn = "#{ENV['HOME']}/.#{CLIApplication::NAME.downcase}rc"
|
42
|
+
|
43
|
+
if( user_cfn && '' != user_cfn && File.exist?( user_cfn ) )
|
44
|
+
|
45
|
+
load_config( user_cfn )
|
46
|
+
else
|
47
|
+
raise ConfigurationNotLoaded.new( "Configuration not loaded" )
|
48
|
+
end
|
49
|
+
end
|
23
50
|
end
|
24
|
-
|
25
|
-
raise YAMLFileNotFound.new( "Configuration not found" )
|
26
51
|
end
|
27
|
-
|
28
|
-
def initialize()
|
29
|
-
@config = YAML.load_file( Config.get_config_file( CLIApplication::NAME ) )
|
30
|
-
rescue Exception => e
|
31
|
-
raise YAMLFileNotFound.new( e.message )
|
32
|
-
end
|
33
52
|
end
|
34
53
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'choice'
|
3
|
+
|
4
|
+
|
1
5
|
module RemoteExecutor
|
2
6
|
Choice.options do
|
3
7
|
header ''
|
@@ -9,13 +13,6 @@ module RemoteExecutor
|
|
9
13
|
desc 'The YAML config file'
|
10
14
|
end
|
11
15
|
|
12
|
-
option :environment, :required=>true do
|
13
|
-
short '-e'
|
14
|
-
long '--environment=value'
|
15
|
-
desc 'The Environment name'
|
16
|
-
valid %w[development preproduction production]
|
17
|
-
end
|
18
|
-
|
19
16
|
option :system, :required=>true do
|
20
17
|
short '-s'
|
21
18
|
long '--system=value'
|
@@ -1,20 +1,15 @@
|
|
1
|
-
module RemoteExecutor
|
2
|
-
|
3
|
-
class System < Struct.new( :name, :environment, :user, :hosts )
|
1
|
+
module RemoteExecutor
|
2
|
+
class System < Struct.new( :name, :user, :hosts )
|
4
3
|
|
5
|
-
public
|
6
4
|
def initialize( params )
|
7
5
|
|
8
6
|
unless params && params.class == Hash
|
9
7
|
fail "Bad parameters"
|
10
8
|
end
|
11
9
|
|
12
|
-
if( params[:name]
|
13
|
-
params[:environment] &&
|
14
|
-
params[:user] &&
|
15
|
-
params[:hosts] )
|
10
|
+
if( params[:name] && params[:user] && params[:hosts] )
|
16
11
|
|
17
|
-
super( params[:name], params[:
|
12
|
+
super( params[:name], params[:user], params[:hosts] )
|
18
13
|
self
|
19
14
|
end
|
20
15
|
end
|
@@ -1,16 +1,20 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'config'
|
3
|
+
|
4
|
+
|
1
5
|
module RemoteExecutor
|
2
6
|
|
3
|
-
class ConfigurationError < Exception
|
4
|
-
end
|
5
|
-
|
6
7
|
class SystemConfig < Config
|
7
8
|
include Singleton
|
8
9
|
|
9
10
|
def find_system( system_name )
|
10
11
|
|
11
|
-
@config.each
|
12
|
+
@config.each do |system|
|
13
|
+
|
14
|
+
return system if( system[:name] == system_name )
|
15
|
+
end
|
12
16
|
|
13
|
-
raise ConfigurationError.new( "System: '#{system_name}' not found
|
17
|
+
raise ConfigurationError.new( "System: '#{system_name}' not found" )
|
14
18
|
end
|
15
19
|
end
|
16
20
|
end
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module RemoteExecutor
|
2
2
|
module Version
|
3
3
|
|
4
|
-
MAJOR
|
5
|
-
MINOR
|
6
|
-
PATCH
|
7
|
-
|
8
|
-
STRING =
|
4
|
+
MAJOR = 0
|
5
|
+
MINOR = 6
|
6
|
+
PATCH = 0
|
7
|
+
|
8
|
+
STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
|
9
9
|
end
|
10
10
|
|
11
|
-
NAME
|
12
|
-
VERSION
|
11
|
+
NAME = 'remote_executor'
|
12
|
+
VERSION = Version::STRING
|
13
|
+
COMPLETE_NAME = "#{NAME}-#{VERSION}"
|
13
14
|
end
|
data/test/unit/tc_cli.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift File.join( File.dirname( __FILE__ ), %w[.. .. lib remote_executor] )
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'cli'
|
5
|
+
|
6
|
+
|
7
|
+
class TC_Cli < Test::Unit::TestCase
|
8
|
+
# def setup
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def teardown
|
12
|
+
# end
|
13
|
+
|
14
|
+
def test_execute
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
$:.unshift File.join( File.dirname( __FILE__ ), %w[.. .. lib remote_executor] )
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'config'
|
6
|
+
|
7
|
+
|
8
|
+
class TC_Config < Test::Unit::TestCase
|
9
|
+
|
10
|
+
def setup
|
11
|
+
@fixtures_file = '../fixtures/settings.yml'
|
12
|
+
@test_file = '/tmp/settings.yml'
|
13
|
+
@rc_file = "#{ENV['HOME']}/.#{RemoteExecutor::CLIApplication::NAME.downcase}rc"
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_initialize()
|
20
|
+
assert_raises( RemoteExecutor::YAMLFileNotFound ) { RemoteExecutor::Config.new( "AppFoo" ) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_initialize_environment
|
24
|
+
|
25
|
+
FileUtils.cp( @fixtures_file, @test_file )
|
26
|
+
ENV[RemoteExecutor::CLIApplication::NAME.upcase] = @test_file
|
27
|
+
|
28
|
+
assert_instance_of( RemoteExecutor::Config, RemoteExecutor::Config.new )
|
29
|
+
|
30
|
+
ENV[RemoteExecutor::CLIApplication::NAME.upcase] = ""
|
31
|
+
FileUtils.rm( @test_file )
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_initialize_rcfile
|
35
|
+
# File not found
|
36
|
+
assert_raises( RemoteExecutor::ConfigurationNotLoaded ) { RemoteExecutor::Config.new }
|
37
|
+
|
38
|
+
FileUtils.cp( @fixtures_file, @rc_file )
|
39
|
+
|
40
|
+
assert_instance_of( RemoteExecutor::Config, RemoteExecutor::Config.new )
|
41
|
+
|
42
|
+
FileUtils.remove( @rc_file )
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
$:.unshift File.join( File.dirname( __FILE__ ), %w[.. .. lib remote_executor] )
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'system'
|
5
|
+
|
6
|
+
|
7
|
+
class TC_System < Test::Unit::TestCase
|
8
|
+
|
9
|
+
TEST_SYSTEM_NAME = 'wi.pro'
|
10
|
+
TEST_SYSTEM_USER = 'root'
|
11
|
+
TEST_SYSTEM_HOSTS = [ 'lr1.wi.pro', 'lr2.wi.pro', 'alf1.wi.pro', 'alf2.wi.pro' ]
|
12
|
+
TEST_PARAMS = {
|
13
|
+
:name=>TEST_SYSTEM_NAME,
|
14
|
+
:user=>TEST_SYSTEM_USER,
|
15
|
+
:hosts=>TEST_SYSTEM_HOSTS
|
16
|
+
}
|
17
|
+
|
18
|
+
def setup
|
19
|
+
end
|
20
|
+
|
21
|
+
def teardown
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_initialize
|
25
|
+
assert_raise( RuntimeError) { RemoteExecutor::System.new( "foo" ) }
|
26
|
+
|
27
|
+
test_system = RemoteExecutor::System.new( TEST_PARAMS )
|
28
|
+
|
29
|
+
assert_instance_of( RemoteExecutor::System, test_system )
|
30
|
+
assert_equal( TEST_SYSTEM_NAME, test_system.name)
|
31
|
+
assert_equal( TEST_SYSTEM_USER, test_system.user )
|
32
|
+
assert_equal( TEST_SYSTEM_HOSTS, test_system.hosts )
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
$:.unshift File.join( File.dirname( __FILE__ ), %w[.. .. lib remote_executor] )
|
2
|
+
|
3
|
+
require 'test/unit'
|
4
|
+
require 'system_config'
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
|
8
|
+
class TC_SystemConfig < Test::Unit::TestCase
|
9
|
+
|
10
|
+
TEST_GOOD_SYSTEM_ID = 'wi.pro'
|
11
|
+
TEST_SYSTEM_USER = 'root'
|
12
|
+
TEST_SYSTEM_HOSTS = [ 'lr1.wi.pro', 'lr2.wi.pro', 'alf1.wi.pro', 'alf2.wi.pro' ]
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@fixtures_file = "../fixtures/settings.yml"
|
16
|
+
@test_file = "/tmp/settings.yml"
|
17
|
+
|
18
|
+
FileUtils.copy( @fixtures_file, @test_file )
|
19
|
+
ENV[RemoteExecutor::CLIApplication::NAME.upcase] = @test_file
|
20
|
+
@system_config = RemoteExecutor::SystemConfig.instance( @test_file )
|
21
|
+
end
|
22
|
+
|
23
|
+
def teardown
|
24
|
+
FileUtils.remove( @test_file )
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_find_system
|
28
|
+
|
29
|
+
assert_instance_of( Hash, @system_config.find_system( TEST_GOOD_SYSTEM_ID ))
|
30
|
+
assert_equal( TEST_GOOD_SYSTEM_ID, @system_config.find_system( TEST_GOOD_SYSTEM_ID )[:name] )
|
31
|
+
assert_equal( TEST_SYSTEM_USER, @system_config.find_system( TEST_GOOD_SYSTEM_ID )[:user] )
|
32
|
+
assert_equal( TEST_SYSTEM_HOSTS, @system_config.find_system( TEST_GOOD_SYSTEM_ID )[:hosts] )
|
33
|
+
assert_raise( RemoteExecutor::ConfigurationError ) { @system_config.find_system( 'fooSystem' ) }
|
34
|
+
end
|
35
|
+
end
|
data/test/unit/ts_all.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test/unit/testsuite'
|
2
|
+
require 'test/unit/ui/console/testrunner'
|
3
|
+
require 'tc_config'
|
4
|
+
require 'tc_system_config'
|
5
|
+
require 'tc_system'
|
6
|
+
require 'tc_cli'
|
7
|
+
|
8
|
+
|
9
|
+
class TS_RemoteExecutorTests
|
10
|
+
|
11
|
+
def self.suite
|
12
|
+
suite = Test::Unit::TestSuite.new
|
13
|
+
|
14
|
+
suite << TC_Config.suite
|
15
|
+
suite << TC_SystemConfig.suite
|
16
|
+
suite << TC_System.suite
|
17
|
+
suite << TC_Cli.suite
|
18
|
+
|
19
|
+
return suite
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
Test::Unit::UI::Console::TestRunner.run( TS_RemoteExecutorTests )
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: remote_executor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 6
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Javier Juarez
|
@@ -26,10 +26,12 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 27
|
30
30
|
segments:
|
31
31
|
- 0
|
32
|
-
|
32
|
+
- 1
|
33
|
+
- 0
|
34
|
+
version: 0.1.0
|
33
35
|
type: :runtime
|
34
36
|
version_requirements: *id001
|
35
37
|
- !ruby/object:Gem::Dependency
|
@@ -40,14 +42,16 @@ dependencies:
|
|
40
42
|
requirements:
|
41
43
|
- - ">="
|
42
44
|
- !ruby/object:Gem::Version
|
43
|
-
hash:
|
45
|
+
hash: 15
|
44
46
|
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
45
49
|
- 0
|
46
|
-
version:
|
50
|
+
version: 2.0.0
|
47
51
|
type: :runtime
|
48
52
|
version_requirements: *id002
|
49
53
|
description: A little remote command launcher over SSH connections
|
50
|
-
email: javier.
|
54
|
+
email: javier.juarez_AT_gmail_DOT_com
|
51
55
|
executables:
|
52
56
|
- remote_executor
|
53
57
|
extensions: []
|
@@ -57,6 +61,7 @@ extra_rdoc_files:
|
|
57
61
|
files:
|
58
62
|
- bin/remote_executor
|
59
63
|
- lib/remote_executor.rb
|
64
|
+
- lib/remote_executor/app.rb
|
60
65
|
- lib/remote_executor/cli.rb
|
61
66
|
- lib/remote_executor/config.rb
|
62
67
|
- lib/remote_executor/options_parser.rb
|
@@ -64,6 +69,11 @@ files:
|
|
64
69
|
- lib/remote_executor/system_config.rb
|
65
70
|
- lib/remote_executor/version.rb
|
66
71
|
- README.rdoc
|
72
|
+
- test/unit/tc_cli.rb
|
73
|
+
- test/unit/tc_config.rb
|
74
|
+
- test/unit/tc_system.rb
|
75
|
+
- test/unit/tc_system_config.rb
|
76
|
+
- test/unit/ts_all.rb
|
67
77
|
has_rdoc: true
|
68
78
|
homepage: http://github.com/jjuarez/remote_executor
|
69
79
|
licenses:
|
@@ -98,5 +108,9 @@ rubygems_version: 1.3.7
|
|
98
108
|
signing_key:
|
99
109
|
specification_version: 3
|
100
110
|
summary: A very simple gem that helps to launch remote commands over SSH connections
|
101
|
-
test_files:
|
102
|
-
|
111
|
+
test_files:
|
112
|
+
- test/unit/tc_cli.rb
|
113
|
+
- test/unit/tc_config.rb
|
114
|
+
- test/unit/tc_system.rb
|
115
|
+
- test/unit/tc_system_config.rb
|
116
|
+
- test/unit/ts_all.rb
|