mobilize-ssh 1.29 → 1.31

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