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.
@@ -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
- keepalive = ! options[:singlejobcluster]
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
- :keepalive => keepalive,
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::Helpers
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 enviroment variable AWS_ACCESS_KEY
46
- and your aws secret key via enviroment variable AWS_SECRET_KEY"
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 local_install_directory
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
- File.join(Dir.getwd, ".mortar-local")
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)
@@ -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
@@ -16,5 +16,5 @@
16
16
 
17
17
  module Mortar
18
18
  # see http://semver.org/
19
- VERSION = "0.7.2"
19
+ VERSION = "0.7.3"
20
20
  end
@@ -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
- :keepalive => false,
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
- :keepalive => true,
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
- :keepalive => true,
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
- :keepalive => true,
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
- :keepalive => true,
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: 7
4
+ hash: 5
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 7
9
- - 2
10
- version: 0.7.2
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-26 00:00:00 Z
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: 7
28
+ hash: 1
29
29
  segments:
30
30
  - 0
31
31
  - 6
32
- - 0
33
- version: 0.6.0
32
+ - 3
33
+ version: 0.6.3
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency