Skip to content

Commit 149518e

Browse files
committed
Development checkpoint.
1 parent 84a48f6 commit 149518e

23 files changed

+2087
-165
lines changed

AppService.spec

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ module AppService
7070
typedef structure {
7171
task_id parent_id;
7272
workspace_id workspace;
73-
} start_params;
73+
} StartParams;
7474
funcdef start_app2(app_id, task_parameters params, StartParams start_params)
7575
returns (Task task);
7676

app_specs/Date.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id":"Date",
3-
"script":"App-Date_bob",
3+
"script":"App-Date",
44
"label":"Date",
55
"description":"Returns the current date and time.",
66
"parameters":[

app_specs/Sleep.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,7 @@
1212
"desc": "Time to sleep, in seconds.",
1313
"type": "int"
1414
}
15-
]
15+
],
16+
"default_ram": "1M",
17+
"default_cpu": 1
1618
}

lib/Bio/KBase/AppService/AppScript.pm

+127-62
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,24 @@ use LWP::UserAgent;
1818
use REST::Client;
1919
use Bio::KBase::AppService::AppConfig ':all';
2020

21+
use Getopt::Long::Descriptive;
2122
use base 'Class::Accessor';
2223

2324
use Data::Dumper;
2425

25-
__PACKAGE__->mk_accessors(qw(callback donot_create_job_result donot_create_result_folder
26+
__PACKAGE__->mk_accessors(qw(execute_callback preflight_callback donot_create_job_result donot_create_result_folder
2627
workspace_url workspace params app_definition result_folder
28+
app_def params proc_params stdout_file stderr_file
29+
hostname json
2730
task_id app_service_url));
2831

2932
sub new
3033
{
31-
my($class, $callback) = @_;
34+
my($class, $execute_callback, $preflight_callback) = @_;
3235

3336
my $self = {
34-
callback => $callback,
37+
execute_callback => $execute_callback,
38+
preflight_callback => $preflight_callback,
3539
};
3640
return bless $self, $class;
3741
}
@@ -48,32 +52,28 @@ sub run
4852
{
4953
my($self, $args) = @_;
5054

51-
#
52-
# Hack to finding task id.
53-
#
54-
my $host = `hostname -f`;
55-
$host = `hostname` if !$host;
56-
chomp $host;
55+
$self->set_task_id();
5756

58-
my $task_id = 'TBD';
59-
if ($ENV{AWE_TASK_ID})
60-
{
61-
$task_id = $ENV{AWE_TASK_ID};
62-
}
63-
elsif ($ENV{PWD} =~ /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})_\d+_\d+$/i)
64-
{
65-
$task_id = $1;
66-
}
67-
else
57+
my $opt;
58+
do {
59+
local @ARGV = @$args;
60+
($opt, my $usage) = describe_options("%c %o app-service-url app-definition.json param-values.json [stdout-file stderr-file]",
61+
["preflight", "Run the app in preflight mode. Print a JSON object representing the expected runtime, requested CPU count, and memory use for this application invocation."],
62+
["help|h", "Show this help message."]);
63+
print($usage->text), exit(0) if $opt->help;
64+
die($usage->text) unless @ARGV == 3 or @ARGV == 5;
65+
66+
my $appserv_url = shift @ARGV;
67+
$self->app_service_url($appserv_url);
68+
$args = [@ARGV];
69+
};
70+
71+
$self->process_parameters($args);
72+
73+
if ($opt->preflight)
6874
{
69-
$task_id = "UNK-$host-$$";
75+
return $self->run_preflight();
7076
}
71-
$self->task_id($task_id);
72-
73-
@$args == 3 or @$args == 5 or die "Usage: $0 app-service-url app-definition.json param-values.json [stdout-file stderr-file]\n";
74-
75-
my $appserv_url = shift @$args;
76-
$self->app_service_url($appserv_url);
7777

7878
#
7979
# If we are running at the terminal, do not set up this infrastructure.
@@ -87,7 +87,7 @@ sub run
8787

8888
my $ua = LWP::UserAgent->new();
8989
my $rest = REST::Client->new();
90-
$rest->setHost("$appserv_url/$task_id");
90+
$rest->setHost($self->appservice_url . "/" . $self->task_id);
9191
$self->{rest} = $rest;
9292

9393
my $sel = IO::Select->new();
@@ -110,7 +110,7 @@ sub run
110110
}
111111

112112
$self->write_block("pid", $pid);
113-
$self->write_block("hostname", $host);
113+
$self->write_block("hostname", $self->hostname);
114114

115115
$stdout_pipe->reader();
116116
$stderr_pipe->reader();
@@ -166,17 +166,59 @@ sub run
166166
return $rc;
167167
}
168168

169+
sub run_preflight
170+
{
171+
my($self) = @_;
172+
173+
return unless $self->preflight_callback();
174+
175+
$self->preflight_callback()->($self, $self->app_def, $self->params, $self->proc_params);
176+
}
177+
178+
sub set_task_id
179+
{
180+
my($self) = @_;
181+
182+
#
183+
# Hack to finding task id.
184+
#
185+
my $host = `hostname -f`;
186+
$host = `hostname` if !$host;
187+
chomp $host;
188+
$self->hostname($host);
189+
190+
my $task_id = 'TBD';
191+
if ($ENV{AWE_TASK_ID})
192+
{
193+
$task_id = $ENV{AWE_TASK_ID};
194+
}
195+
elsif ($ENV{SLURM_JOB_ID})
196+
{
197+
$task_id = $ENV{SLURM_JOB_ID};
198+
}
199+
elsif ($ENV{PWD} =~ /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})_\d+_\d+$/i)
200+
{
201+
$task_id = $1;
202+
}
203+
else
204+
{
205+
$task_id = "UNK-$host-$$";
206+
}
207+
$self->task_id($task_id);
208+
}
209+
169210
sub write_block
170211
{
171212
my($self, $path, $data) = @_;
172213
$self->{rest}->POST($path, $data);
173214
}
174215

175-
sub subproc_run
216+
sub process_parameters
176217
{
177218
my($self, $args) = @_;
178219

179220
my $json = JSON::XS->new->pretty(1)->relaxed(1);
221+
$self->json($json);
180222

181223
my $app_def_file = shift @$args;
182224
my $params_file = shift @$args;
@@ -185,8 +227,31 @@ sub subproc_run
185227
my $stderr_file = shift @$args;
186228

187229
my $app_def = $json->decode(scalar read_file($app_def_file));
188-
my $params = $json->decode(scalar read_file($params_file));
189230

231+
my $params_txt;
232+
my $params_from_cmdline;
233+
my $file_error;
234+
if (open(my $fh, "<", $params_file))
235+
{
236+
$params_txt = read_file($fh);
237+
}
238+
else
239+
{
240+
$file_error = $!;
241+
# for immediate-mode testing, allow specification of params as inline text.
242+
$params_from_cmdline = 1;
243+
$params_txt = $params_file;
244+
}
245+
246+
my $params = eval { $json->decode($params_txt); };
247+
if (!$params)
248+
{
249+
die "Error reading or parsing params (file error $!; parse error $@)";
250+
}
251+
if (ref($params) ne 'HASH')
252+
{
253+
die "Invalid parameters (must be JSON object)";
254+
}
190255
#
191256
# Preprocess parameters to create hash of named parameters, looking for
192257
# missing required values and filling in defaults.
@@ -224,68 +289,63 @@ sub subproc_run
224289
{
225290
die "Errors found in parameter processing:\n " . join("\n ", @errors), "\n";
226291
}
292+
293+
$self->app_def($app_def);
294+
$self->params($params);
295+
$self->proc_params(\%proc_param);
296+
$self->stdout_file($stdout_file);
297+
$self->stderr_file($stderr_file);
227298

299+
}
300+
301+
sub subproc_run
302+
{
303+
my($self, $args) = @_;
304+
228305
my $ws = Bio::P3::Workspace::WorkspaceClientExt->new($self->workspace_url);
229306
$self->{workspace} = $ws;
230-
$self->{params} = \%proc_param;
231-
$self->{app_definition} = $app_def;
232307

233308
if (!defined($self->donot_create_result_folder()) || $self->donot_create_result_folder() == 0) {
234309
$self->create_result_folder();
235310
}
236-
237-
my $host = `hostname -f`;
238-
$host = `hostname` if !$host;
239-
chomp $host;
240311
my $start_time = gettimeofday;
241312

242313
my $job_output;
243-
if ($stdout_file)
314+
if ($self->stdout_file)
244315
{
245-
my $stdout_fh = IO::File->new($stdout_file, "w+");
246-
my $stderr_fh = IO::File->new($stderr_file, "w+");
316+
my $stdout_fh = IO::File->new($self->stdout_file, "w+");
317+
my $stderr_fh = IO::File->new($self->stderr_file, "w+");
247318

248-
capture(sub { $job_output = $self->callback->($self, $app_def, $params, \%proc_param) } , stdout => $stdout_fh, stderr => $stderr_fh);
319+
capture(sub { $job_output = $self->execute_callback->($self, $self->app_def, $self->params, $self->proc_params) } , stdout => $stdout_fh, stderr => $stderr_fh);
249320
}
250321
else
251322
{
252-
$job_output = $self->callback->($self, $app_def, $params, \%proc_param);
323+
$job_output = $self->execute_callback->($self, $self->app_def, $self->params, $self->proc_params);
253324
}
254325

255-
if (!defined($self->donot_create_result_folder()) || $self->donot_create_result_folder() == 0)
326+
if ($self->params->{output_path} && $self->params->{output_path} && !$self->donot_create_result_folder())
256327
{
257328
my $end_time = gettimeofday;
258329
my $elap = $end_time - $start_time;
259330

260331
my $files = $ws->ls({ paths => [ $self->result_folder ], recursive => 1});
261332

262-
#
263-
# Hack to finding task id.
264-
#
265-
my $task_id = 'TBD';
266-
if ($ENV{PWD} =~ /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})_\d+_\d+$/i)
267-
{
268-
$task_id = $1;
269-
}
270-
else
271-
{
272-
$task_id = "Not found in '$ENV{PWD}'";
273-
}
333+
my $task_id = $self->task_id;
274334

275335
my $job_obj = {
276336
id => $task_id,
277-
app => $app_def,
278-
parameters => \%proc_param,
337+
app => $self->app_def,
338+
parameters => $self->roc_params,
279339
start_time => $start_time,
280340
end_time => $end_time,
281341
elapsed_time => $elap,
282-
hostname => $host,
342+
hostname => $self->hostname,
283343
output_files => [ map { [ $_->[2] . $_->[0], $_->[4] ] } @{$files->{$self->result_folder}}],
284344
job_output => $job_output,
285345
};
286346

287347
my $file = $self->params->{output_path} . "/" . $self->params->{output_file};
288-
$ws->save_data_to_file($json->encode($job_obj), {}, $file, 'job_result',1);
348+
$ws->save_data_to_file($self->json->encode($job_obj), {}, $file, 'job_result',1);
289349
}
290350
delete $self->{workspace};
291351
}
@@ -295,10 +355,15 @@ sub create_result_folder
295355
{
296356
my($self) = @_;
297357

298-
my $base_folder = $self->params->{output_path};
299-
my $result_folder = $base_folder . "/." . $self->params->{output_file};
300-
$self->result_folder($result_folder);
301-
$self->workspace->create({overwrite => 1, objects => [[$result_folder, 'folder', { application_type => $self->app_definition->{id}}]]});
358+
my $params = $self->params;
359+
360+
if ($params->{output_path} && $params->{output_file})
361+
{
362+
my $base_folder = $params->{output_path};
363+
my $result_folder = $base_folder . "/." . $params->{output_file};
364+
$self->result_folder($result_folder);
365+
$self->workspace->create({overwrite => 1, objects => [[$result_folder, 'folder', { application_type => $self->app_definition->{id}}]]});
366+
}
302367
}
303368

304369
sub token

0 commit comments

Comments
 (0)