mobilize-ssh 1.361 → 1.363

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,15 +2,44 @@ module Mobilize
2
2
  module Ssh
3
3
  #adds convenience methods
4
4
  require "#{File.dirname(__FILE__)}/../helpers/ssh_helper"
5
- def Ssh.pop_comm_dir(comm_dir,file_hash)
5
+ def Ssh.pop_loc_dir(unique_name,file_hash)
6
+ loc_dir = "/tmp/#{unique_name}"
7
+ `rm -rf #{loc_dir} && mkdir -p #{loc_dir}`
6
8
  file_hash.each do |fname,fdata|
7
- fpath = "#{comm_dir}/#{fname}"
9
+ fpath = "#{loc_dir}/#{fname}"
8
10
  #for now, only gz is binary
9
- binary = fname.ends_with?(".gz") ? true : false
10
- #read data from cache, put it in a tmp_file
11
- Ssh.tmp_file(fdata,binary,fpath)
11
+ mode = fname.ends_with?(".gz") ? "wb" : "w"
12
+ File.open(fpath,mode) {|f| f.print(fdata)}
12
13
  end
13
- return true if file_hash.keys.length>0
14
+ return loc_dir if file_hash.keys.length>0
15
+ end
16
+
17
+ def Ssh.deploy(node,user_name,unique_name,command,file_hash)
18
+ loc_dir = Ssh.pop_loc_dir(unique_name,file_hash)
19
+ Ssh.fire!(node,"rm -rf #{unique_name} && mkdir -p #{unique_name} && chown -R #{Ssh.node_owner(node)} #{unique_name}")
20
+ if loc_dir
21
+ Ssh.scp(node,loc_dir,".")
22
+ #make sure loc_dir is removed
23
+ FileUtils.rm_r(loc_dir,:force=>true)
24
+ end
25
+ #create cmd_file in unique_name
26
+ cmd_path = "#{unique_name}/cmd.sh"
27
+ Ssh.write(node,command,cmd_path)
28
+ #move folder to user's home, change ownership
29
+ user_dir = "/home/#{user_name}/"
30
+ mobilize_dir = "#{user_dir}mobilize/"
31
+ deploy_dir = "#{mobilize_dir}#{unique_name}/"
32
+ deploy_cmd_path = "#{deploy_dir}cmd.sh"
33
+ deploy_cmd = "sudo mkdir -p #{mobilize_dir} && " +
34
+ "sudo rm -rf #{mobilize_dir}#{unique_name} && " +
35
+ "sudo mv #{unique_name} #{mobilize_dir} && " +
36
+ "sudo chown -R #{user_name} #{mobilize_dir}"
37
+ Ssh.fire!(node,deploy_cmd)
38
+ #need to use bash or we get no tee
39
+ full_cmd = "/bin/bash -l -c '(cd #{deploy_dir} && sh #{deploy_cmd_path} > >(tee stdout) 2> >(tee stderr >&2))'"
40
+ #fire_cmd runs sh on cmd_path, optionally with sudo su
41
+ fire_cmd = %{sudo su #{user_name} -c "#{full_cmd}"}
42
+ return fire_cmd
14
43
  end
15
44
 
16
45
  # converts a source path or target path to a dst in the context of handler and stage
@@ -67,13 +96,9 @@ module Mobilize
67
96
  return true
68
97
  end
69
98
 
70
- def Ssh.run(node,command,user_name,file_hash={},run_params=nil)
71
- default_user_name = Ssh.host(node)['user']
99
+ def Ssh.run(node,command,user_name,stage_path=nil,file_hash={},run_params=nil)
72
100
  file_hash ||= {}
73
101
  run_params ||={}
74
- #make sure the dir for this command is clear
75
- comm_md5 = [user_name,node,command,file_hash.keys.to_s,Time.now.to_f.to_s].join.to_md5
76
- comm_dir = Dir.mktmpdir
77
102
  #replace any params in the file_hash and command
78
103
  run_params.each do |k,v|
79
104
  command.gsub!("@#{k}",v)
@@ -81,41 +106,25 @@ module Mobilize
81
106
  data.gsub!("@#{k}",v)
82
107
  end
83
108
  end
84
- #populate comm dir with any files
85
- Ssh.pop_comm_dir(comm_dir,file_hash)
86
- #make sure user starts in rem_dir
87
- rem_dir = "#{comm_md5}/"
88
- #make sure the rem_dir is gone
89
- Ssh.fire!(node,"sudo rm -rf #{rem_dir}")
90
- if File.exists?(comm_dir)
91
- Ssh.scp(node,comm_dir,rem_dir)
92
- #make sure comm_dir is removed
93
- FileUtils.rm_r(comm_dir,:force=>true)
94
- else
95
- #create folder
96
- mkdir_command = "mkdir #{rem_dir}"
97
- Ssh.fire!(node,mkdir_command)
98
- end
99
- #create cmd_file in rem_folder
100
- cmd_file = "#{comm_md5}.sh"
101
- cmd_path = "#{rem_dir}#{cmd_file}"
102
- Ssh.write(node,command,cmd_path)
103
- full_cmd = "(cd #{rem_dir} && sh #{cmd_file})"
104
- #fire_cmd runs sh on cmd_path, optionally with sudo su
105
- if user_name != default_user_name
106
- #make sure user owns the folder and all files
107
- fire_cmd = %{sudo chown -R #{user_name} #{rem_dir}; sudo su #{user_name} -c "#{full_cmd}"}
108
- rm_cmd = %{sudo rm -rf #{rem_dir}}
109
- else
110
- fire_cmd = full_cmd
111
- rm_cmd = "rm -rf #{rem_dir}"
112
- end
109
+ #make sure the dir for this command is unique
110
+ unique_name = if stage_path
111
+ stage_path.downcase.alphanunderscore
112
+ else
113
+ [user_name,node,command,file_hash.keys.to_s,Time.now.to_f.to_s].join.to_md5
114
+ end
115
+ fire_cmd = Ssh.deploy(node, user_name, unique_name, command, file_hash)
113
116
  result = Ssh.fire!(node,fire_cmd)
114
- Ssh.fire!(node,rm_cmd)
115
- result
117
+ #clear out the md5 folders and those not requested to keep
118
+ s = Stage.find_by_path(stage_path) if stage_path
119
+ unless s and s.params['keep_logs']
120
+ rm_cmd = "sudo rm -rf /home/#{user_name}/mobilize/#{unique_name}"
121
+ Ssh.fire!(node,rm_cmd)
122
+ end
123
+ return result
116
124
  end
117
125
 
118
126
  def Ssh.fire!(node,cmd)
127
+ puts "#{Time.now.utc}--Ssh on #{node}: #{cmd}"
119
128
  name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
120
129
  key_path = "#{Base.root}/#{key}"
121
130
  opts = {:port=>(port || 22),:keys=>key_path}
@@ -169,7 +178,7 @@ module Mobilize
169
178
  node = Ssh.default_node unless Ssh.nodes.include?(node)
170
179
  if user_name and !Ssh.sudoers(node).include?(u.name)
171
180
  raise "#{u.name} does not have su permissions for this node"
172
- elsif user_name.nil? and Ssh.su_all_users(node)
181
+ elsif user_name.nil?
173
182
  user_name = u.name
174
183
  end
175
184
  return user_name
@@ -213,10 +222,14 @@ module Mobilize
213
222
  node, command = [params['node'],params['cmd']]
214
223
  node ||= Ssh.default_node
215
224
  user_name = Ssh.user_name_by_stage_path(stage_path)
225
+ #do not allow server commands from non-sudoers for the special server node
226
+ if node=='server' and !Ssh.sudoers(node).include?(user_name)
227
+ raise "You do not have permission to run commands on the mobilize server"
228
+ end
216
229
  file_hash = Ssh.file_hash_by_stage_path(stage_path,gdrive_slot)
217
230
  Gdrive.unslot_worker_by_path(stage_path)
218
231
  run_params = params['params']
219
- result = Ssh.run(node,command,user_name,file_hash,run_params)
232
+ result = Ssh.run(node,command,user_name,stage_path,file_hash,run_params)
220
233
  #use Gridfs to cache result
221
234
  response = {}
222
235
  response['out_url'] = Dataset.write_by_url("gridfs://#{s.path}/out",result['stdout'].to_s,Gdrive.owner_name)
@@ -16,10 +16,6 @@ module Mobilize
16
16
  self.config['nodes'][node]['sudoers']
17
17
  end
18
18
 
19
- def self.su_all_users(node)
20
- self.config['nodes'][node]['su_all_users']
21
- end
22
-
23
19
  def self.nodes
24
20
  self.config['nodes'].keys
25
21
  end
@@ -28,8 +24,17 @@ module Mobilize
28
24
  self.nodes.first
29
25
  end
30
26
 
27
+ def self.node_owner(node)
28
+ self.host(node)['user']
29
+ end
30
+
31
+ def self.skip_gateway?(node)
32
+ self.config['nodes'][node]['skip_gateway']
33
+ end
34
+
31
35
  #determine if current machine is on host domain, needs gateway if one is provided and it is not
32
36
  def self.needs_gateway?(node)
37
+ return false if self.skip_gateway?(node)
33
38
  host_domain_name = self.host(node)['name'].split(".")[-2..-1].join(".")
34
39
  return true if self.gateway(node) and Socket.domain_name != host_domain_name
35
40
  end
@@ -1,5 +1,5 @@
1
1
  module Mobilize
2
2
  module Ssh
3
- VERSION = "1.361"
3
+ VERSION = "1.363"
4
4
  end
5
5
  end
data/lib/samples/ssh.yml CHANGED
@@ -23,11 +23,13 @@ test:
23
23
  su_all_users: true
24
24
  host:
25
25
  name: test-host.com
26
+ skip_gateway: true
26
27
  key: config/mobilize/ssh_private.key
27
28
  port: 22
28
29
  user: host_user
29
30
  gateway:
30
31
  name: test-gateway.com
32
+ skip_gateway: true
31
33
  key: config/mobilize/ssh_private.key
32
34
  port: 22
33
35
  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.361"
19
+ gem.add_runtime_dependency "mobilize-base","1.363"
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"
@@ -3,23 +3,23 @@
3
3
  active: true
4
4
  trigger: once
5
5
  status: ""
6
- stage1: ssh.run node:"test_node", cmd:"ruby code.rb", user:"root", sources:["code.rb", "code.sh"]
6
+ stage1: ssh.run keep_logs:true, node:"test_node", cmd:"ruby code.rb", user:"root", sources:["code.rb", "code.sh"]
7
7
  stage2: gsheet.write source:"stage1", target:"ssh1.out"
8
8
  - name: ssh2
9
9
  active: true
10
10
  trigger: "after ssh1"
11
11
  status: ""
12
- stage1: ssh.run cmd:"sh code2.sh", user:"root", sources:["code2.sh","test_node/var/log/syslog"], params:{file:"syslog"}
12
+ stage1: ssh.run keep_logs:true, cmd:"sh code2.sh", user:"root", sources:["code2.sh","test_node/var/log/syslog"], params:{file:"syslog"}
13
13
  stage2: gsheet.write source:"stage1", target:"ssh2.out"
14
14
  - name: ssh3
15
15
  active: true
16
16
  trigger: "after ssh2"
17
17
  status: ""
18
- stage1: ssh.run cmd:"echo '@test_param'", params:{test_param:"test param successful"}
18
+ stage1: ssh.run keep_logs:true, cmd:"echo '@test_param'", params:{test_param:"test param successful"}
19
19
  stage2: gsheet.write source:"stage1", target:"ssh3.out"
20
20
  - name: ssh4
21
21
  active: true
22
22
  trigger: "after ssh3"
23
23
  status: ""
24
- stage1: ssh.run node:"test_node", user:root, sources:["git://DeNA/mobilize-ssh/test/fixtures/code.rb","git://DeNA/mobilize-ssh/test/fixtures/code.sh"], cmd:"ruby code.rb"
24
+ stage1: ssh.run keep_logs:true, node:"test_node", user:root, sources:["git://DeNA/mobilize-ssh/test/fixtures/code.rb","git://DeNA/mobilize-ssh/test/fixtures/code.sh"], cmd:"ruby code.rb"
25
25
  stage2: gsheet.write source:stage1, target:"ssh4.out"
@@ -18,7 +18,7 @@ describe "Mobilize" do
18
18
  end
19
19
 
20
20
  puts "add/update jobs"
21
- u.jobs.each{|j| j.delete}
21
+ u.jobs.each{|j| j.stages.each{|s| s.delete}; j.delete}
22
22
  jobs_fixture_name = "integration_jobs"
23
23
  jobs_target_url = "gsheet://#{r.title}/jobs"
24
24
  TestHelper.write_fixture(jobs_fixture_name, jobs_target_url, 'update')
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.361'
4
+ version: '1.363'
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: 2013-05-31 00:00:00.000000000 Z
12
+ date: 2013-06-13 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.361'
21
+ version: '1.363'
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.361'
29
+ version: '1.363'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: net-ssh
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -121,7 +121,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
121
  version: '0'
122
122
  segments:
123
123
  - 0
124
- hash: -3139478933470599366
124
+ hash: 4500700013252989723
125
125
  required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  none: false
127
127
  requirements:
@@ -130,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
130
130
  version: '0'
131
131
  segments:
132
132
  - 0
133
- hash: -3139478933470599366
133
+ hash: 4500700013252989723
134
134
  requirements: []
135
135
  rubyforge_project:
136
136
  rubygems_version: 1.8.25