mobilize-ssh 1.0.7 → 1.0.9
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 +10 -2
- data/lib/mobilize-ssh/handlers/ssh.rb +66 -34
- data/lib/mobilize-ssh/version.rb +1 -1
- data/lib/samples/ssh.yml +6 -0
- data/mobilize-ssh.gemspec +1 -1
- data/test/mobilize-ssh_test.rb +2 -2
- data/test/ssh_job_rows.yml +2 -2
- metadata +4 -4
data/README.md
CHANGED
|
@@ -83,8 +83,16 @@ 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
84
|
pass into the "node" param over in the ssh.run task.
|
|
85
85
|
|
|
86
|
-
Each node has
|
|
87
|
-
|
|
86
|
+
Each node has:
|
|
87
|
+
* a host;
|
|
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.
|
|
88
96
|
|
|
89
97
|
Each host and gateway has a series of ssh params:
|
|
90
98
|
* name - the ip address or name of the host
|
|
@@ -16,6 +16,14 @@ 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
|
+
|
|
19
27
|
#determine if current machine is on host domain, needs gateway if one is provided and it is not
|
|
20
28
|
def Ssh.needs_gateway?(node)
|
|
21
29
|
host_domain_name = Ssh.host(node)['name'].split(".")[-2..-1].join(".")
|
|
@@ -34,9 +42,17 @@ module Mobilize
|
|
|
34
42
|
return true if file_hash.keys.length>0
|
|
35
43
|
end
|
|
36
44
|
|
|
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
|
+
|
|
37
52
|
def Ssh.scp(node,from_path,to_path)
|
|
38
53
|
name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
|
39
54
|
key_path = "#{Base.root}/#{key}"
|
|
55
|
+
Ssh.set_key_permissions(key_path)
|
|
40
56
|
opts = {:port=>(port || 22),:keys=>key_path}
|
|
41
57
|
if Ssh.needs_gateway?(node)
|
|
42
58
|
gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
|
@@ -52,9 +68,9 @@ module Mobilize
|
|
|
52
68
|
end
|
|
53
69
|
|
|
54
70
|
def Ssh.run(node,command,file_hash=nil,su_user=nil)
|
|
55
|
-
|
|
71
|
+
key,user = Ssh.host(node).ie{|h| ['key','user'].map{|k| h[k]}}
|
|
56
72
|
key_path = "#{Base.root}/#{key}"
|
|
57
|
-
|
|
73
|
+
Ssh.set_key_permissions(key_path)
|
|
58
74
|
su_user ||= user
|
|
59
75
|
file_hash ||= {}
|
|
60
76
|
#make sure the dir for this command is clear
|
|
@@ -64,48 +80,55 @@ module Mobilize
|
|
|
64
80
|
Ssh.pop_comm_dir(comm_dir,file_hash)
|
|
65
81
|
#move any files up to the node
|
|
66
82
|
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}")
|
|
67
87
|
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(";")
|
|
71
|
-
#make sure the rem_dir is gone
|
|
72
|
-
Ssh.run(node,"rm -rf #{rem_dir}")
|
|
73
88
|
Ssh.scp(node,comm_dir,rem_dir)
|
|
74
89
|
"rm -rf #{comm_dir}".bash
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
end
|
|
80
|
-
if su_user != user
|
|
81
|
-
#wrap the command in sudo su -c
|
|
82
|
-
command = %{sudo su #{su_user} -c "#{command}"}
|
|
90
|
+
else
|
|
91
|
+
#create folder
|
|
92
|
+
mkdir_command = "mkdir #{rem_dir}"
|
|
93
|
+
Ssh.fire!(node,mkdir_command)
|
|
83
94
|
end
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
#create cmd_file in rem_folder
|
|
96
|
+
cmd_file = "#{comm_md5}.sh"
|
|
97
|
+
cmd_path = "#{rem_dir}#{cmd_file}"
|
|
98
|
+
Ssh.write(node,command,cmd_path)
|
|
99
|
+
full_cmd = "(cd #{rem_dir} && sh #{cmd_file})"
|
|
100
|
+
#fire_cmd runs sh on cmd_path, optionally with sudo su
|
|
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}
|
|
86
118
|
if Ssh.needs_gateway?(node)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
119
|
+
gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
|
|
120
|
+
gkey_path = "#{Base.root}/#{gkey}"
|
|
121
|
+
gopts = {:port=>(gport || 22),:keys=>gkey_path}
|
|
122
|
+
Net::SSH::Gateway.run(gname,guser,name,user,cmd,gopts,opts)
|
|
91
123
|
else
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
#delete remote dir if necessary
|
|
97
|
-
if rem_dir
|
|
98
|
-
del_cmd = "rm -rf #{rem_dir}"
|
|
99
|
-
if su_user
|
|
100
|
-
del_cmd = %{sudo su #{su_user} -c "#{del_cmd}"}
|
|
124
|
+
Net::SSH.start(name,user,opts) do |ssh|
|
|
125
|
+
ssh.run(cmd)
|
|
101
126
|
end
|
|
102
|
-
Ssh.run(node,del_cmd)
|
|
103
127
|
end
|
|
104
|
-
result
|
|
105
128
|
end
|
|
106
129
|
|
|
107
130
|
def Ssh.read(node,path)
|
|
108
|
-
Ssh.
|
|
131
|
+
Ssh.fire!(node,"cat #{path}")
|
|
109
132
|
end
|
|
110
133
|
|
|
111
134
|
def Ssh.write(node,fdata,to_path,binary=false)
|
|
@@ -153,11 +176,20 @@ module Mobilize
|
|
|
153
176
|
|
|
154
177
|
def Ssh.run_by_stage_path(stage_path)
|
|
155
178
|
s = Stage.where(:path=>stage_path).first
|
|
179
|
+
u = s.job.runner.user
|
|
156
180
|
params = s.params
|
|
157
181
|
node, command = [params['node'],params['cmd']]
|
|
158
182
|
file_hash = Ssh.file_hash_by_stage_path(stage_path)
|
|
159
183
|
su_user = s.params['su_user']
|
|
160
|
-
Ssh.
|
|
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
|
|
188
|
+
end
|
|
189
|
+
out_tsv = Ssh.run(node,command,file_hash,su_user)
|
|
190
|
+
#use Gridfs to cache result
|
|
191
|
+
out_url = "gridfs://#{s.path}/out"
|
|
192
|
+
Dataset.write_to_url(out_url,out_tsv)
|
|
161
193
|
end
|
|
162
194
|
end
|
|
163
195
|
end
|
data/lib/mobilize-ssh/version.rb
CHANGED
data/lib/samples/ssh.yml
CHANGED
|
@@ -2,17 +2,23 @@ development:
|
|
|
2
2
|
tmp_file_dir: "tmp/file/"
|
|
3
3
|
nodes:
|
|
4
4
|
dev_node:
|
|
5
|
+
sudoers: [sudo_user]
|
|
6
|
+
su_all_users: true
|
|
5
7
|
host: {name: dev-host.com, key: "config/mobilize/ssh_private.key", port: 22, user: host_user}
|
|
6
8
|
gateway: {name: dev-gateway.com, key: "config/mobilize/ssh_private.key", port: 22, user: gateway_user}
|
|
7
9
|
test:
|
|
8
10
|
tmp_file_dir: "tmp/file/"
|
|
9
11
|
nodes:
|
|
10
12
|
test_node:
|
|
13
|
+
sudoers: [sudo_user]
|
|
14
|
+
su_all_users: true
|
|
11
15
|
host: {name: test-host.com, key: "config/mobilize/ssh_private.key", port: 22, user: host_user}
|
|
12
16
|
gateway: {name: test-gateway.com, key: "config/mobilize/ssh_private.key", port: 22, user: gateway_user}
|
|
13
17
|
production:
|
|
14
18
|
tmp_file_dir: "tmp/file/"
|
|
15
19
|
nodes:
|
|
16
20
|
prod_node:
|
|
21
|
+
sudoers: [sudo_user]
|
|
22
|
+
su_all_users: true
|
|
17
23
|
host: {name: prod-host.com, key: "config/mobilize/ssh_private.key", port: 22, user: host_user}
|
|
18
24
|
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.9"
|
|
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
|
@@ -43,9 +43,9 @@ describe "Mobilize" do
|
|
|
43
43
|
ssh_job_rows.map{|j| r.jobs(j['name'])}.each{|j| j.delete if j}
|
|
44
44
|
jobs_sheet.add_or_update_rows(ssh_job_rows)
|
|
45
45
|
|
|
46
|
-
puts "job row added, force
|
|
46
|
+
puts "job row added, force enqueue runner, wait 150s"
|
|
47
47
|
r.enqueue!
|
|
48
|
-
sleep
|
|
48
|
+
sleep 150
|
|
49
49
|
|
|
50
50
|
puts "update job status and activity"
|
|
51
51
|
r.update_gsheet(gdrive_slot)
|
data/test/ssh_job_rows.yml
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
stage2: 'gsheet.write source:"stage1", target:"Runner_mobilize(test)/test_ssh_1.out"'
|
|
7
7
|
- name: test_ssh_2
|
|
8
8
|
active: true
|
|
9
|
-
trigger:
|
|
9
|
+
trigger: "after test_ssh_1"
|
|
10
10
|
status: ""
|
|
11
11
|
stage1: 'ssh.run node:"test_node", cmd:"sh code.sh", su_user:"root", source:"Runner_mobilize(test)/code.sh"'
|
|
12
12
|
stage2: 'gsheet.write source:"stage1", target:"Runner_mobilize(test)/test_ssh_2.out"'
|
|
13
13
|
- name: test_ssh_3
|
|
14
14
|
active: true
|
|
15
|
-
trigger:
|
|
15
|
+
trigger: "after test_ssh_2"
|
|
16
16
|
status: ""
|
|
17
17
|
stage1: 'ssh.run node:"test_node", cmd:"whoami"'
|
|
18
18
|
stage2: 'gsheet.write source:"stage1", target:"Runner_mobilize(test)/test_ssh_3.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.9
|
|
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-22 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.9
|
|
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.9
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: net-ssh
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|