mobilize-ssh 1.0.9 → 1.0.21
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 +6 -16
- data/Rakefile +2 -2
- data/lib/mobilize-ssh/handlers/ssh.rb +52 -96
- data/lib/mobilize-ssh/{tasks.rb → rakes.rb} +0 -0
- data/lib/mobilize-ssh/version.rb +1 -1
- data/lib/samples/ssh.yml +0 -6
- data/mobilize-ssh.gemspec +1 -1
- data/test/mobilize-ssh_test.rb +4 -20
- data/test/ssh_job_rows.yml +3 -15
- metadata +11 -6
data/README.md
CHANGED
@@ -81,18 +81,10 @@ The Ssh configuration consists of:
|
|
81
81
|
over to the nodes. They will be deleted afterwards, unless the job
|
82
82
|
fails in mid-copy. By default this is tmp/file/.
|
83
83
|
* nodes, identified by aliases, such as `test_node`. This alias is what you should
|
84
|
-
pass into the "
|
85
|
-
|
86
|
-
Each node has
|
87
|
-
|
88
|
-
* a gateway (optional); If you don't need a gateway, remove that row from the configuration file.
|
89
|
-
* sudoers; these are user names that are allowed to pass su_user params
|
90
|
-
to the run call. This requires passwordless sudo for the host user.
|
91
|
-
* su_all_users true/false option, which ensures that commands are executed by the
|
92
|
-
user on the Runner. It prefixes all commands with sudo su <user_name> before executing the
|
93
|
-
command. This is strongly recommended if possible as it ensures users do
|
94
|
-
not overstep their permissions. This requires passwordless sudo for the
|
95
|
-
host user and accounts on the host machine for each user.
|
84
|
+
pass into the "node_alias" param over in the ssh.run task.
|
85
|
+
|
86
|
+
Each node has a host, and optionally has a gateway. If you don't need a
|
87
|
+
gateway, remove that row from the configuration file.
|
96
88
|
|
97
89
|
Each host and gateway has a series of ssh params:
|
98
90
|
* name - the ip address or name of the host
|
@@ -133,12 +125,10 @@ Start
|
|
133
125
|
### Create Job
|
134
126
|
|
135
127
|
* For mobilize-ssh, the following task is available:
|
136
|
-
* ssh.run
|
128
|
+
* ssh.run `<node_alias>,<command>,*<gsheet_full_paths>`, which reads
|
137
129
|
all gsheets, copies them to a temporary folder on the selected node, and
|
138
130
|
runs the command inside that folder.
|
139
|
-
*
|
140
|
-
will cause the command to be prefixed with sudo su <su_user> -c.
|
141
|
-
* The test uses `ssh.run node:"test_node", cmd:"ruby code.rb", su_user: "root", sources:["Runner_mobilize(test)/code.rb","Runner_mobilize(test)/code.sh"]`
|
131
|
+
* The test uses `ssh.run "test_node", "ruby code.rb", "Runner_mobilize(test)/code.rb", "Runner_mobilize(test)/code.sh"`
|
142
132
|
|
143
133
|
<a name='section_Start_Run_Test'></a>
|
144
134
|
### Run Test
|
data/Rakefile
CHANGED
@@ -16,14 +16,6 @@ module Mobilize
|
|
16
16
|
Ssh.config['nodes'][node]['gateway']
|
17
17
|
end
|
18
18
|
|
19
|
-
def Ssh.sudoers(node)
|
20
|
-
Ssh.config['nodes'][node]['sudoers']
|
21
|
-
end
|
22
|
-
|
23
|
-
def Ssh.su_all_users(node)
|
24
|
-
Ssh.config['nodes'][node]['su_all_users']
|
25
|
-
end
|
26
|
-
|
27
19
|
#determine if current machine is on host domain, needs gateway if one is provided and it is not
|
28
20
|
def Ssh.needs_gateway?(node)
|
29
21
|
host_domain_name = Ssh.host(node)['name'].split(".")[-2..-1].join(".")
|
@@ -42,17 +34,9 @@ module Mobilize
|
|
42
34
|
return true if file_hash.keys.length>0
|
43
35
|
end
|
44
36
|
|
45
|
-
def Ssh.set_key_permissions(key_path)
|
46
|
-
#makes sure permissions are set as appropriate for ssh key
|
47
|
-
"chmod a-rwx #{key_path}".bash
|
48
|
-
"chmod u+rw #{key_path}".bash
|
49
|
-
return true
|
50
|
-
end
|
51
|
-
|
52
37
|
def Ssh.scp(node,from_path,to_path)
|
53
38
|
name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
54
39
|
key_path = "#{Base.root}/#{key}"
|
55
|
-
Ssh.set_key_permissions(key_path)
|
56
40
|
opts = {:port=>(port || 22),:keys=>key_path}
|
57
41
|
if Ssh.needs_gateway?(node)
|
58
42
|
gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
@@ -68,9 +52,9 @@ module Mobilize
|
|
68
52
|
end
|
69
53
|
|
70
54
|
def Ssh.run(node,command,file_hash=nil,su_user=nil)
|
71
|
-
key,user = Ssh.host(node).ie{|h| ['key','user'].map{|k| h[k]}}
|
55
|
+
name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
72
56
|
key_path = "#{Base.root}/#{key}"
|
73
|
-
|
57
|
+
opts = {:port=>(port || 22),:keys=>key_path}
|
74
58
|
su_user ||= user
|
75
59
|
file_hash ||= {}
|
76
60
|
#make sure the dir for this command is clear
|
@@ -80,55 +64,46 @@ module Mobilize
|
|
80
64
|
Ssh.pop_comm_dir(comm_dir,file_hash)
|
81
65
|
#move any files up to the node
|
82
66
|
rem_dir = nil
|
83
|
-
#make sure user starts in rem_dir
|
84
|
-
rem_dir = "#{comm_md5}/"
|
85
|
-
#make sure the rem_dir is gone
|
86
|
-
Ssh.fire!(node,"rm -rf #{rem_dir}")
|
87
67
|
if File.exists?(comm_dir)
|
68
|
+
#make sure user starts in rem_dir
|
69
|
+
rem_dir = "#{comm_md5}/"
|
70
|
+
command = ["cd #{rem_dir}",command].join(";")
|
88
71
|
Ssh.scp(node,comm_dir,rem_dir)
|
89
72
|
"rm -rf #{comm_dir}".bash
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
73
|
+
if su_user
|
74
|
+
chown_command = "sudo chown -R #{su_user} #{rem_dir}"
|
75
|
+
Ssh.run(node,chown_command)
|
76
|
+
end
|
94
77
|
end
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
#
|
101
|
-
fire_cmd = if su_user != user
|
102
|
-
%{sudo su #{su_user} -c "#{full_cmd}"}
|
103
|
-
else
|
104
|
-
full_cmd
|
105
|
-
end
|
106
|
-
result = Ssh.fire!(node,fire_cmd)
|
107
|
-
#remove the directory after you're done
|
108
|
-
rm_cmd = "rm -rf #{rem_dir}"
|
109
|
-
Ssh.fire!(node,rm_cmd)
|
110
|
-
result
|
111
|
-
end
|
112
|
-
|
113
|
-
def Ssh.fire!(node,cmd)
|
114
|
-
name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
115
|
-
key_path = "#{Base.root}/#{key}"
|
116
|
-
Ssh.set_key_permissions(key_path)
|
117
|
-
opts = {:port=>(port || 22),:keys=>key_path}
|
78
|
+
if su_user != user
|
79
|
+
#wrap the command in sudo su -c
|
80
|
+
command = %{sudo su #{su_user} -c "#{command}"}
|
81
|
+
end
|
82
|
+
result = nil
|
83
|
+
#one with gateway, one without
|
118
84
|
if Ssh.needs_gateway?(node)
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
85
|
+
gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
86
|
+
gkey_path = "#{Base.root}/#{gkey}"
|
87
|
+
gopts = {:port=>(gport || 22),:keys=>gkey_path}
|
88
|
+
result = Net::SSH::Gateway.run(gname,guser,name,user,command,gopts,opts)
|
123
89
|
else
|
124
|
-
|
125
|
-
|
90
|
+
Net::SSH.start(name,user,opts) do |ssh|
|
91
|
+
result = ssh.run(command)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
#delete remote dir if necessary
|
95
|
+
if rem_dir
|
96
|
+
del_cmd = "rm -rf #{rem_dir}"
|
97
|
+
if su_user
|
98
|
+
del_cmd = %{sudo su #{su_user} -c "#{del_cmd}"}
|
126
99
|
end
|
100
|
+
Ssh.run(node,del_cmd)
|
127
101
|
end
|
102
|
+
result
|
128
103
|
end
|
129
104
|
|
130
105
|
def Ssh.read(node,path)
|
131
|
-
Ssh.
|
106
|
+
Ssh.run(node,"cat #{path}")
|
132
107
|
end
|
133
108
|
|
134
109
|
def Ssh.write(node,fdata,to_path,binary=false)
|
@@ -149,47 +124,28 @@ module Mobilize
|
|
149
124
|
return tmp_file_path
|
150
125
|
end
|
151
126
|
|
152
|
-
def Ssh.
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
[params['source']]
|
161
|
-
end
|
162
|
-
if gsheet_paths and gsheet_paths.length>0
|
163
|
-
gdrive_slot = Gdrive.slot_worker_by_path(stage_path)
|
164
|
-
file_hash = {}
|
165
|
-
gsheet_paths.map do |gpath|
|
166
|
-
string = Gsheet.find_by_path(gpath,gdrive_slot).to_tsv
|
167
|
-
fname = gpath.split("/").last
|
168
|
-
{fname => string}
|
169
|
-
end.each do |f|
|
170
|
-
file_hash = f.merge(file_hash)
|
171
|
-
end
|
172
|
-
Gdrive.unslot_worker_by_path(stage_path)
|
173
|
-
return file_hash
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def Ssh.run_by_stage_path(stage_path)
|
178
|
-
s = Stage.where(:path=>stage_path).first
|
179
|
-
u = s.job.runner.user
|
180
|
-
params = s.params
|
181
|
-
node, command = [params['node'],params['cmd']]
|
182
|
-
file_hash = Ssh.file_hash_by_stage_path(stage_path)
|
183
|
-
su_user = s.params['su_user']
|
184
|
-
if su_user and !Ssh.sudoers(node).include?(u.name)
|
185
|
-
raise "You do not have su permissions for this node"
|
186
|
-
elsif su_user.nil? and Ssh.su_all_users(node)
|
187
|
-
su_user = u.name
|
127
|
+
def Ssh.get_file_hash(gsheet_paths,gdrive_slot)
|
128
|
+
file_hash = {}
|
129
|
+
gsheet_paths.map do |gpath|
|
130
|
+
string = Gsheet.find_by_path(gpath,gdrive_slot).to_tsv
|
131
|
+
fname = gpath.split("/").last
|
132
|
+
{fname => string}
|
133
|
+
end.each do |f|
|
134
|
+
file_hash = f.merge(file_hash)
|
188
135
|
end
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
136
|
+
file_hash
|
137
|
+
end
|
138
|
+
|
139
|
+
def Ssh.run_by_task_path(task_path)
|
140
|
+
t = Task.where(:path=>task_path).first
|
141
|
+
params = t.params
|
142
|
+
node, command = [params[0],params[1]]
|
143
|
+
file_hash = if params[2]
|
144
|
+
gsheet_paths = params[2..-1] if params[2]
|
145
|
+
gdrive_slot = Gdrive.slot_worker_by_path(task_path)
|
146
|
+
Ssh.get_file_hash(gsheet_paths,gdrive_slot)
|
147
|
+
end
|
148
|
+
Ssh.run(node,command,file_hash)
|
193
149
|
end
|
194
150
|
end
|
195
151
|
end
|
File without changes
|
data/lib/mobilize-ssh/version.rb
CHANGED
data/lib/samples/ssh.yml
CHANGED
@@ -2,23 +2,17 @@ development:
|
|
2
2
|
tmp_file_dir: "tmp/file/"
|
3
3
|
nodes:
|
4
4
|
dev_node:
|
5
|
-
sudoers: [sudo_user]
|
6
|
-
su_all_users: true
|
7
5
|
host: {name: dev-host.com, key: "config/mobilize/ssh_private.key", port: 22, user: host_user}
|
8
6
|
gateway: {name: dev-gateway.com, key: "config/mobilize/ssh_private.key", port: 22, user: gateway_user}
|
9
7
|
test:
|
10
8
|
tmp_file_dir: "tmp/file/"
|
11
9
|
nodes:
|
12
10
|
test_node:
|
13
|
-
sudoers: [sudo_user]
|
14
|
-
su_all_users: true
|
15
11
|
host: {name: test-host.com, key: "config/mobilize/ssh_private.key", port: 22, user: host_user}
|
16
12
|
gateway: {name: test-gateway.com, key: "config/mobilize/ssh_private.key", port: 22, user: gateway_user}
|
17
13
|
production:
|
18
14
|
tmp_file_dir: "tmp/file/"
|
19
15
|
nodes:
|
20
16
|
prod_node:
|
21
|
-
sudoers: [sudo_user]
|
22
|
-
su_all_users: true
|
23
17
|
host: {name: prod-host.com, key: "config/mobilize/ssh_private.key", port: 22, user: host_user}
|
24
18
|
gateway: {name: prod-gateway.com, key: "config/mobilize/ssh_private.key", port: 22, user: gateway_user}
|
data/mobilize-ssh.gemspec
CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
|
-
gem.add_runtime_dependency "mobilize-base","1.0.
|
19
|
+
gem.add_runtime_dependency "mobilize-base","1.0.51"
|
20
20
|
gem.add_runtime_dependency "net-ssh"
|
21
21
|
gem.add_runtime_dependency "net-scp"
|
22
22
|
gem.add_runtime_dependency "net-ssh-gateway"
|
data/test/mobilize-ssh_test.rb
CHANGED
@@ -18,10 +18,6 @@ describe "Mobilize" do
|
|
18
18
|
u = Mobilize::User.where(:name=>user_name).first
|
19
19
|
r = u.runner
|
20
20
|
|
21
|
-
rb_code_sheet = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/code.rb",gdrive_slot)
|
22
|
-
sh_code_sheet = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/code.sh",gdrive_slot)
|
23
|
-
[rb_code_sheet,sh_code_sheet].each {|s| s.delete if s}
|
24
|
-
|
25
21
|
puts "add test code"
|
26
22
|
rb_code_sheet = Mobilize::Gsheet.find_or_create_by_path("#{r.path.split("/")[0..-2].join("/")}/code.rb",gdrive_slot)
|
27
23
|
rb_code_tsv = File.open("#{Mobilize::Base.root}/test/code.rb").read
|
@@ -33,32 +29,20 @@ describe "Mobilize" do
|
|
33
29
|
|
34
30
|
jobs_sheet = r.gsheet(gdrive_slot)
|
35
31
|
|
36
|
-
#delete target sheets if they exist
|
37
|
-
ssh_target_sheet_1 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_1.out",gdrive_slot)
|
38
|
-
ssh_target_sheet_2 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_2.out",gdrive_slot)
|
39
|
-
ssh_target_sheet_3 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_3.out",gdrive_slot)
|
40
|
-
[ssh_target_sheet_1,ssh_target_sheet_2,ssh_target_sheet_3].each {|s| s.delete if s}
|
41
|
-
|
42
32
|
ssh_job_rows = ::YAML.load_file("#{Mobilize::Base.root}/test/ssh_job_rows.yml")
|
43
|
-
ssh_job_rows.map{|j| r.jobs(j['name'])}.each{|j| j.delete if j}
|
44
33
|
jobs_sheet.add_or_update_rows(ssh_job_rows)
|
45
34
|
|
46
|
-
puts "job row added, force
|
35
|
+
puts "job row added, force enqueued runner, wait 90s"
|
47
36
|
r.enqueue!
|
48
|
-
sleep
|
37
|
+
sleep 90
|
49
38
|
|
50
39
|
puts "update job status and activity"
|
51
40
|
r.update_gsheet(gdrive_slot)
|
52
41
|
|
53
42
|
puts "jobtracker posted data to test sheet"
|
54
|
-
|
55
|
-
ssh_target_sheet_2 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_2.out",gdrive_slot)
|
56
|
-
ssh_target_sheet_3 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_3.out",gdrive_slot)
|
57
|
-
|
58
|
-
assert ssh_target_sheet_1.to_tsv.length > 100
|
59
|
-
assert ssh_target_sheet_2.to_tsv.length > 100
|
60
|
-
assert ssh_target_sheet_3.to_tsv.length > 3
|
43
|
+
ssh_target_sheet = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh.out",gdrive_slot)
|
61
44
|
|
45
|
+
assert ssh_target_sheet.to_tsv.length > 100
|
62
46
|
end
|
63
47
|
|
64
48
|
end
|
data/test/ssh_job_rows.yml
CHANGED
@@ -1,18 +1,6 @@
|
|
1
|
-
- name:
|
1
|
+
- name: test_ssh
|
2
2
|
active: true
|
3
3
|
trigger: once
|
4
4
|
status: ""
|
5
|
-
|
6
|
-
|
7
|
-
- name: test_ssh_2
|
8
|
-
active: true
|
9
|
-
trigger: "after test_ssh_1"
|
10
|
-
status: ""
|
11
|
-
stage1: 'ssh.run node:"test_node", cmd:"sh code.sh", su_user:"root", source:"Runner_mobilize(test)/code.sh"'
|
12
|
-
stage2: 'gsheet.write source:"stage1", target:"Runner_mobilize(test)/test_ssh_2.out"'
|
13
|
-
- name: test_ssh_3
|
14
|
-
active: true
|
15
|
-
trigger: "after test_ssh_2"
|
16
|
-
status: ""
|
17
|
-
stage1: 'ssh.run node:"test_node", cmd:"whoami"'
|
18
|
-
stage2: 'gsheet.write source:"stage1", target:"Runner_mobilize(test)/test_ssh_3.out"'
|
5
|
+
task1: 'ssh.run "test_node", "ruby code.rb", "Runner_mobilize(test)/code.rb", "Runner_mobilize(test)/code.sh"'
|
6
|
+
task2: 'gsheet.write "task1", "Runner_mobilize(test)/test_ssh.out"'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobilize-ssh
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.21
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mobilize-base
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0.
|
21
|
+
version: 1.0.51
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.0.
|
29
|
+
version: 1.0.51
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: net-ssh
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -93,7 +93,7 @@ files:
|
|
93
93
|
- lib/mobilize-ssh/extensions/socket.rb
|
94
94
|
- lib/mobilize-ssh/extensions/string.rb
|
95
95
|
- lib/mobilize-ssh/handlers/ssh.rb
|
96
|
-
- lib/mobilize-ssh/
|
96
|
+
- lib/mobilize-ssh/rakes.rb
|
97
97
|
- lib/mobilize-ssh/version.rb
|
98
98
|
- lib/samples/ssh.yml
|
99
99
|
- mobilize-ssh.gemspec
|
@@ -115,12 +115,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
115
115
|
- - ! '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
hash: 871259298100733038
|
118
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
122
|
none: false
|
120
123
|
requirements:
|
121
124
|
- - ! '>='
|
122
125
|
- !ruby/object:Gem::Version
|
123
126
|
version: '0'
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
hash: 871259298100733038
|
124
130
|
requirements: []
|
125
131
|
rubyforge_project:
|
126
132
|
rubygems_version: 1.8.24
|
@@ -134,4 +140,3 @@ test_files:
|
|
134
140
|
- test/redis-test.conf
|
135
141
|
- test/ssh_job_rows.yml
|
136
142
|
- test/test_helper.rb
|
137
|
-
has_rdoc:
|