mobilize-ssh 1.2 → 1.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -13,6 +13,7 @@ Table Of Contents
13
13
  * [Install Dirs and Files](#section_Install_Dirs_and_Files)
14
14
  * [Configure](#section_Configure)
15
15
  * [Ssh](#section_Configure_Ssh)
16
+ * [Git](#section_Configure_Git)
16
17
  * [Start](#section_Start)
17
18
  * [Create Job](#section_Start_Create_Job)
18
19
  * [Run Test](#section_Start_Run_Test)
@@ -79,9 +80,6 @@ Configure
79
80
  ### Configure Ssh
80
81
 
81
82
  The Ssh configuration consists of:
82
- * tmp_file_dir, which is where files will be stored before being scp'd
83
- over to the nodes. They will be deleted afterwards, unless the job
84
- fails in mid-copy. By default this is tmp/file/.
85
83
  * nodes, identified by aliases, such as `test_node`. This alias is what you should
86
84
  pass into the "node" param over in the ssh.run task.
87
85
  * if no node is specified, commands will default to the first node listed.
@@ -109,7 +107,6 @@ Sample ssh.yml:
109
107
  ``` yml
110
108
  ---
111
109
  development:
112
- tmp_file_dir: tmp/file/
113
110
  nodes:
114
111
  dev_node:
115
112
  sudoers:
@@ -126,7 +123,6 @@ development:
126
123
  port: 22
127
124
  user: gateway_user
128
125
  test:
129
- tmp_file_dir: tmp/file/
130
126
  nodes:
131
127
  test_node:
132
128
  sudoers:
@@ -143,7 +139,6 @@ test:
143
139
  port: 22
144
140
  user: gateway_user
145
141
  production:
146
- tmp_file_dir: tmp/file/
147
142
  nodes:
148
143
  prod_node:
149
144
  sudoers:
@@ -161,6 +156,57 @@ production:
161
156
  user: gateway_user
162
157
  ```
163
158
 
159
+ <a name='section_Configure_Git'></a>
160
+ ### Configure Git
161
+
162
+ Git configuration is not required but recommended, as it allows you to
163
+ pull files directly from public or private Git repositories.
164
+
165
+ The Git configuration consists of:
166
+ * domains, identified by aliases, such as `private` and `public`.
167
+ * domains are passed into the source parameters in the git.run task.
168
+ * if no domain is specified, commands will default to the first domain listed.
169
+
170
+ Each domain has:
171
+ * a host;
172
+ * a key (optional); If you don't need an ssh key to access the repo, remove that row from the configuration file.
173
+ * this is the relative path of the ssh key required to access the repository.
174
+ * a user, which is the user used for the git clone command.
175
+
176
+ Sample git.yml:
177
+
178
+ ``` yml
179
+ ---
180
+ development:
181
+ domains:
182
+ private:
183
+ host: github.<domain>.com
184
+ key: config/mobilize/ssh_private.key
185
+ user: git
186
+ public:
187
+ host: github.com
188
+ user: git
189
+ test:
190
+ domains:
191
+ private:
192
+ host: github.<domain>.com
193
+ key: config/mobilize/ssh_private.key
194
+ user: git
195
+ public:
196
+ host: github.com
197
+ user: git
198
+ production:
199
+ domains:
200
+ private:
201
+ host: github.<domain>.com
202
+ key: config/mobilize/ssh_private.key
203
+ user: git
204
+ public:
205
+ host: github.com
206
+ user: git
207
+ ```
208
+
209
+
164
210
  <a name='section_Start'></a>
165
211
  Start
166
212
  -----
@@ -169,10 +215,21 @@ Start
169
215
  ### Create Job
170
216
 
171
217
  * For mobilize-ssh, the following task is available:
172
- * ssh.run `node: <node_alias>, cmd: <command>, user: user, sources:[*<source_paths>]`, which reads sources, copies them to a temporary folder on the selected node, and runs the command inside that folder.
173
- * user, sources, and node are optional; cmd is required.
218
+ * ssh.run `node: <node_alias>, cmd: <command>, user: user, sources:[*<source_paths>], params:[{<key,value pairs>}]`, which reads sources, copies them to a temporary folder on the selected node, and runs the command inside that folder.
219
+ * user, sources, node, and params are optional; cmd is required.
174
220
  * specifying user will cause the command to be prefixed with sudo su <user> -c.
175
221
  * non-google sources will also be read as the specified user.
222
+ * git sources can be specified with syntax `git://<domain>/<repo_owner>/<repo_name>/<file_path>`.
223
+ * Accessing private repos requires that you add the Mobilize public key to the repository as a deploy key.
224
+ * there is no user-level access control for git repositories at this time.
225
+ * domain defaults to the first one listed, if not included.
226
+ * params are also optional for all of the below. They replace tokens in sources and the command.
227
+ * params are passed as a YML or JSON, as in:
228
+ * `ssh.run source:<source_path>, params:{'date':'2013-03-01', 'unit':'widgets'}`
229
+ * this example replaces all the keys, preceded by '@' in all source hqls with the value.
230
+ * The preceding '@' is used to keep from replacing instances
231
+ of "date" and "unit" in the command/source file; you should have `@date` and `@unit` in your actual HQL
232
+ if you'd like to replace those tokens.
176
233
  * not specifying node will cause the command to be run on the default node.
177
234
  * ssh sources can be specified with syntax
178
235
  `ssh://<node><file_full_path>`. If node is omitted, default node will be used.
@@ -0,0 +1,111 @@
1
+ module Mobilize
2
+ module Git
3
+ def Git.config
4
+ Base.config('git')
5
+ end
6
+
7
+ def Git.host(domain)
8
+ Git.config['domains'][domain]['host']
9
+ end
10
+
11
+ def Git.domains
12
+ Git.config['domains'].keys
13
+ end
14
+
15
+ def Git.default_domain
16
+ Git.domains.first
17
+ end
18
+
19
+ # converts a source path or target path to a dst in the context of handler and stage
20
+ def Git.path_to_dst(path,stage_path,gdrive_slot)
21
+ red_path = path.split("://").last
22
+ git_url = Git.url_by_path(red_path)
23
+ return Dataset.find_or_create_by_url(git_url)
24
+ end
25
+
26
+ def Git.url_by_path(path)
27
+ path_nodes = path.split("/")
28
+ domain = path_nodes.first.to_s
29
+ revision = "HEAD"
30
+ if Git.domains.include?(domain)
31
+ repo = path_nodes[1..2].join("/")
32
+ file_path = path_nodes[3..-1].join("/")
33
+ else
34
+ domain = Git.default_domain
35
+ repo = path_nodes[0..1].join("/")
36
+ file_path = path_nodes[2..-1].join("/")
37
+ end
38
+ url = "git://#{domain}/#{repo}/#{revision}/#{file_path}"
39
+ return url
40
+ end
41
+
42
+ #return path to tar.gz of git repo
43
+ def Git.pack(domain,repo,revision="HEAD")
44
+ repo_dir = Git.pull(domain,repo,revision)
45
+ repo_name = repo.split("/").last
46
+ tar_gz_path = "#{repo_dir}/../#{repo_name}.tar.gz"
47
+ pack_cmd = "cd #{repo_dir} && git archive #{revision} --format=tar.gz > #{tar_gz_path}"
48
+ pack_cmd.bash(true)
49
+ FileUtils.rm_r(repo_dir,:force=>true)
50
+ return tar_gz_path
51
+ end
52
+
53
+ #confirm that git file exists
54
+ def Git.exists?(url)
55
+ domain,repo,revision,file_path=[]
56
+ url.split("/").ie do |url_nodes|
57
+ domain = url_nodes[2]
58
+ repo = url_nodes[3..4].join("/")
59
+ revision = url_nodes[5]
60
+ file_path = url_nodes[6..-1].join("/")
61
+ end
62
+ repo_dir = Git.pull(domain,repo,revision)
63
+ full_path = "#{repo_dir}/#{file_path}"
64
+ exists = File.exists?(full_path)
65
+ if exists
66
+ FileUtils.rm_r(repo_dir,:force=>true)
67
+ return exists
68
+ else
69
+ raise "Unable to find #{full_path}"
70
+ end
71
+ end
72
+
73
+ #pulls a git repo and sets it to the specified revision in the
74
+ #specified folder
75
+ def Git.pull(domain,repo,revision,run_dir=Dir.mktmpdir)
76
+ domain_properties = Git.config['domains'][domain]
77
+ user,host,key = ['user','host','key'].map{|k| domain_properties[k]}
78
+ #create folder for repo and command
79
+ run_file_path = run_dir + "/cmd.sh"
80
+ #put together command
81
+ git_prefix = key ? "ssh-add #{Base.root}/#{key};" : ""
82
+ git_suffix = (revision=="HEAD" ? " --depth=1" : "; git checkout -q #{revision}")
83
+ #add keys, clone repo, go to specific revision, execute command
84
+ full_cmd = "cd #{run_dir};#{git_prefix}git clone -q #{user}@#{host}:#{repo}.git#{git_suffix}"
85
+ #put command in file, run ssh-agent bash on it
86
+ File.open(run_file_path,"w") {|f| f.print(full_cmd)}
87
+ run_cmd = "ssh-agent bash #{run_file_path}"
88
+ #run the command, it will return an exception if there are issues
89
+ run_cmd.bash(true)
90
+ repo_name = repo.split("/").last
91
+ repo_dir = "#{run_dir}/#{repo_name}"
92
+ return repo_dir
93
+ end
94
+
95
+ def Git.read_by_dataset_path(dst_path,user_name,*args)
96
+ domain,repo,revision,file_path = []
97
+ dst_path.split("/").ie do |path_nodes|
98
+ domain = path_nodes[0]
99
+ repo = path_nodes[1..2].join("/")
100
+ revision = path_nodes[3]
101
+ file_path = path_nodes[4..-1].join("/")
102
+ end
103
+ #slash in front of path
104
+ repo_dir = Git.pull(domain,repo,revision)
105
+ full_path = "#{repo_dir}/#{file_path}"
106
+ result = "cat #{full_path}".bash(true)
107
+ FileUtils.rm_r(repo_dir,:force=>true)
108
+ return result
109
+ end
110
+ end
111
+ end
@@ -1,45 +1,8 @@
1
1
  module Mobilize
2
2
  module Ssh
3
- def Ssh.config
4
- Base.config('ssh')
5
- end
6
-
7
- def Ssh.tmp_file_dir
8
- Ssh.config['tmp_file_dir']
9
- end
10
-
11
- def Ssh.host(node)
12
- Ssh.config['nodes'][node]['host']
13
- end
14
-
15
- def Ssh.gateway(node)
16
- Ssh.config['nodes'][node]['gateway']
17
- end
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
- def Ssh.nodes
28
- Ssh.config['nodes'].keys
29
- end
30
-
31
- def Ssh.default_node
32
- Ssh.nodes.first
33
- end
34
-
35
- #determine if current machine is on host domain, needs gateway if one is provided and it is not
36
- def Ssh.needs_gateway?(node)
37
- host_domain_name = Ssh.host(node)['name'].split(".")[-2..-1].join(".")
38
- return true if Ssh.gateway(node) and Socket.domain_name != host_domain_name
39
- end
40
-
3
+ #adds convenience methods
4
+ require "#{File.dirname(__FILE__)}/../helpers/ssh_helper"
41
5
  def Ssh.pop_comm_dir(comm_dir,file_hash)
42
- FileUtils.rm_r comm_dir, :force=>true
43
6
  file_hash.each do |fname,fdata|
44
7
  fpath = "#{comm_dir}/#{fname}"
45
8
  #for now, only gz is binary
@@ -50,15 +13,8 @@ module Mobilize
50
13
  return true if file_hash.keys.length>0
51
14
  end
52
15
 
53
- def Ssh.set_key_permissions(key_path)
54
- #makes sure permissions are set as appropriate for ssh key
55
- raise "could not find ssh key at #{key_path}" unless File.exists?(key_path)
56
- File.chmod(0600,key_path) unless File.stat(key_path).mode.to_s(8)[3..5] == "600"
57
- return true
58
- end
59
-
60
16
  # converts a source path or target path to a dst in the context of handler and stage
61
- def Ssh.path_to_dst(path,stage_path)
17
+ def Ssh.path_to_dst(path,stage_path,gdrive_slot)
62
18
  has_handler = true if path.index("://")
63
19
  red_path = path.split("://").last
64
20
  #is user has a handler, their first path node is a node name,
@@ -69,7 +25,7 @@ module Mobilize
69
25
  return Dataset.find_or_create_by_url(ssh_url)
70
26
  end
71
27
  #otherwise, use Gsheet
72
- return Gsheet.path_to_dst(red_path,stage_path)
28
+ return Gsheet.path_to_dst(red_path,stage_path,gdrive_slot)
73
29
  end
74
30
 
75
31
  def Ssh.url_by_path(path,user_name)
@@ -97,7 +53,6 @@ module Mobilize
97
53
  def Ssh.scp(node,from_path,to_path)
98
54
  name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
99
55
  key_path = "#{Base.root}/#{key}"
100
- Ssh.set_key_permissions(key_path)
101
56
  opts = {:port=>(port || 22),:keys=>key_path}
102
57
  if Ssh.needs_gateway?(node)
103
58
  gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
@@ -112,25 +67,30 @@ module Mobilize
112
67
  return true
113
68
  end
114
69
 
115
- def Ssh.run(node,command,user,file_hash={})
116
- key,default_user = Ssh.host(node).ie{|h| ['key','user'].map{|k| h[k]}}
117
- key_path = "#{Base.root}/#{key}"
118
- Ssh.set_key_permissions(key_path)
70
+ def Ssh.run(node,command,user_name,file_hash={},run_params=nil)
71
+ default_user_name = Ssh.host(node)['user']
119
72
  file_hash ||= {}
73
+ run_params ||={}
120
74
  #make sure the dir for this command is clear
121
- comm_md5 = [user,node,command,file_hash.keys.to_s].join.to_md5
122
- comm_dir = "#{Ssh.tmp_file_dir}#{comm_md5}"
123
- #populate comm dir with any files
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
+ #replace any params in the file_hash and command
78
+ run_params.each do |k,v|
79
+ command.gsub!("@#{k}",v)
80
+ file_hash.each do |name,data|
81
+ data.gsub!("@#{k}",v)
82
+ end
83
+ end
84
+ #populate comm dir with any files
124
85
  Ssh.pop_comm_dir(comm_dir,file_hash)
125
- #move any files up to the node
126
- rem_dir = nil
127
86
  #make sure user starts in rem_dir
128
87
  rem_dir = "#{comm_md5}/"
129
88
  #make sure the rem_dir is gone
130
89
  Ssh.fire!(node,"sudo rm -rf #{rem_dir}")
131
90
  if File.exists?(comm_dir)
132
91
  Ssh.scp(node,comm_dir,rem_dir)
133
- FileUtils.rm_r comm_dir, :force=>true
92
+ #make sure comm_dir is removed
93
+ FileUtils.rm_r(comm_dir,:force=>true)
134
94
  else
135
95
  #create folder
136
96
  mkdir_command = "mkdir #{rem_dir}"
@@ -142,9 +102,9 @@ module Mobilize
142
102
  Ssh.write(node,command,cmd_path)
143
103
  full_cmd = "(cd #{rem_dir} && sh #{cmd_file})"
144
104
  #fire_cmd runs sh on cmd_path, optionally with sudo su
145
- if user != default_user
105
+ if user_name != default_user_name
146
106
  #make sure user owns the folder and all files
147
- fire_cmd = %{sudo chown -R #{user} #{rem_dir}; sudo su #{user} -c "#{full_cmd}"}
107
+ fire_cmd = %{sudo chown -R #{user_name} #{rem_dir}; sudo su #{user_name} -c "#{full_cmd}"}
148
108
  rm_cmd = %{sudo rm -rf #{rem_dir}}
149
109
  else
150
110
  fire_cmd = full_cmd
@@ -158,7 +118,6 @@ module Mobilize
158
118
  def Ssh.fire!(node,cmd)
159
119
  name,key,port,user = Ssh.host(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
160
120
  key_path = "#{Base.root}/#{key}"
161
- Ssh.set_key_permissions(key_path)
162
121
  opts = {:port=>(port || 22),:keys=>key_path}
163
122
  response = if Ssh.needs_gateway?(node)
164
123
  gname,gkey,gport,guser = Ssh.gateway(node).ie{|h| ['name','key','port','user'].map{|k| h[k]}}
@@ -188,17 +147,15 @@ module Mobilize
188
147
  def Ssh.write(node,fdata,to_path,binary=false)
189
148
  from_path = Ssh.tmp_file(fdata,binary)
190
149
  Ssh.scp(node,from_path,to_path)
191
- FileUtils.rm from_path
150
+ #make sure local is removed
151
+ FileUtils.rm_r(from_path,:force=>true)
192
152
  return true
193
153
  end
194
154
 
195
155
  def Ssh.tmp_file(fdata,binary=false,fpath=nil)
196
156
  #creates a file under tmp/files with an md5 from the data
197
- tmp_file_path = fpath || "#{Ssh.tmp_file_dir}#{(fdata + Time.now.utc.to_f.to_s).to_md5}"
157
+ tmp_file_path = fpath || "#{Dir.mktmpdir}/#{(fdata + Time.now.utc.to_f.to_s).to_md5}"
198
158
  write_mode = binary ? "wb" : "w"
199
- #make sure folder is created
200
- tmp_file_dir = tmp_file_path.split("/")[0..-2].join("/")
201
- FileUtils.mkdir_p(tmp_file_dir)
202
159
  #write data to path
203
160
  File.open(tmp_file_path,write_mode) {|f| f.print(fdata)}
204
161
  return tmp_file_path
@@ -208,7 +165,7 @@ module Mobilize
208
165
  s = Stage.where(:path=>stage_path).first
209
166
  u = s.job.runner.user
210
167
  user_name = s.params['user']
211
- node = s.params['node']
168
+ node = s.params['node']
212
169
  node = Ssh.default_node unless Ssh.nodes.include?(node)
213
170
  if user_name and !Ssh.sudoers(node).include?(u.name)
214
171
  raise "#{u.name} does not have su permissions for this node"
@@ -218,23 +175,27 @@ module Mobilize
218
175
  return user_name
219
176
  end
220
177
 
221
- def Ssh.file_hash_by_stage_path(stage_path)
178
+ def Ssh.file_hash_by_stage_path(stage_path,gdrive_slot)
222
179
  file_hash = {}
223
180
  s = Stage.where(:path=>stage_path).first
224
181
  u = s.job.runner.user
225
182
  user_name = Ssh.user_name_by_stage_path(stage_path)
226
- s.sources.each do |sdst|
183
+ s.sources(gdrive_slot).each do |sdst|
227
184
  split_path = sdst.path.split("/")
228
185
  #if path is to stage output, name with stage name
229
- file_name = if split_path.last == "out" and
230
- (1..5).to_a.map{|n| "stage#{n.to_s}"}.include?(split_path[-2].to_s)
186
+ file_name = if (split_path.last == "out" and (1..5).to_a.map{|n| "stage#{n.to_s}"}.include?(split_path[-2].to_s))
187
+ #<jobname>/stage1/out
231
188
  "#{split_path[-2]}.out"
189
+ elsif (1..5).to_a.map{|n| "stage#{n.to_s}"}.include?(split_path.last[-6..-1])
190
+ #runner<jobname>stage1
191
+ "#{split_path.last[-6..-1]}.out"
232
192
  else
233
193
  split_path.last
234
194
  end
235
195
  if ["gsheet","gfile"].include?(sdst.handler)
236
196
  #google drive sources are always read as the user
237
- file_hash[file_name] = sdst.read(u.name)
197
+ #with the apportioned slot
198
+ file_hash[file_name] = sdst.read(u.name,gdrive_slot)
238
199
  else
239
200
  #other sources should be read by su-user
240
201
  file_hash[file_name] = sdst.read(user_name)
@@ -244,17 +205,24 @@ module Mobilize
244
205
  end
245
206
 
246
207
  def Ssh.run_by_stage_path(stage_path)
208
+ gdrive_slot = Gdrive.slot_worker_by_path(stage_path)
209
+ #return blank response if there are no slots available
210
+ return nil unless gdrive_slot
247
211
  s = Stage.where(:path=>stage_path).first
248
212
  params = s.params
249
213
  node, command = [params['node'],params['cmd']]
250
214
  node ||= Ssh.default_node
251
215
  user_name = Ssh.user_name_by_stage_path(stage_path)
252
- file_hash = Ssh.file_hash_by_stage_path(stage_path)
253
- result = Ssh.run(node,command,user_name,file_hash)
216
+ file_hash = Ssh.file_hash_by_stage_path(stage_path,gdrive_slot)
217
+ Gdrive.unslot_worker_by_path(stage_path)
218
+ run_params = params['params']
219
+ result = Ssh.run(node,command,user_name,file_hash,run_params)
254
220
  #use Gridfs to cache result
255
221
  response = {}
256
222
  response['out_url'] = Dataset.write_by_url("gridfs://#{s.path}/out",result['stdout'].to_s,Gdrive.owner_name)
257
223
  response['err_url'] = Dataset.write_by_url("gridfs://#{s.path}/err",result['stderr'].to_s,Gdrive.owner_name) if result['stderr'].to_s.length>0
224
+ #is an error if there is no out and there is an err, regardless of signal
225
+ result['exit_code'] = 500 if result['stdout'].to_s.strip.length==0 and result['stderr'].to_s.strip.length>0
258
226
  response['signal'] = result['exit_code']
259
227
  response
260
228
  end
@@ -0,0 +1,37 @@
1
+ module Mobilize
2
+ module Ssh
3
+ def self.config
4
+ Base.config('ssh')
5
+ end
6
+
7
+ def self.host(node)
8
+ self.config['nodes'][node]['host']
9
+ end
10
+
11
+ def self.gateway(node)
12
+ self.config['nodes'][node]['gateway']
13
+ end
14
+
15
+ def self.sudoers(node)
16
+ self.config['nodes'][node]['sudoers']
17
+ end
18
+
19
+ def self.su_all_users(node)
20
+ self.config['nodes'][node]['su_all_users']
21
+ end
22
+
23
+ def self.nodes
24
+ self.config['nodes'].keys
25
+ end
26
+
27
+ def self.default_node
28
+ self.nodes.first
29
+ end
30
+
31
+ #determine if current machine is on host domain, needs gateway if one is provided and it is not
32
+ def self.needs_gateway?(node)
33
+ host_domain_name = self.host(node)['name'].split(".")[-2..-1].join(".")
34
+ return true if self.gateway(node) and Socket.domain_name != host_domain_name
35
+ end
36
+ end
37
+ end
@@ -1,5 +1,5 @@
1
1
  module Mobilize
2
2
  module Ssh
3
- VERSION = "1.2"
3
+ VERSION = "1.3"
4
4
  end
5
5
  end
data/lib/mobilize-ssh.rb CHANGED
@@ -6,10 +6,10 @@ require "net/scp"
6
6
  require "mobilize-ssh/extensions/net-ssh-connection-session"
7
7
  require "mobilize-ssh/extensions/net-ssh-gateway"
8
8
  require "mobilize-ssh/extensions/socket"
9
- require "mobilize-ssh/extensions/string"
10
9
 
11
10
  module Mobilize
12
11
  module Ssh
13
12
  end
14
13
  end
15
14
  require "mobilize-ssh/handlers/ssh"
15
+ require "mobilize-ssh/handlers/git"
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.2"
19
+ gem.add_runtime_dependency "mobilize-base","1.3"
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/code2.sh CHANGED
@@ -1 +1 @@
1
- tail syslog
1
+ tail @file
@@ -14,8 +14,8 @@ describe "Mobilize" do
14
14
 
15
15
  gdrive_slot = Mobilize::Gdrive.owner_email
16
16
  puts "create user 'mobilize'"
17
- user = gdrive_slot.split("@").first
18
- u = Mobilize::User.where(:name=>user).first
17
+ user_name = gdrive_slot.split("@").first
18
+ u = Mobilize::User.where(:name=>user_name).first
19
19
  r = u.runner
20
20
 
21
21
  rb_code_sheet = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/code.rb",gdrive_slot)
@@ -42,6 +42,7 @@ describe "Mobilize" do
42
42
  ssh_target_sheet_1 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_1.out",gdrive_slot)
43
43
  ssh_target_sheet_2 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_2.out",gdrive_slot)
44
44
  ssh_target_sheet_3 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_3.out",gdrive_slot)
45
+ ssh_target_sheet_4 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_4.out",gdrive_slot)
45
46
  [ssh_target_sheet_1,ssh_target_sheet_2,ssh_target_sheet_3].each {|s| s.delete if s}
46
47
 
47
48
  ssh_job_rows = ::YAML.load_file("#{Mobilize::Base.root}/test/ssh_job_rows.yml")
@@ -59,10 +60,12 @@ describe "Mobilize" do
59
60
  ssh_target_sheet_1 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_1.out",gdrive_slot)
60
61
  ssh_target_sheet_2 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_2.out",gdrive_slot)
61
62
  ssh_target_sheet_3 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_3.out",gdrive_slot)
63
+ ssh_target_sheet_4 = Mobilize::Gsheet.find_by_path("#{r.path.split("/")[0..-2].join("/")}/test_ssh_4.out",gdrive_slot)
62
64
 
63
65
  assert ssh_target_sheet_1.to_tsv.length > 100
64
66
  assert ssh_target_sheet_2.to_tsv.length > 100
65
67
  assert ssh_target_sheet_3.to_tsv.length > 3
68
+ assert ssh_target_sheet_4.to_tsv.length > 100
66
69
 
67
70
  end
68
71
 
@@ -1,18 +1,25 @@
1
+ ---
1
2
  - name: test_ssh_1
2
3
  active: true
3
4
  trigger: once
4
5
  status: ""
5
- stage1: 'ssh.run node:"test_node", cmd:"ruby code.rb", user:"root", sources:["code.rb", "code.sh"]'
6
- stage2: 'gsheet.write source:"stage1", target:"test_ssh_1.out"'
6
+ stage1: ssh.run node:"test_node", cmd:"ruby code.rb", user:"root", sources:["code.rb", "code.sh"]
7
+ stage2: gsheet.write source:"stage1", target:"test_ssh_1.out"
7
8
  - name: test_ssh_2
8
9
  active: true
9
10
  trigger: "after test_ssh_1"
10
11
  status: ""
11
- stage1: 'ssh.run cmd:"sh code2.sh", user:"root", sources:["code2.sh","test_node/var/log/syslog"]'
12
- stage2: 'gsheet.write source:"stage1", target:"test_ssh_2.out"'
12
+ stage1: ssh.run cmd:"sh code2.sh", user:"root", sources:["code2.sh","test_node/var/log/syslog"], params:{file:"syslog"}
13
+ stage2: gsheet.write source:"stage1", target:"test_ssh_2.out"
13
14
  - name: test_ssh_3
14
15
  active: true
15
16
  trigger: "after test_ssh_2"
16
17
  status: ""
17
- stage1: 'ssh.run cmd:"whoami"'
18
- stage2: 'gsheet.write source:"stage1", target:"test_ssh_3.out"'
18
+ stage1: ssh.run cmd:"echo '@test_param'", params:{test_param:"test param successful"}
19
+ stage2: gsheet.write source:"stage1", target:"test_ssh_3.out"
20
+ - name: test_ssh_4
21
+ active: true
22
+ trigger: "after test_ssh_3"
23
+ status: ""
24
+ stage1: ssh.run node:"test_node", user:root, sources:["git://DeNA/mobilize-ssh/test/code.rb","git://DeNA/mobilize-ssh/test/code.sh"], cmd:"ruby code.rb"
25
+ stage2: gsheet.write source:stage1, target:"test_ssh_4.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.2'
4
+ version: '1.3'
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-03-21 00:00:00.000000000 Z
12
+ date: 2013-04-18 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.2'
21
+ version: '1.3'
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.2'
29
+ version: '1.3'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: net-ssh
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -91,8 +91,9 @@ files:
91
91
  - lib/mobilize-ssh/extensions/net-ssh-connection-session.rb
92
92
  - lib/mobilize-ssh/extensions/net-ssh-gateway.rb
93
93
  - lib/mobilize-ssh/extensions/socket.rb
94
- - lib/mobilize-ssh/extensions/string.rb
94
+ - lib/mobilize-ssh/handlers/git.rb
95
95
  - lib/mobilize-ssh/handlers/ssh.rb
96
+ - lib/mobilize-ssh/helpers/ssh_helper.rb
96
97
  - lib/mobilize-ssh/tasks.rb
97
98
  - lib/mobilize-ssh/version.rb
98
99
  - lib/samples/ssh.yml
@@ -124,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
124
125
  version: '0'
125
126
  requirements: []
126
127
  rubyforge_project:
127
- rubygems_version: 1.8.24
128
+ rubygems_version: 1.8.25
128
129
  signing_key:
129
130
  specification_version: 3
130
131
  summary: extend mobilize-base with the ability to run files across hosts
@@ -136,4 +137,3 @@ test_files:
136
137
  - test/redis-test.conf
137
138
  - test/ssh_job_rows.yml
138
139
  - test/test_helper.rb
139
- has_rdoc:
@@ -1,5 +0,0 @@
1
- class String
2
- def to_md5
3
- Digest::MD5.hexdigest(self)
4
- end
5
- end