mortar 0.7.2 → 0.7.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/lib/mortar/command/jobs.rb
CHANGED
@@ -23,6 +23,10 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
23
23
|
|
24
24
|
include Mortar::Git
|
25
25
|
|
26
|
+
CLUSTER_TYPE__SINGLE_JOB = 'single_job'
|
27
|
+
CLUSTER_TYPE__PERSISTENT = 'persistent'
|
28
|
+
CLUSTER_TYPE__PERMANENT = 'permanent'
|
29
|
+
|
26
30
|
# jobs
|
27
31
|
#
|
28
32
|
# Show recent and running jobs.
|
@@ -57,6 +61,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
57
61
|
# -c, --clusterid CLUSTERID # Run job on an existing cluster with ID of CLUSTERID (optional)
|
58
62
|
# -s, --clustersize NUMNODES # Run job on a new cluster, with NUMNODES nodes (optional; must be >= 2 if provided)
|
59
63
|
# -1, --singlejobcluster # Stop the cluster after job completes. (Default: false—-cluster can be used for other jobs, and will shut down after 1 hour of inactivity)
|
64
|
+
# -2, --permanentcluster # Don't automatically stop the cluster after it has been idle for an hour (Default: false--cluster will be shut down after 1 hour of inactivity)
|
60
65
|
# -p, --parameter NAME=VALUE # Set a pig parameter value in your script.
|
61
66
|
# -f, --param-file PARAMFILE # Load pig parameter values from a file.
|
62
67
|
# -d, --donotnotify # Don't send an email on job completion. (Default: false--an email will be sent to you once the job completes)
|
@@ -102,7 +107,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
102
107
|
end
|
103
108
|
|
104
109
|
if options[:clusterid]
|
105
|
-
[:clustersize, :singlejobcluster].each do |opt|
|
110
|
+
[:clustersize, :singlejobcluster, :permanentcluster].each do |opt|
|
106
111
|
unless options[opt].nil?
|
107
112
|
error("Option #{opt.to_s} cannot be set when running a job on an existing cluster (with --clusterid option)")
|
108
113
|
end
|
@@ -116,11 +121,19 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
116
121
|
# post job to API
|
117
122
|
response = action("Requesting job execution") do
|
118
123
|
if options[:clustersize]
|
124
|
+
if options[:singlejobcluster] && options[:permanentcluster]
|
125
|
+
error("Cannot declare cluster as both --singlejobcluster and --permanentcluster")
|
126
|
+
end
|
119
127
|
cluster_size = options[:clustersize].to_i
|
120
|
-
|
128
|
+
cluster_type = CLUSTER_TYPE__PERSISTENT
|
129
|
+
if options[:singlejobcluster]
|
130
|
+
cluster_type = CLUSTER_TYPE__SINGLE_JOB
|
131
|
+
elsif options[:permanentcluster]
|
132
|
+
cluster_type = CLUSTER_TYPE__PERMANENT
|
133
|
+
end
|
121
134
|
api.post_job_new_cluster(project.name, script.name, git_ref, cluster_size,
|
122
135
|
:parameters => pig_parameters,
|
123
|
-
:
|
136
|
+
:cluster_type => cluster_type,
|
124
137
|
:notify_on_job_finish => notify_on_job_finish,
|
125
138
|
:is_control_script => is_control_script).body
|
126
139
|
else
|
@@ -22,7 +22,7 @@ require "mortar/local/jython"
|
|
22
22
|
|
23
23
|
|
24
24
|
class Mortar::Local::Controller
|
25
|
-
include Mortar::
|
25
|
+
include Mortar::Local::InstallUtil
|
26
26
|
|
27
27
|
NO_JAVA_ERROR_MESSAGE = <<EOF
|
28
28
|
A suitable java installation could not be found. If you already have java installed
|
@@ -42,8 +42,8 @@ https://pypi.python.org/pypi/virtualenv
|
|
42
42
|
EOF
|
43
43
|
|
44
44
|
NO_AWS_KEYS_ERROR_MESSAGE = <<EOF
|
45
|
-
Please specify your aws access key via
|
46
|
-
and your aws secret key via
|
45
|
+
Please specify your aws access key via environment variable AWS_ACCESS_KEY
|
46
|
+
and your aws secret key via environment variable AWS_SECRET_KEY"
|
47
47
|
EOF
|
48
48
|
|
49
49
|
|
@@ -91,6 +91,19 @@ EOF
|
|
91
91
|
|
92
92
|
jy = Mortar::Local::Jython.new()
|
93
93
|
jy.install_or_update()
|
94
|
+
|
95
|
+
ensure_local_install_dir_in_gitignore
|
96
|
+
end
|
97
|
+
|
98
|
+
def ensure_local_install_dir_in_gitignore()
|
99
|
+
if File.exists? local_project_gitignore
|
100
|
+
open(local_project_gitignore, 'r+') do |gitignore|
|
101
|
+
unless gitignore.read().include? local_install_directory_name
|
102
|
+
gitignore.seek(0, IO::SEEK_END)
|
103
|
+
gitignore.puts local_install_directory_name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
94
107
|
end
|
95
108
|
|
96
109
|
# Main entry point for user running a pig script
|
@@ -28,10 +28,26 @@ module Mortar
|
|
28
28
|
|
29
29
|
include Mortar::Helpers
|
30
30
|
|
31
|
-
def
|
31
|
+
def local_install_directory_name
|
32
|
+
".mortar-local"
|
33
|
+
end
|
34
|
+
|
35
|
+
def project_root
|
32
36
|
# note: assumes that CWD is the project root, is
|
33
37
|
# this a safe assumption?
|
34
|
-
|
38
|
+
Dir.getwd
|
39
|
+
end
|
40
|
+
|
41
|
+
def local_install_directory
|
42
|
+
File.join(project_root, local_install_directory_name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def local_pig_logfile
|
46
|
+
project_root + "/local-pig.log"
|
47
|
+
end
|
48
|
+
|
49
|
+
def local_project_gitignore
|
50
|
+
project_root + "/.gitignore"
|
35
51
|
end
|
36
52
|
|
37
53
|
def jython_directory
|
@@ -42,6 +58,10 @@ module Mortar
|
|
42
58
|
jython_directory + "/cachedir"
|
43
59
|
end
|
44
60
|
|
61
|
+
def gitignore_template_path
|
62
|
+
File.expand_path("../../templates/project/gitignore", __FILE__)
|
63
|
+
end
|
64
|
+
|
45
65
|
# Drops a marker file for an installed package, used
|
46
66
|
# to help determine if updates should be performed
|
47
67
|
def note_install(subdirectory)
|
data/lib/mortar/local/pig.rb
CHANGED
@@ -224,6 +224,7 @@ class Mortar::Local::Pig
|
|
224
224
|
# get it to do something interesting, such as '-f some-file.pig'
|
225
225
|
def run_pig_command(cmd, parameters = nil, jython_output = true)
|
226
226
|
unset_hadoop_env_vars
|
227
|
+
delete_local_log_file
|
227
228
|
# Generate the script for running the command, then
|
228
229
|
# write it to a temp script which will be exectued
|
229
230
|
script_text = script_for_command(cmd, parameters)
|
@@ -243,6 +244,12 @@ class Mortar::Local::Pig
|
|
243
244
|
ENV['HADOOP_CONF_DIR'] = ''
|
244
245
|
end
|
245
246
|
|
247
|
+
def delete_local_log_file
|
248
|
+
if File.exists? local_pig_logfile
|
249
|
+
FileUtils.rm local_pig_logfile
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
246
253
|
# Generates a bash script which sets up the necessary environment and
|
247
254
|
# then runs the pig command
|
248
255
|
def script_for_command(cmd, parameters, jython_output = true)
|
@@ -278,6 +285,7 @@ class Mortar::Local::Pig
|
|
278
285
|
opts['fs.s3n.awsAccessKeyId'] = ENV['AWS_ACCESS_KEY']
|
279
286
|
opts['fs.s3n.awsSecretAccessKey'] = ENV['AWS_SECRET_KEY']
|
280
287
|
opts['pig.events.logformat'] = PIG_LOG_FORMAT
|
288
|
+
opts['pig.logfile'] = local_pig_logfile
|
281
289
|
opts['python.verbose'] = 'error'
|
282
290
|
opts['jython.output'] = true
|
283
291
|
opts['python.home'] = jython_directory
|
data/lib/mortar/version.rb
CHANGED
@@ -48,7 +48,7 @@ module Mortar::Command
|
|
48
48
|
|
49
49
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
50
50
|
:parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]),
|
51
|
-
:
|
51
|
+
:cluster_type => Jobs::CLUSTER_TYPE__SINGLE_JOB,
|
52
52
|
:notify_on_job_finish => true,
|
53
53
|
:is_control_script=> false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
54
54
|
|
@@ -71,7 +71,64 @@ Or by running:
|
|
71
71
|
STDOUT
|
72
72
|
end
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
|
+
it "handles permanentcluster parameter" do
|
76
|
+
with_git_initialized_project do |p|
|
77
|
+
# stub api requests
|
78
|
+
job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
|
79
|
+
job_url = "http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5"
|
80
|
+
cluster_size = 5
|
81
|
+
|
82
|
+
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
83
|
+
:parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]),
|
84
|
+
:cluster_type => Jobs::CLUSTER_TYPE__PERMANENT,
|
85
|
+
:notify_on_job_finish => true,
|
86
|
+
:is_control_script=> false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
87
|
+
|
88
|
+
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
89
|
+
stderr, stdout = execute("jobs:run my_script -2 --clustersize 5 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
|
90
|
+
stdout.should == <<-STDOUT
|
91
|
+
Taking code snapshot... done
|
92
|
+
Sending code snapshot to Mortar... done
|
93
|
+
Requesting job execution... done
|
94
|
+
job_id: c571a8c7f76a4fd4a67c103d753e2dd5
|
95
|
+
|
96
|
+
Job status can be viewed on the web at:
|
97
|
+
|
98
|
+
http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5
|
99
|
+
|
100
|
+
Or by running:
|
101
|
+
|
102
|
+
mortar jobs:status c571a8c7f76a4fd4a67c103d753e2dd5 --poll
|
103
|
+
|
104
|
+
STDOUT
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
it "throws error on singlejobcluster and permanentcluster" do
|
110
|
+
with_git_initialized_project do |p|
|
111
|
+
|
112
|
+
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
113
|
+
stderr, stdout = execute("jobs:run my_script -2 -1 --clustersize 5 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
|
114
|
+
stderr.should == <<-STDERR
|
115
|
+
! Cannot declare cluster as both --singlejobcluster and --permanentcluster
|
116
|
+
STDERR
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it "throws error on clusterid and permanentcluster" do
|
121
|
+
with_git_initialized_project do |p|
|
122
|
+
cluster_id = "e2790e7e8c7d48e39157238d58191346"
|
123
|
+
|
124
|
+
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
125
|
+
stderr, stdout = execute("jobs:run my_script -2 --clusterid e2790e7e8c7d48e39157238d58191346 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
|
126
|
+
stderr.should == <<-STDERR
|
127
|
+
! Option permanentcluster cannot be set when running a job on an existing cluster (with --clusterid option)
|
128
|
+
STDERR
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
75
132
|
it "runs a job on a new cluster" do
|
76
133
|
with_git_initialized_project do |p|
|
77
134
|
# stub api requests
|
@@ -81,7 +138,7 @@ STDOUT
|
|
81
138
|
|
82
139
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
83
140
|
:parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]),
|
84
|
-
:
|
141
|
+
:cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
|
85
142
|
:notify_on_job_finish => true,
|
86
143
|
:is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
87
144
|
|
@@ -146,7 +203,7 @@ STDOUT
|
|
146
203
|
mock(Mortar::Auth.api).get_clusters() {Excon::Response.new(:body => {'clusters' => []})}
|
147
204
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
148
205
|
:parameters => [],
|
149
|
-
:
|
206
|
+
:cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
|
150
207
|
:notify_on_job_finish => true,
|
151
208
|
:is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
152
209
|
|
@@ -262,11 +319,10 @@ STDOUT
|
|
262
319
|
with_git_initialized_project do |p|
|
263
320
|
job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
|
264
321
|
cluster_size = 5
|
265
|
-
keepalive = true
|
266
322
|
|
267
323
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
268
324
|
:parameters => match_array([{"name" => "FIRST", "value" => "FOO"}, {"name" => "SECOND", "value" => "BAR"}, {"name" => "THIRD", "value" => "BEAR\n"}]),
|
269
|
-
:
|
325
|
+
:cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
|
270
326
|
:notify_on_job_finish => true,
|
271
327
|
:is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id})}
|
272
328
|
|
@@ -288,11 +344,10 @@ PARAMS
|
|
288
344
|
with_git_initialized_project do |p|
|
289
345
|
job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
|
290
346
|
cluster_size = 5
|
291
|
-
keepalive = true
|
292
347
|
|
293
348
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
294
349
|
:parameters => match_array([{"name" => "FIRST", "value" => "FOO"}, {"name" => "SECOND", "value" => "BAR"}, {"name" => "THIRD", "value" => "BEAR\n"}]),
|
295
|
-
:
|
350
|
+
:cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
|
296
351
|
:notify_on_job_finish => true,
|
297
352
|
:is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id})}
|
298
353
|
|
@@ -315,7 +370,6 @@ PARAMS
|
|
315
370
|
with_git_initialized_project do |p|
|
316
371
|
job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
|
317
372
|
cluster_size = 5
|
318
|
-
keepalive = true
|
319
373
|
|
320
374
|
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
321
375
|
|
@@ -140,6 +140,9 @@ STDERR
|
|
140
140
|
any_instance_of(Mortar::Local::Jython) do |j|
|
141
141
|
mock(j).install_or_update.returns(true)
|
142
142
|
end
|
143
|
+
any_instance_of(Mortar::Local::Controller) do |j|
|
144
|
+
mock(j).ensure_local_install_dir_in_gitignore.returns(true)
|
145
|
+
end
|
143
146
|
stderr, stdout = execute("local:configure")
|
144
147
|
stderr.should == ""
|
145
148
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mortar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 7
|
9
|
-
-
|
10
|
-
version: 0.7.
|
9
|
+
- 3
|
10
|
+
version: 0.7.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Mortar Data
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-03-
|
18
|
+
date: 2013-03-29 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: mortar-api-ruby
|
@@ -25,12 +25,12 @@ dependencies:
|
|
25
25
|
requirements:
|
26
26
|
- - ~>
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
hash:
|
28
|
+
hash: 1
|
29
29
|
segments:
|
30
30
|
- 0
|
31
31
|
- 6
|
32
|
-
-
|
33
|
-
version: 0.6.
|
32
|
+
- 3
|
33
|
+
version: 0.6.3
|
34
34
|
type: :runtime
|
35
35
|
version_requirements: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|