mobilize-ssh 1.29 → 1.31

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,67 @@ 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 user, which is the user used for the git clone command.
173
+ * a set of repo keys (optional) which correspond to "deploy keys" on
174
+ github. Each repo must have its own ssh key, and the public key must be
175
+ stored in the repo.
176
+ * if your repo doesn't need an ssh key to work, this is not necessary
177
+ to add.
178
+
179
+
180
+ Sample git.yml:
181
+
182
+ ``` yml
183
+ ---
184
+ development:
185
+ domains:
186
+ private:
187
+ host: github.private.com
188
+ user: git
189
+ repo_keys:
190
+ "repo_path_1": 'local/path/to/key1'
191
+ "repo_path_2": 'local/path/to/key1'
192
+ public:
193
+ host: github.com
194
+ user: git
195
+ test:
196
+ domains:
197
+ public:
198
+ host: github.com
199
+ user: git
200
+ private:
201
+ host: github.private.com
202
+ user: git
203
+ repo_keys:
204
+ "repo_path_1": 'local/path/to/key1'
205
+ "repo_path_2": 'local/path/to/key1'
206
+ production:
207
+ domains:
208
+ private:
209
+ host: github.private.com
210
+ user: git
211
+ repo_keys:
212
+ "repo_path_1": 'local/path/to/key1'
213
+ "repo_path_2": 'local/path/to/key1'
214
+ public:
215
+ host: github.com
216
+ user: git
217
+ ```
218
+
219
+
164
220
  <a name='section_Start'></a>
165
221
  Start
166
222
  -----
@@ -169,10 +225,21 @@ Start
169
225
  ### Create Job
170
226
 
171
227
  * 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.
228
+ * 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.
229
+ * user, sources, node, and params are optional; cmd is required.
174
230
  * specifying user will cause the command to be prefixed with sudo su <user> -c.
175
231
  * non-google sources will also be read as the specified user.
232
+ * git sources can be specified with syntax `git://<domain>/<repo_owner>/<repo_name>/<file_path>`.
233
+ * Accessing private repos requires that you add the Mobilize public key to the repository as a deploy key.
234
+ * there is no user-level access control for git repositories at this time.
235
+ * domain defaults to the first one listed, if not included.
236
+ * params are also optional for all of the below. They replace tokens in sources and the command.
237
+ * params are passed as a YML or JSON, as in:
238
+ * `ssh.run source:<source_path>, params:{'date':'2013-03-01', 'unit':'widgets'}`
239
+ * this example replaces all the keys, preceded by '@' in all source hqls with the value.
240
+ * The preceding '@' is used to keep from replacing instances
241
+ of "date" and "unit" in the command/source file; you should have `@date` and `@unit` in your actual HQL
242
+ if you'd like to replace those tokens.
176
243
  * not specifying node will cause the command to be run on the default node.
177
244
  * ssh sources can be specified with syntax
178
245
  `ssh://<node><file_full_path>`. If node is omitted, default node will be used.
@@ -0,0 +1,120 @@
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
+ def Git.repo_key(domain,repo)
20
+ begin
21
+ Git.config['domains'][domain]['repo_keys'][repo]
22
+ rescue
23
+ nil #no key for public repos
24
+ end
25
+ end
26
+
27
+ # converts a source path or target path to a dst in the context of handler and stage
28
+ def Git.path_to_dst(path,stage_path,gdrive_slot)
29
+ red_path = path.split("://").last
30
+ git_url = Git.url_by_path(red_path)
31
+ return Dataset.find_or_create_by_url(git_url)
32
+ end
33
+
34
+ def Git.url_by_path(path)
35
+ path_nodes = path.split("/")
36
+ domain = path_nodes.first.to_s
37
+ revision = "HEAD"
38
+ if Git.domains.include?(domain)
39
+ repo = path_nodes[1..2].join("/")
40
+ file_path = path_nodes[3..-1].join("/")
41
+ else
42
+ domain = Git.default_domain
43
+ repo = path_nodes[0..1].join("/")
44
+ file_path = path_nodes[2..-1].join("/")
45
+ end
46
+ url = "git://#{domain}/#{repo}/#{revision}/#{file_path}"
47
+ return url
48
+ end
49
+
50
+ #return path to tar.gz of git repo
51
+ def Git.pack(domain,repo,revision="HEAD")
52
+ repo_dir = Git.pull(domain,repo,revision)
53
+ repo_name = repo.split("/").last
54
+ tar_gz_path = "#{repo_dir}/../#{repo_name}.tar.gz"
55
+ pack_cmd = "cd #{repo_dir} && git archive #{revision} --format=tar.gz > #{tar_gz_path}"
56
+ pack_cmd.bash(true)
57
+ FileUtils.rm_r(repo_dir,:force=>true)
58
+ return tar_gz_path
59
+ end
60
+
61
+ #confirm that git file exists
62
+ def Git.exists?(url)
63
+ domain,repo,revision,file_path=[]
64
+ url.split("/").ie do |url_nodes|
65
+ domain = url_nodes[2]
66
+ repo = url_nodes[3..4].join("/")
67
+ revision = url_nodes[5]
68
+ file_path = url_nodes[6..-1].join("/")
69
+ end
70
+ repo_dir = Git.pull(domain,repo,revision)
71
+ full_path = "#{repo_dir}/#{file_path}"
72
+ exists = File.exists?(full_path)
73
+ if exists
74
+ FileUtils.rm_r(repo_dir,:force=>true)
75
+ return exists
76
+ else
77
+ raise "Unable to find #{full_path}"
78
+ end
79
+ end
80
+
81
+ #pulls a git repo and sets it to the specified revision in the
82
+ #specified folder
83
+ def Git.pull(domain,repo,revision,run_dir=Dir.mktmpdir)
84
+ domain_properties = Git.config['domains'][domain]
85
+ user,host= ['user','host'].map{|k| domain_properties[k]}
86
+ key = Git.repo_key(domain,repo)
87
+ #create folder for repo and command
88
+ run_file_path = run_dir + "/cmd.sh"
89
+ #put together command
90
+ git_prefix = key ? "ssh-add #{Base.root}/#{key};" : ""
91
+ git_suffix = (revision=="HEAD" ? " --depth=1" : "; git checkout -q #{revision}")
92
+ #add keys, clone repo, go to specific revision, execute command
93
+ full_cmd = "cd #{run_dir};#{git_prefix}git clone -q #{user}@#{host}:#{repo}.git#{git_suffix}"
94
+ #put command in file, run ssh-agent bash on it
95
+ File.open(run_file_path,"w") {|f| f.print(full_cmd)}
96
+ run_cmd = "ssh-agent bash #{run_file_path}"
97
+ #run the command, it will return an exception if there are issues
98
+ run_cmd.bash(true)
99
+ repo_name = repo.split("/").last
100
+ repo_dir = "#{run_dir}/#{repo_name}"
101
+ return repo_dir
102
+ end
103
+
104
+ def Git.read_by_dataset_path(dst_path,user_name,*args)
105
+ domain,repo,revision,file_path = []
106
+ dst_path.split("/").ie do |path_nodes|
107
+ domain = path_nodes[0]
108
+ repo = path_nodes[1..2].join("/")
109
+ revision = path_nodes[3]
110
+ file_path = path_nodes[4..-1].join("/")
111
+ end
112
+ #slash in front of path
113
+ repo_dir = Git.pull(domain,repo,revision)
114
+ full_path = "#{repo_dir}/#{file_path}"
115
+ result = "cat #{full_path}".bash(true)
116
+ FileUtils.rm_r(repo_dir,:force=>true)
117
+ return result
118
+ end
119
+ end
120
+ 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,13 +13,6 @@ 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
17
  def Ssh.path_to_dst(path,stage_path,gdrive_slot)
62
18
  has_handler = true if path.index("://")
@@ -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"
@@ -226,9 +183,12 @@ module Mobilize
226
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
@@ -255,11 +215,14 @@ module Mobilize
255
215
  user_name = Ssh.user_name_by_stage_path(stage_path)
256
216
  file_hash = Ssh.file_hash_by_stage_path(stage_path,gdrive_slot)
257
217
  Gdrive.unslot_worker_by_path(stage_path)
258
- result = Ssh.run(node,command,user_name,file_hash)
218
+ run_params = params['params']
219
+ result = Ssh.run(node,command,user_name,file_hash,run_params)
259
220
  #use Gridfs to cache result
260
221
  response = {}
261
222
  response['out_url'] = Dataset.write_by_url("gridfs://#{s.path}/out",result['stdout'].to_s,Gdrive.owner_name)
262
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
263
226
  response['signal'] = result['exit_code']
264
227
  response
265
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.29"
3
+ VERSION = "1.31"
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"
@@ -0,0 +1,34 @@
1
+ ---
2
+ development:
3
+ domains:
4
+ private:
5
+ host: github.private.com
6
+ user: git
7
+ repo_keys:
8
+ "repo_path_1": 'local/path/to/key1'
9
+ "repo_path_2": 'local/path/to/key1'
10
+ public:
11
+ host: github.com
12
+ user: git
13
+ test:
14
+ domains:
15
+ public:
16
+ host: github.com
17
+ user: git
18
+ private:
19
+ host: github.private.com
20
+ user: git
21
+ repo_keys:
22
+ "repo_path_1": 'local/path/to/key1'
23
+ "repo_path_2": 'local/path/to/key1'
24
+ production:
25
+ domains:
26
+ private:
27
+ host: github.private.com
28
+ user: git
29
+ repo_keys:
30
+ "repo_path_1": 'local/path/to/key1'
31
+ "repo_path_2": 'local/path/to/key1'
32
+ public:
33
+ host: github.com
34
+ user: git
data/lib/samples/ssh.yml CHANGED
@@ -1,6 +1,5 @@
1
1
  ---
2
2
  development:
3
- tmp_file_dir: tmp/file/
4
3
  nodes:
5
4
  dev_node:
6
5
  sudoers:
@@ -17,7 +16,6 @@ development:
17
16
  port: 22
18
17
  user: gateway_user
19
18
  test:
20
- tmp_file_dir: tmp/file/
21
19
  nodes:
22
20
  test_node:
23
21
  sudoers:
@@ -34,7 +32,6 @@ test:
34
32
  port: 22
35
33
  user: gateway_user
36
34
  production:
37
- tmp_file_dir: tmp/file/
38
35
  nodes:
39
36
  prod_node:
40
37
  sudoers:
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.29"
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,69 +1,78 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobilize-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: '1.29'
4
+ version: '1.31'
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Cassio Paes-Leme
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-03-27 00:00:00.000000000 Z
12
+ date: 2013-04-18 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: mobilize-base
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - '='
18
20
  - !ruby/object:Gem::Version
19
- version: '1.29'
21
+ version: '1.3'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - '='
25
28
  - !ruby/object:Gem::Version
26
- version: '1.29'
29
+ version: '1.3'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: net-ssh
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - '>='
35
+ - - ! '>='
32
36
  - !ruby/object:Gem::Version
33
37
  version: '0'
34
38
  type: :runtime
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - '>='
43
+ - - ! '>='
39
44
  - !ruby/object:Gem::Version
40
45
  version: '0'
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: net-scp
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
- - - '>='
51
+ - - ! '>='
46
52
  - !ruby/object:Gem::Version
47
53
  version: '0'
48
54
  type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
- - - '>='
59
+ - - ! '>='
53
60
  - !ruby/object:Gem::Version
54
61
  version: '0'
55
62
  - !ruby/object:Gem::Dependency
56
63
  name: net-ssh-gateway
57
64
  requirement: !ruby/object:Gem::Requirement
65
+ none: false
58
66
  requirements:
59
- - - '>='
67
+ - - ! '>='
60
68
  - !ruby/object:Gem::Version
61
69
  version: '0'
62
70
  type: :runtime
63
71
  prerelease: false
64
72
  version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
65
74
  requirements:
66
- - - '>='
75
+ - - ! '>='
67
76
  - !ruby/object:Gem::Version
68
77
  version: '0'
69
78
  description: mobilize-ssh allows you to automate ssh commands and files across hosts
@@ -82,10 +91,12 @@ files:
82
91
  - lib/mobilize-ssh/extensions/net-ssh-connection-session.rb
83
92
  - lib/mobilize-ssh/extensions/net-ssh-gateway.rb
84
93
  - lib/mobilize-ssh/extensions/socket.rb
85
- - lib/mobilize-ssh/extensions/string.rb
94
+ - lib/mobilize-ssh/handlers/git.rb
86
95
  - lib/mobilize-ssh/handlers/ssh.rb
96
+ - lib/mobilize-ssh/helpers/ssh_helper.rb
87
97
  - lib/mobilize-ssh/tasks.rb
88
98
  - lib/mobilize-ssh/version.rb
99
+ - lib/samples/git.yml
89
100
  - lib/samples/ssh.yml
90
101
  - mobilize-ssh.gemspec
91
102
  - test/code.rb
@@ -97,26 +108,33 @@ files:
97
108
  - test/test_helper.rb
98
109
  homepage: http://github.com/dena/mobilize-ssh
99
110
  licenses: []
100
- metadata: {}
101
111
  post_install_message:
102
112
  rdoc_options: []
103
113
  require_paths:
104
114
  - lib
105
115
  required_ruby_version: !ruby/object:Gem::Requirement
116
+ none: false
106
117
  requirements:
107
- - - '>='
118
+ - - ! '>='
108
119
  - !ruby/object:Gem::Version
109
120
  version: '0'
121
+ segments:
122
+ - 0
123
+ hash: -1792437726743818090
110
124
  required_rubygems_version: !ruby/object:Gem::Requirement
125
+ none: false
111
126
  requirements:
112
- - - '>='
127
+ - - ! '>='
113
128
  - !ruby/object:Gem::Version
114
129
  version: '0'
130
+ segments:
131
+ - 0
132
+ hash: -1792437726743818090
115
133
  requirements: []
116
134
  rubyforge_project:
117
- rubygems_version: 2.0.3
135
+ rubygems_version: 1.8.25
118
136
  signing_key:
119
- specification_version: 4
137
+ specification_version: 3
120
138
  summary: extend mobilize-base with the ability to run files across hosts
121
139
  test_files:
122
140
  - test/code.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: ab5d4bcff9f392506c76c0685ca82796ca9683b5
4
- data.tar.gz: 1f722cc3f065c0f586124f36ccc3b4fe30664382
5
- SHA512:
6
- metadata.gz: 07c7407655e448f6d961a271bb6d491ab8e61cec75000c21af9937450e535eb764b394a42b3de5852354a4c80f089cc2af8d0445eaefbcfbdf8eb1e45ff05c46
7
- data.tar.gz: 71073a430e5aee47305e05f671af47693af7661f3c1f0a6226f18e3298b123870059a82aa9a38fbb8cc602e4b3cdb357e9a6dc24a2aa9b70deed65a070533708
@@ -1,5 +0,0 @@
1
- class String
2
- def to_md5
3
- Digest::MD5.hexdigest(self)
4
- end
5
- end