mortar 0.4.4 → 0.5.0
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 +1 -1
- data/lib/mortar/command/clusters.rb +19 -0
- data/lib/mortar/command/illustrate.rb +3 -0
- data/lib/mortar/command/jobs.rb +8 -3
- data/lib/mortar/templates/pigscript/pigscript.pig +7 -5
- data/lib/mortar/templates/project/pigscripts/pigscript.pig +7 -5
- data/lib/mortar/version.rb +1 -1
- data/spec/mortar/command/clusters_spec.rb +23 -0
- data/spec/mortar/command/jobs_spec.rb +43 -6
- metadata +9 -9
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Mortar Development Framework
|
2
2
|
|
3
|
-
Mortar is a platform as a service for Hadoop. With Mortar, you can run jobs on Hadoop using Apache Pig and Python without any special training.
|
3
|
+
[Mortar](http://www.mortardata.com/) is a platform as a service for Hadoop. With Mortar, you can run jobs on Hadoop using Apache Pig and Python without any special training.
|
4
4
|
|
5
5
|
The Mortar Development Framework lets you develop Mortar Hadoop jobs directly on your local computer without installing any Hadoop libraries. Lots more info can be found on the [Mortar help site](http://help.mortardata.com).
|
6
6
|
|
@@ -37,4 +37,23 @@ class Mortar::Command::Clusters < Mortar::Command::Base
|
|
37
37
|
end
|
38
38
|
|
39
39
|
end
|
40
|
+
|
41
|
+
# clusters: stop CLUSTER_ID
|
42
|
+
#
|
43
|
+
# Stop a running cluster.
|
44
|
+
#
|
45
|
+
def stop
|
46
|
+
cluster_id = shift_argument
|
47
|
+
unless cluster_id
|
48
|
+
error("Usage: mortar clusters:stop CLUSTER_ID\nMust specify CLUSTER_ID.")
|
49
|
+
end
|
50
|
+
|
51
|
+
response = api.stop_cluster(cluster_id) .body
|
52
|
+
|
53
|
+
if response['message'].nil?
|
54
|
+
display("Stopping cluster #{cluster_id}.")
|
55
|
+
else
|
56
|
+
display(response['message'])
|
57
|
+
end
|
58
|
+
end
|
40
59
|
end
|
@@ -40,9 +40,12 @@ class Mortar::Command::Illustrate < Mortar::Command::Base
|
|
40
40
|
pigscript_name = shift_argument
|
41
41
|
alias_name = shift_argument
|
42
42
|
skip_pruning = options[:skippruning] ||= false
|
43
|
+
|
44
|
+
# TODO: When illustrating without alias works, remove the `&& alias_name` to re-enable the feature on CLI
|
43
45
|
unless pigscript_name && alias_name
|
44
46
|
error("Usage: mortar illustrate PIGSCRIPT ALIAS\nMust specify PIGSCRIPT and ALIAS.")
|
45
47
|
end
|
48
|
+
|
46
49
|
validate_arguments!
|
47
50
|
validate_git_based_project!
|
48
51
|
pigscript = validate_pigscript!(pigscript_name)
|
data/lib/mortar/command/jobs.rb
CHANGED
@@ -60,6 +60,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
60
60
|
# -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)
|
61
61
|
# -p, --parameter NAME=VALUE # Set a pig parameter value in your script.
|
62
62
|
# -f, --param-file PARAMFILE # Load pig parameter values from a file.
|
63
|
+
# -d, --donotnotify # Don't send an email on job completion. (Default: false--an email will be sent to you once the job completes)
|
63
64
|
#
|
64
65
|
#Examples:
|
65
66
|
#
|
@@ -74,7 +75,8 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
74
75
|
validate_arguments!
|
75
76
|
|
76
77
|
unless options[:clusterid] || options[:clustersize]
|
77
|
-
|
78
|
+
options[:clustersize] = 2
|
79
|
+
display("Defaulting to running job on new cluster of size 2")
|
78
80
|
end
|
79
81
|
|
80
82
|
if options[:clusterid]
|
@@ -88,6 +90,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
88
90
|
validate_git_based_project!
|
89
91
|
pigscript = validate_pigscript!(pigscript_name)
|
90
92
|
git_ref = create_and_push_snapshot_branch(git, project)
|
93
|
+
notify_on_job_finish = ! options[:donotnotify]
|
91
94
|
|
92
95
|
# post job to API
|
93
96
|
response = action("Requesting job execution") do
|
@@ -96,11 +99,13 @@ class Mortar::Command::Jobs < Mortar::Command::Base
|
|
96
99
|
keepalive = ! options[:singlejobcluster]
|
97
100
|
api.post_job_new_cluster(project.name, pigscript.name, git_ref, cluster_size,
|
98
101
|
:parameters => pig_parameters,
|
99
|
-
:keepalive => keepalive
|
102
|
+
:keepalive => keepalive,
|
103
|
+
:notify_on_job_finish => notify_on_job_finish).body
|
100
104
|
else
|
101
105
|
cluster_id = options[:clusterid]
|
102
106
|
api.post_job_existing_cluster(project.name, pigscript.name, git_ref, cluster_id,
|
103
|
-
:parameters => pig_parameters
|
107
|
+
:parameters => pig_parameters,
|
108
|
+
:notify_on_job_finish => notify_on_job_finish).body
|
104
109
|
end
|
105
110
|
end
|
106
111
|
|
@@ -1,11 +1,13 @@
|
|
1
1
|
/**
|
2
2
|
* <%= script_name %>
|
3
|
-
*
|
4
|
-
* Required parameters:
|
5
|
-
*
|
6
|
-
* - INPUT_PATH Input path for script data (e.g. s3n://hawk-example-data/tutorial/excite.log.bz2)
|
7
|
-
* - OUTPUT_PATH Output path for script data (e.g. s3n://my-output-bucket/<%= script_name %>)
|
8
3
|
*/
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Parameters - set default values here; you can override with -p on the command-line.
|
7
|
+
*/
|
8
|
+
|
9
|
+
<%= '%default'%> INPUT_PATH 's3n://hawk-example-data/tutorial/excite.log.bz2'
|
10
|
+
<%= '%default'%> OUTPUT_PATH 's3n://my-output-bucket/$MORTAR_EMAIL_S3_ESCAPED/<%= script_name %>'
|
9
11
|
|
10
12
|
<% if not options[:skip_udf] %>
|
11
13
|
/**
|
@@ -1,11 +1,13 @@
|
|
1
1
|
/**
|
2
2
|
* <%= project_name %>
|
3
|
-
*
|
4
|
-
* Required parameters:
|
5
|
-
*
|
6
|
-
* - INPUT_PATH Input path for script data (e.g. s3n://hawk-example-data/tutorial/excite.log.bz2)
|
7
|
-
* - OUTPUT_PATH Output path for script data (e.g. s3n://my-output-bucket/<%= project_name %>)
|
8
3
|
*/
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Parameters - set default values here; you can override with -p on the command-line.
|
7
|
+
*/
|
8
|
+
|
9
|
+
<%= '%default'%> INPUT_PATH 's3n://hawk-example-data/tutorial/excite.log.bz2'
|
10
|
+
<%= '%default'%> OUTPUT_PATH 's3n://my-output-bucket/$MORTAR_EMAIL_S3_ESCAPED/<%= project_name %>'
|
9
11
|
|
10
12
|
/**
|
11
13
|
* User-Defined Functions (UDFs)
|
data/lib/mortar/version.rb
CHANGED
@@ -56,5 +56,28 @@ There are no running or recent clusters
|
|
56
56
|
STDOUT
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
60
|
+
context("stop") do
|
61
|
+
it "Stops a running cluster with default message" do
|
62
|
+
cluster_id = "1234abcd"
|
63
|
+
mock(Mortar::Auth.api).stop_cluster(cluster_id) {Excon::Response.new(:body => {"success" => true})}
|
64
|
+
|
65
|
+
stderr, stdout = execute("clusters:stop #{cluster_id}")
|
66
|
+
stdout.should == <<-STDOUT
|
67
|
+
Stopping cluster #{cluster_id}.
|
68
|
+
STDOUT
|
69
|
+
end
|
70
|
+
|
71
|
+
it "Stops a running cluster with server message" do
|
72
|
+
cluster_id = "1234abcd"
|
73
|
+
message = "some awesome message"
|
74
|
+
mock(Mortar::Auth.api).stop_cluster(cluster_id) {Excon::Response.new(:body => {"success" => true, "message" => message})}
|
75
|
+
|
76
|
+
stderr, stdout = execute("clusters:stop #{cluster_id}")
|
77
|
+
stdout.should == "#{message}\n"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
59
81
|
end
|
82
|
+
|
60
83
|
end
|
@@ -48,7 +48,8 @@ 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
|
-
:keepalive => false
|
51
|
+
:keepalive => false,
|
52
|
+
:notify_on_job_finish => true) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
52
53
|
|
53
54
|
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
54
55
|
stderr, stdout = execute("jobs:run my_script -1 --clustersize 5 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
|
@@ -79,7 +80,8 @@ STDOUT
|
|
79
80
|
|
80
81
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
81
82
|
:parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]),
|
82
|
-
:keepalive => true
|
83
|
+
:keepalive => true,
|
84
|
+
:notify_on_job_finish => true) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
83
85
|
|
84
86
|
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
85
87
|
stderr, stdout = execute("jobs:run my_script --clustersize 5 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
|
@@ -101,6 +103,39 @@ STDOUT
|
|
101
103
|
end
|
102
104
|
end
|
103
105
|
|
106
|
+
it "runs a job with no cluster defined" do
|
107
|
+
with_git_initialized_project do |p|
|
108
|
+
job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
|
109
|
+
job_url = "http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5"
|
110
|
+
cluster_size = 2
|
111
|
+
|
112
|
+
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
113
|
+
:parameters => [],
|
114
|
+
:keepalive => true,
|
115
|
+
:notify_on_job_finish => true) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
116
|
+
|
117
|
+
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
118
|
+
stderr, stdout = execute("jobs:run my_script ", p, @git)
|
119
|
+
stdout.should == <<-STDOUT
|
120
|
+
Defaulting to running job on new cluster of size 2
|
121
|
+
Taking code snapshot... done
|
122
|
+
Sending code snapshot to Mortar... done
|
123
|
+
Requesting job execution... done
|
124
|
+
job_id: c571a8c7f76a4fd4a67c103d753e2dd5
|
125
|
+
|
126
|
+
Job status can be viewed on the web at:
|
127
|
+
|
128
|
+
http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5
|
129
|
+
|
130
|
+
Or by running:
|
131
|
+
|
132
|
+
mortar jobs:status c571a8c7f76a4fd4a67c103d753e2dd5 --poll
|
133
|
+
|
134
|
+
STDOUT
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
104
139
|
it "runs a job on an existing cluster" do
|
105
140
|
with_git_initialized_project do |p|
|
106
141
|
# stub api requests
|
@@ -108,10 +143,10 @@ STDOUT
|
|
108
143
|
job_url = "http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5"
|
109
144
|
cluster_id = "e2790e7e8c7d48e39157238d58191346"
|
110
145
|
|
111
|
-
mock(Mortar::Auth.api).post_job_existing_cluster("myproject", "my_script", is_a(String), cluster_id, :parameters => []) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
146
|
+
mock(Mortar::Auth.api).post_job_existing_cluster("myproject", "my_script", is_a(String), cluster_id, :parameters => [], :notify_on_job_finish => false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
|
112
147
|
|
113
148
|
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
114
|
-
stderr, stdout = execute("jobs:run my_script --clusterid e2790e7e8c7d48e39157238d58191346", p, @git)
|
149
|
+
stderr, stdout = execute("jobs:run my_script --clusterid e2790e7e8c7d48e39157238d58191346 -d", p, @git)
|
115
150
|
stdout.should == <<-STDOUT
|
116
151
|
Taking code snapshot... done
|
117
152
|
Sending code snapshot to Mortar... done
|
@@ -138,7 +173,8 @@ STDOUT
|
|
138
173
|
|
139
174
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
140
175
|
:parameters => match_array([{"name" => "FIRST", "value" => "FOO"}, {"name" => "SECOND", "value" => "BAR"}, {"name" => "THIRD", "value" => "BEAR\n"}]),
|
141
|
-
:keepalive => true
|
176
|
+
:keepalive => true,
|
177
|
+
:notify_on_job_finish => true) {Excon::Response.new(:body => {"job_id" => job_id})}
|
142
178
|
|
143
179
|
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
144
180
|
|
@@ -162,7 +198,8 @@ PARAMS
|
|
162
198
|
|
163
199
|
mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
|
164
200
|
:parameters => match_array([{"name" => "FIRST", "value" => "FOO"}, {"name" => "SECOND", "value" => "BAR"}, {"name" => "THIRD", "value" => "BEAR\n"}]),
|
165
|
-
:keepalive => true
|
201
|
+
:keepalive => true,
|
202
|
+
:notify_on_job_finish => true) {Excon::Response.new(:body => {"job_id" => job_id})}
|
166
203
|
|
167
204
|
write_file(File.join(p.pigscripts_path, "my_script.pig"))
|
168
205
|
|
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: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 5
|
9
|
+
- 0
|
10
|
+
version: 0.5.0
|
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:
|
18
|
+
date: 2013-01-17 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: 11
|
29
29
|
segments:
|
30
30
|
- 0
|
31
|
-
-
|
32
|
-
-
|
33
|
-
version: 0.
|
31
|
+
- 5
|
32
|
+
- 0
|
33
|
+
version: 0.5.0
|
34
34
|
type: :runtime
|
35
35
|
version_requirements: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|