mobilize-ssh 1.2 → 1.3

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
@@ -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