elsewhere 0.5 → 0.6
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/README.md +4 -0
- data/elsewhere.gemspec +1 -1
- data/lib/elsewhere/remote_run.rb +74 -35
- data/lib/elsewhere/version.rb +1 -1
- data/tests/test_config.yml +10 -0
- data/tests/test_remote_run.rb +34 -0
- metadata +12 -10
data/README.md
CHANGED
|
@@ -13,8 +13,12 @@ r.commands << "source /etc/profile"
|
|
|
13
13
|
r.commands << "cd ~/current"
|
|
14
14
|
r.commands << "rake do:something:useful"
|
|
15
15
|
|
|
16
|
+
#fails silently
|
|
16
17
|
r.execute
|
|
17
18
|
|
|
19
|
+
#raises exception on nonzero status codes
|
|
20
|
+
r.execute!
|
|
21
|
+
|
|
18
22
|
=> { "www.example.com" => "results from data stream"}
|
|
19
23
|
```
|
|
20
24
|
|
data/elsewhere.gemspec
CHANGED
|
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
|
7
7
|
s.version = Elsewhere::VERSION
|
|
8
8
|
s.authors = ["Bill Chapman"]
|
|
9
9
|
s.email = ["bchapman@academicmanagement.com"]
|
|
10
|
-
s.homepage = ""
|
|
10
|
+
s.homepage = "https://github.com/byllc/elsewhere"
|
|
11
11
|
s.summary = %q{ Simple wrapper for Net SSH to run a list of commands remotely }
|
|
12
12
|
s.description = %q{ Yet another way to run stuff remotely }
|
|
13
13
|
|
data/lib/elsewhere/remote_run.rb
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
module Elsewhere
|
|
2
2
|
|
|
3
|
-
# Execute commands on a remote server
|
|
4
|
-
# I know capistrano already does this
|
|
5
|
-
# This was abstracted from a more specific solution that we already had in place and I thought it was worth sharing
|
|
6
|
-
#
|
|
7
|
-
# Usage:
|
|
8
|
-
#
|
|
9
|
-
# r = RemoteRun.new("hostname","username")
|
|
10
|
-
# r.commands << "source /etc/profile"
|
|
11
|
-
# r.commands << "cd ~/current"
|
|
12
|
-
# r.commands << "rake extractor:run cas=3 users=12550"
|
|
13
|
-
#
|
|
14
|
-
# r.execute
|
|
15
|
-
#
|
|
3
|
+
# Execute commands on a remote server
|
|
4
|
+
# I know capistrano already does this
|
|
5
|
+
# This was abstracted from a more specific solution that we already had in place and I thought it was worth sharing
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
#
|
|
9
|
+
# r = RemoteRun.new("hostname","username")
|
|
10
|
+
# r.commands << "source /etc/profile"
|
|
11
|
+
# r.commands << "cd ~/current"
|
|
12
|
+
# r.commands << "rake extractor:run cas=3 users=12550"
|
|
13
|
+
#
|
|
14
|
+
# r.execute
|
|
15
|
+
#
|
|
16
16
|
require 'net/ssh'
|
|
17
17
|
require 'net/ssh/gateway'
|
|
18
18
|
require 'yaml'
|
|
@@ -21,7 +21,7 @@ module Elsewhere
|
|
|
21
21
|
#TODO: move to remote_run/exceptions.rb when we gemify this
|
|
22
22
|
class RemoteRunError < StandardError; end
|
|
23
23
|
|
|
24
|
-
attr_accessor :hosts, :gateway_address, :gateway_user, :commands
|
|
24
|
+
attr_accessor :hosts, :user, :gateway_address, :gateway_user, :commands
|
|
25
25
|
|
|
26
26
|
def initialize(hosts,user, options={})
|
|
27
27
|
@hosts = [hosts].flatten #accept a single host or an array of hosts
|
|
@@ -31,6 +31,14 @@ module Elsewhere
|
|
|
31
31
|
@commands = []
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def add_command
|
|
35
|
+
@commands << command
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def remove_command command
|
|
39
|
+
@commands.delete(command.strip)
|
|
40
|
+
end
|
|
41
|
+
|
|
34
42
|
#expects the config file to be formatted as yaml as follows
|
|
35
43
|
#environment:
|
|
36
44
|
# group:
|
|
@@ -53,18 +61,23 @@ module Elsewhere
|
|
|
53
61
|
end
|
|
54
62
|
end
|
|
55
63
|
|
|
56
|
-
def ssh_wrapper(host,command)
|
|
64
|
+
def ssh_wrapper(host,command,raise_exceptions)
|
|
57
65
|
output = nil
|
|
58
66
|
Net::SSH.start(host, @user) do |ssh|
|
|
59
|
-
output = execute_over_ssh(ssh,command)
|
|
67
|
+
output = execute_over_ssh(ssh,command,raise_exceptions)
|
|
60
68
|
end
|
|
61
69
|
output
|
|
62
70
|
end
|
|
63
71
|
|
|
72
|
+
#run all items and raise an exception if exit_code is nonzero
|
|
73
|
+
def execute!(joined_by = " && ")
|
|
74
|
+
execute( joined_by, true )
|
|
75
|
+
end
|
|
76
|
+
|
|
64
77
|
# Run all of the items in the commands hash
|
|
65
78
|
# The joined_by paramenter dictates how to join the commands before execution
|
|
66
79
|
# Returns: A hash of the responses for each specified host
|
|
67
|
-
def execute(joined_by = " && ")
|
|
80
|
+
def execute(joined_by = " && ", raise_exceptions=false)
|
|
68
81
|
run_me = @commands.join(joined_by)
|
|
69
82
|
output = {}
|
|
70
83
|
|
|
@@ -72,30 +85,54 @@ module Elsewhere
|
|
|
72
85
|
gateway_wrapper.ssh(host, @user, {:forward_agent => true}) do |gateway|
|
|
73
86
|
@hosts.uniq.each do |h|
|
|
74
87
|
gateway.ssh(host, options[:gateway_user], {:forward_agent => true}) do |ssh|
|
|
75
|
-
output[h] = execute_over_ssh(ssh, run_me)
|
|
88
|
+
output[h] = execute_over_ssh(ssh, run_me,raise_exceptions)
|
|
76
89
|
end
|
|
77
90
|
end
|
|
78
91
|
end
|
|
79
92
|
else
|
|
80
|
-
@hosts.uniq.each{ |h| output[h] = ssh_wrapper(h,run_me) }
|
|
93
|
+
@hosts.uniq.each{ |h| output[h] = ssh_wrapper(h,run_me,raise_exceptions) }
|
|
81
94
|
end
|
|
82
95
|
|
|
83
96
|
return output
|
|
84
97
|
end
|
|
85
98
|
|
|
86
|
-
#execute the given
|
|
99
|
+
#execute the given command set for the Net::SSH instance
|
|
87
100
|
#return the data or raise an error depending on which stream is returned
|
|
88
|
-
def execute_over_ssh(ssh,command)
|
|
89
|
-
stdout
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
def execute_over_ssh(ssh,command,raise_exceptions)
|
|
102
|
+
stdout = ""
|
|
103
|
+
stderr = ""
|
|
104
|
+
exit_code = nil
|
|
105
|
+
channel = ssh.open_channel do |channel|
|
|
106
|
+
|
|
107
|
+
channel.exec(command) do |channel, success|
|
|
108
|
+
channel.on_data do |ch,data|
|
|
109
|
+
stdout = data
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
channel.on_extended_data do |ch, type, data|
|
|
113
|
+
stderr = data
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
channel.on_close do |ch|
|
|
117
|
+
#when channel closes
|
|
118
|
+
#TODO: Implement callback here
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
channel.on_request "exit-status" do |channel, data|
|
|
122
|
+
exit_code = data.read_long
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
ssh.loop
|
|
129
|
+
|
|
130
|
+
#we want to raise any non zero exit codes
|
|
131
|
+
unless ( exit_code == 0 && raise_exceptions )
|
|
132
|
+
raise RemoteRunError, "#{stderr} - Exit Code: #{exit_code}"
|
|
133
|
+
else
|
|
134
|
+
return stdout
|
|
135
|
+
end
|
|
99
136
|
end
|
|
100
137
|
|
|
101
138
|
|
|
@@ -103,9 +140,11 @@ module Elsewhere
|
|
|
103
140
|
end
|
|
104
141
|
|
|
105
142
|
if __FILE__ == $0
|
|
106
|
-
host = ""
|
|
107
|
-
user = ""
|
|
108
|
-
r = RemoteRun.new(host,user)
|
|
109
|
-
r.commands << "
|
|
143
|
+
host = "wa-app-q0"
|
|
144
|
+
user = "wa-current"
|
|
145
|
+
r = Elsewhere::RemoteRun.new(host,user)
|
|
146
|
+
r.commands << "source /etc/profile"
|
|
147
|
+
r.commands << "cd ~/current"
|
|
148
|
+
r.commands << "bundle exec rake --trace transformer:run cas=3 queue=solo remote_run_id=1 ddcid=2013 exit=true RAILS_ENV=qa"
|
|
110
149
|
puts r.execute
|
|
111
150
|
end
|
data/lib/elsewhere/version.rb
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'minitest/autorun'
|
|
2
|
+
require 'elsewhere'
|
|
3
|
+
|
|
4
|
+
class TestRemoteRun < MiniTest::Unit::TestCase
|
|
5
|
+
|
|
6
|
+
def setup
|
|
7
|
+
@user = "test_user"
|
|
8
|
+
@hosts = %w{ www.example.com }
|
|
9
|
+
@gateway = "www.examplegateway.com"
|
|
10
|
+
@gateway_user = "test_user"
|
|
11
|
+
|
|
12
|
+
@config = Dir.pwd + "/tests/test_config.yml"
|
|
13
|
+
@remote_run = Elsewhere::RemoteRun.initialize_from_config(@config, 'test', 'test_group')
|
|
14
|
+
@remote_run_with_gateway = Elsewhere::RemoteRun.initialize_from_config(@config, 'test', 'test_group_with_gateway')
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_hosts_are_set_from_initialized_config
|
|
19
|
+
assert_equal @hosts , @remote_run.hosts
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def test_user_is_set_from_initialized_config
|
|
23
|
+
assert_equal @user, @remote_run.user
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_gateway_is_set_from_initialized_config
|
|
27
|
+
assert_equal @gateway, @remote_run_with_gateway.gateway_address
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_gateway_user_is_set_from_initialized_config
|
|
31
|
+
assert_equal @gateway_user, @remote_run_with_gateway.gateway_user
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: elsewhere
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.6'
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-05-
|
|
12
|
+
date: 2012-05-08 00:00:00.000000000Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: minitest
|
|
16
|
-
requirement: &
|
|
16
|
+
requirement: &2168858640 !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,10 +21,10 @@ dependencies:
|
|
|
21
21
|
version: '0'
|
|
22
22
|
type: :development
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements: *
|
|
24
|
+
version_requirements: *2168858640
|
|
25
25
|
- !ruby/object:Gem::Dependency
|
|
26
26
|
name: net-ssh
|
|
27
|
-
requirement: &
|
|
27
|
+
requirement: &2168858200 !ruby/object:Gem::Requirement
|
|
28
28
|
none: false
|
|
29
29
|
requirements:
|
|
30
30
|
- - ! '>='
|
|
@@ -32,10 +32,10 @@ dependencies:
|
|
|
32
32
|
version: '0'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
|
-
version_requirements: *
|
|
35
|
+
version_requirements: *2168858200
|
|
36
36
|
- !ruby/object:Gem::Dependency
|
|
37
37
|
name: net-ssh-gateway
|
|
38
|
-
requirement: &
|
|
38
|
+
requirement: &2168857760 !ruby/object:Gem::Requirement
|
|
39
39
|
none: false
|
|
40
40
|
requirements:
|
|
41
41
|
- - ! '>='
|
|
@@ -43,7 +43,7 @@ dependencies:
|
|
|
43
43
|
version: '0'
|
|
44
44
|
type: :runtime
|
|
45
45
|
prerelease: false
|
|
46
|
-
version_requirements: *
|
|
46
|
+
version_requirements: *2168857760
|
|
47
47
|
description: ! ' Yet another way to run stuff remotely '
|
|
48
48
|
email:
|
|
49
49
|
- bchapman@academicmanagement.com
|
|
@@ -59,7 +59,9 @@ files:
|
|
|
59
59
|
- lib/elsewhere.rb
|
|
60
60
|
- lib/elsewhere/remote_run.rb
|
|
61
61
|
- lib/elsewhere/version.rb
|
|
62
|
-
|
|
62
|
+
- tests/test_config.yml
|
|
63
|
+
- tests/test_remote_run.rb
|
|
64
|
+
homepage: https://github.com/byllc/elsewhere
|
|
63
65
|
licenses: []
|
|
64
66
|
post_install_message:
|
|
65
67
|
rdoc_options: []
|
|
@@ -79,7 +81,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
79
81
|
version: '0'
|
|
80
82
|
requirements: []
|
|
81
83
|
rubyforge_project: elsewhere
|
|
82
|
-
rubygems_version: 1.8.
|
|
84
|
+
rubygems_version: 1.8.17
|
|
83
85
|
signing_key:
|
|
84
86
|
specification_version: 3
|
|
85
87
|
summary: Simple wrapper for Net SSH to run a list of commands remotely
|