Skip to content
This repository was archived by the owner on Jun 6, 2023. It is now read-only.

Commit 8892824

Browse files
committed
cli mode: tail job logs automatically, show job states while in transition, and init project if none
1 parent 54dd42a commit 8892824

File tree

1 file changed

+81
-14
lines changed

1 file changed

+81
-14
lines changed

lib/jobs/create.js

Lines changed: 81 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,21 @@
33
var method = require('./../method');
44
var assign = require('lodash.assign');
55
var path = require('path');
6+
var mkdirp = require('mkdirp');
67
var async = require('async');
78
var os = require('os');
89
var fs = require('fs');
910
var archiver = require('archiver');
1011
var ProgressBar = require('progress');
1112
var projectConfig = require('./../projectConfig');
13+
var jobs_logs = require('./../jobs/logs.js');
14+
var jobs_waitfor = require('./../jobs/waitfor.js');
15+
var jobs_show = require('./../jobs/show.js');
1216

1317
/**
1418
* @memberof jobs
1519
* @method create
16-
* @description Create a new Paperspace job.
20+
* @description Create a new Paperspace job, and tail its log output if run at the command line. To disable the tailing behavior specify '--tail false'. Note: if a project is not defined for the current working directory, and you are running in command line mode, a project configuration settings file will be created. Use '--init false' or specify '--project [projectname]' to override this behavior.
1721
* @param {object} params - Job creation parameters
1822
* @param {string} params.container - A required reference to a container name or container link to be used for the job.
1923
* @param {string} [params.machineType] - An optional machine type to run the job on: either 'GPU+', 'P4000', 'P5000', 'P6000', 'V100', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'C8', 'C9', or 'C10'.<p>Defaults to 'GPU+'.
@@ -23,6 +27,7 @@ var projectConfig = require('./../projectConfig');
2327
* @param {string} [params.command] - An optional command to run within the workspace or container.
2428
* @param {string} [params.workspace] - An optional path to a workspace, or link to a git repository to upload and merge with the container. If a zip file name is provided it is uploaded instead. If no workspace is provided the current directory is zipped up and transferred. If the workspace is 'none', no workspace is merged and the container is run as-is.
2529
* @param {string} [params.dataset] - An optional reference to a dataset to be merged with the container.
30+
* @param {boolean} [params.tail] - Optional; defaults to true in command line mode only. Specify false to disable automatic tailing.
2631
* @param {boolean} [params.json] - Optional; if true, do not write progress to standard out. '--json' with no value is equivalent to true.
2732
* @param {function} cb - Node-style error-first callback function
2833
* @returns {object} job - The created job JSON object
@@ -118,6 +123,27 @@ function directorySize(path, cb, size) {
118123
var MAX_UPLOAD_SIZE = 104857600; // 100MB
119124

120125
function create(params, cb) {
126+
var json = false;
127+
if (params.json) {
128+
json = true;
129+
// Note: we don't delete params.json because lib/request.js needs to examine it to determine if upload progress should be displayed
130+
}
131+
var init = true;
132+
if (params.init) {
133+
init = params.init;
134+
delete params.init;
135+
}
136+
var tail = global.paperspace_cli && !json; // tail defaults to true in cli mode, false otherwise;
137+
if (typeof params.tail === 'boolean') {
138+
tail = params.tail;
139+
delete params.tail;
140+
}
141+
142+
// XXX TODO trim leading/trailing spaces from input paths
143+
// XXX TODO whitelist git services
144+
// XXX TODO convert to gzip
145+
// XXX TODO stream compress
146+
121147
var cwd = process.cwd();
122148
if (!params.project && !params.projectId) {
123149
// default to name of project in .ps_project/config.json or name of current directory
@@ -127,18 +153,28 @@ function create(params, cb) {
127153
if (params.project === '/') {
128154
return ifCliPrintErrorOnly(new Error('Error: cannot create project from root dir. Please create a project dir and run from there.'));
129155
}
156+
if (global.paperspace_cli && !json && init) {
157+
var config = { 'project': params.project };
158+
var configDir = path.resolve(cwd, '.ps_project');
159+
if (!fs.existsSync(configDir)) mkdirp.sync(configDir);
160+
else if (!fs.statSync(configDir).isDirectory()) {
161+
return ifCliPrintErrorOnly(new Error('Error: existing file with same name as .ps_project directory.'));
162+
}
163+
164+
var configFileName = path.resolve(configDir, 'config.json');
165+
if (fs.existsSync(configFileName) && !fs.statSync(configFileName).isFile()) {
166+
return ifCliPrintErrorOnly(new Error('Error: config file not accessible: ' + configFileName));
167+
}
168+
169+
fs.writeFileSync(configFileName, JSON.stringify(config, null, 2) + '\n');
170+
171+
// refresh projectConfig state
172+
params.project = projectConfig.getProject();
173+
174+
console.log('New project name: ' + params.project);
175+
}
130176
}
131177
}
132-
var json = false;
133-
if (params.json) {
134-
json = true;
135-
// Note: we don't delete params.json because lib/request.js needs to examine it to determine if upload progress should be displayed
136-
}
137-
138-
// XXX TODO trim leading/trailing spaces from input paths
139-
// XXX TODO whitelist git services
140-
// XXX TODO convert to gzip
141-
// XXX TODO stream compress
142178

143179
if (!params.workspace) params.workspace = cwd;
144180

@@ -150,6 +186,37 @@ function create(params, cb) {
150186
return cb(err);
151187
}
152188

189+
function maybeTailLogs(err, resp) {
190+
if (global.paperspace_cli && !json && tail) {
191+
if (err) return cb(err);
192+
if (!resp.body || !resp.body.id) return new Error('Job create failed; job id not found.');
193+
var jobId = resp.body.id;
194+
console.log('New jobId: ' + resp.body.id);
195+
console.log('Job ' + resp.body.state);
196+
if (resp.body.state === 'Pending') console.log('Waiting for job to run...');
197+
return jobs_waitfor({ jobId: jobId, state: 'Running' }, function _waitforCb(err, resp) {
198+
if (err) return cb(err);
199+
if (!resp.body || !resp.body.state) return new Error('Job state not found.');
200+
var state = resp.body.state;
201+
console.log('Job ' + state);
202+
if (state === 'Stopped' && !state === 'Failed' && !state === 'Running') {
203+
return cb();
204+
}
205+
console.log('Awaiting logs...');
206+
return jobs_logs({ jobId: jobId, tail: true }, function _logsCb(err, resp) {
207+
if (err) return cb(err);
208+
return jobs_show({ jobId: jobId }, function _showCb(err, resp) {
209+
if (err) return cb(err);
210+
if (!resp.body || !resp.body.state) return new Error('Job state not found.');
211+
console.log('Job ' + resp.body.state + (resp.body.exitCode || resp.body.exitCode === 0 ? ', exitCode ' + resp.body.exitCode : ''));
212+
return cb();
213+
});
214+
});
215+
});
216+
}
217+
return cb(err, resp);
218+
}
219+
153220
// don't allow zipping of the root directory
154221
if (params.workspace === '/') {
155222
return ifCliPrintErrorOnly(new Error('Error: cannot zip workspace from root directory.'));
@@ -199,7 +266,7 @@ function create(params, cb) {
199266
return method(create, params, function _methodCb(err, resp) {
200267
if (err) return cb(err);
201268
if (resp.body) projectConfig.setLastJobId(resp.body.project, resp.body.id);
202-
return cb(err, resp);
269+
return maybeTailLogs(err, resp);
203270
});
204271
});
205272

@@ -270,7 +337,7 @@ function create(params, cb) {
270337
return method(create, params, function _methodCb(err, resp) {
271338
if (err) return cb(err);
272339
if (resp.body) projectConfig.setLastJobId(resp.body.project, resp.body.id);
273-
return cb(err, resp);
340+
return maybeTailLogs(err, resp);
274341
});
275342
}
276343
} else {
@@ -284,7 +351,7 @@ function create(params, cb) {
284351
return method(create, params, function _methodCb(err, resp) {
285352
if (err) return cb(err);
286353
if (resp.body) projectConfig.setLastJobId(resp.body.project, resp.body.id);
287-
return cb(err, resp);
354+
return maybeTailLogs(err, resp);
288355
});
289356
}
290357
}

0 commit comments

Comments
 (0)