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 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 a host, and optionally has a gateway. If you don't need a
87
- gateway, remove that row from the configuration file.
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
- name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
71
+ key,user = Ssh.host(node).ie{|h| ['key','user'].map{|k| h[k]}}
56
72
  key_path = "#{Base.root}/#{key}"
57
- opts = {:port=>(port || 22),:keys=>key_path}
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
- if su_user
76
- chown_command = "sudo chown -R #{su_user} #{rem_dir}"
77
- Ssh.run(node,chown_command)
78
- end
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
- result = nil
85
- #one with gateway, one without
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
- gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
88
- gkey_path = "#{Base.root}/#{gkey}"
89
- gopts = {:port=>(gport || 22),:keys=>gkey_path}
90
- result = Net::SSH::Gateway.run(gname,guser,name,user,command,gopts,opts)
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
- Net::SSH.start(name,user,opts) do |ssh|
93
- result = ssh.run(command)
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.run(node,"cat #{path}")
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.run(node,command,file_hash,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
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
@@ -1,5 +1,5 @@
1
1
  module Mobilize
2
2
  module Ssh
3
- VERSION = "1.0.7"
3
+ VERSION = "1.0.9"
4
4
  end
5
5
  end
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.8"
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"
@@ -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 enqueued runner, wait 120s"
46
+ puts "job row added, force enqueue runner, wait 150s"
47
47
  r.enqueue!
48
- sleep 120
48
+ sleep 150
49
49
 
50
50
  puts "update job status and activity"
51
51
  r.update_gsheet(gdrive_slot)
@@ -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: once
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: once
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.7
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-16 00:00:00.000000000 Z
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.8
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.8
29
+ version: 1.0.9
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: net-ssh
32
32
  requirement: !ruby/object:Gem::Requirement