Skip to content

Commit

Permalink
Updates cross compilation server API and cleans up Rust deployment code
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnyman727 committed Jul 13, 2016
1 parent de6f0b2 commit d90f375
Show file tree
Hide file tree
Showing 11 changed files with 374 additions and 77 deletions.
7 changes: 4 additions & 3 deletions bin/tessel-2.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,13 @@ makeCommand('run')
default: false,
help: 'Deploy a project containing all files within, including those not used by the program, excluding any files matched by non-negated rules in .tesselignore and including any files matched by rules in .tesselinclude. Program is started from specified file.'
})
.option('rustCC', {
default: 'localhost:8080',
.option('rustcc', {
// TODO: make this point to a long-lived server somewhere
default: 'http://localhost:8080',
help: 'Specify the location and port of the Rust cross-compilation server.'
})
.help(`
Deploy a script to Tessel and run it.
Deploy an application to Tessel and run it.
Assets that are not directly deployed as a dependency via require analysis,
for example images or html files of an application (and their directories),
Expand Down
4 changes: 1 addition & 3 deletions lib/tessel/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
* Language: *
*
*/
var rust = require('./deployment/rust');

module.exports.app = {
// Note: These should be converted to method shorthand
// once t2-cli moves to Node 6
Expand All @@ -24,7 +22,7 @@ module.exports.js = {
};

module.exports.rs = {
execute: () => [rust.meta.binary],
execute: (filepath, relpath) => [filepath + relpath],
};

module.exports.py = {
Expand Down
122 changes: 77 additions & 45 deletions lib/tessel/deployment/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,26 @@
var path = require('path');
var http = require('http');
var path = require('path');
var url = require('url');

// Third Party Dependencies
var fs = require('fs-extra');
var tags = require('common-tags');
var tar = require('tar');
var toml = require('toml');
require('toml-require').install();
var Reader = require('fstream').Reader;
var tar = require('tar');
var tarStream = require('tar-stream');
var streamToArray = require('stream-to-array');

// Internal
var commands = require('../commands');
var lists = require('./lists/rust');
var Tessel = require('../tessel');
var log = require('../../log');
var Tessel = require('../tessel');

var exportables = {
meta: {
name: 'rust',
extname: 'rs',
// TODO: do not hardcode the binary name
binary: '/tmp/remote-script/hello',
// TODO: do not hardcode the entry
binary: '.',
entry: 'src/main.rs',
configuration: 'Cargo.toml',
checkConfiguration: (pushdir, basename, program) => {
Expand All @@ -41,18 +37,34 @@ var exportables = {
program
};
},
shell: () => {
shell: (opts) => {
return tags.stripIndent `
#!/bin/sh
exec /app/remote-script/${exportables.meta.binary}
exec /app/remote-script/${opts.resolvedEntryPoint}
`;
},
},
lists: lists,
};

exportables.preBundle = function() {
return Promise.resolve();
// The Rust prebundle step just updated the resolvedEntryPoint
// property with the Rust binary name
exportables.preBundle = function(opts) {
return new Promise((resolve, reject) => {
// Get details of the project
var details = exportables.meta.checkConfiguration(opts.target);

// If it was unable to fetch the details
if (typeof details !== 'object') {
// Abort the deploy
return reject('Unable to parse Cargo.toml');
} else {
// Update the resolved entry point to the program name
opts.resolvedEntryPoint = details.program;
// Continue with the deploy
resolve();
}
});
};

// This must implement a Promise that resolves with a Buffer
Expand All @@ -62,68 +74,88 @@ exportables.tarBundle = function(opts) {
return exportables.remoteRustCompilation(opts);
};

// The following line will be ignored by JSHint because
// presently, `options` is not in use, but it's valuable to
// include the parameter in the list.
exportables.preRun = function(tessel, options) { // jshint ignore:line
return new Promise((resolve) => {
return tessel.connection.exec(commands.chmod('+x', `${Tessel.REMOTE_RUN_PATH}${exportables.meta.binary}`), {}, () => resolve());
});
};

/*
exportables.postRun = function(tessel, options) {
return Promise.resolve();
};
*/

exportables.remoteRustCompilation = function(opts) {
log.info('Compiling Rust code...');
// The following line will be ignored by JSHint because
// presently, `opts` is not in use, but it's valuable to
// include the parameter in the list.
exportables.preRun = function(tessel, opts) { // jshint ignore:line
return tessel.simpleExec(commands.chmod('+x', `${Tessel.REMOTE_RUN_PATH}${opts.resolvedEntryPoint}`));
};

exportables.remoteRustCompilation = (opts) => {
log.info('Compiling Rust code remotely...');
return new Promise(function(resolve, reject) {

// Save our incoming compiled buffer to this array
var buffers = [];

var host = opts.rustCC;
var port = '8080';

// Check if the URI has a port like localhost:1234
if (host.includes(':')) {
var parts = opts.rustCC.split(':');
host = parts[0];
port = parts[1];
// Parse out the components of the remote rust compilation server
if (!opts.rustcc.startsWith('http')) {
// Without an HTTP protocol definition, url.parse will fail;
// assume http:// was implied
opts.rustcc = 'http://' + opts.rustcc;
}
var destination = url.parse(opts.rustcc);

// The location of our cross compilation server
var post_options = {
host: host,
port: port,
var options = {
host: destination.hostname,
port: destination.port,
path: '/rust-compile',
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
// TODO: How is this safely resolvable?
// Perhaps parsing opts.resolvedEntryPoint?
'X-BINARY-NAME': 'hello',
'X-PROJECT-FOLDER': path.basename(opts.target),
}
};

// Set up the request
var post_req = http.request(post_options, function(res) {
var req = http.request(options, (res) => {
// When we get incoming binary data, save to our buffers
res.on('data', function(chunk) {
// Write this incoming data to our tar packer
// Write this incoming data to our buffer collection
buffers.push(chunk);
})
// Reject on failure
.on('error', function(e) {
return reject(e);
.on('error', function(postReqError) {
return reject(postReqError);
})
// When the post completes, resolve with the executable
.on('end', function() {
// Resolve with concatenated buffers
return resolve(Buffer.concat(buffers));

// Parse the incoming data as JSON
var result = JSON.parse(Buffer.concat(buffers));

// Check if there was an error message written
if (result.error !== undefined && result.error !== '') {
// If there was, abort with the provided message
return reject(new Error(result.error));
}
// Check if compilation failed via stderr
else if (result.stderr !== null && result.stderr !== '') {
return reject(new Error(result.stderr));
}

// If output from the compilation process was provided
if (result.stdout !== null) {
// Print it out
log.info(result.stdout);
}

// If the binary was not provided
if (result.binary === null) {
// Reject with an error
return reject(new Error('Neither binary nor error returned by cross compilation server.'));
}
// If the binary was provided
else {
// All was successful and we can return
return resolve(new Buffer(result.binary, 'base64'));
}
});
});

Expand All @@ -140,7 +172,7 @@ exportables.remoteRustCompilation = function(opts) {
})
.on('error', reject)
.pipe(outgoingPacker)
.pipe(post_req);
.pipe(req);
});
};

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"homepage": "https://github.com/tessel/t2-cli",
"devDependencies": {
"coveralls": "^2.11.9",
"concat-stream": "^1.5.1",
"grunt": "^0.4.5",
"grunt-cli": "^0.1.13",
"grunt-contrib-jshint": "^0.11.2",
Expand Down Expand Up @@ -71,13 +72,11 @@
"shell-escape": "^0.2.0",
"ssh2": "^0.4.2",
"sshpk": "^1.6.0",
"stream-to-array": "^2.3.0",
"stream-to-buffer": "^0.1.0",
"t2-project": "^0.3.0",
"tar": "^2.1.1",
"tar-stream": "^1.3.0",
"toml": "^2.3.0",
"toml-require": "^1.1.0",
"uglify-js": "^2.6.2",
"update-notifier": "^0.6.3",
"url-join": "0.0.1",
Expand Down Expand Up @@ -115,6 +114,7 @@
"Rahul Ravikumar <rahul@rahulrav.com>",
"Neil Kistner <neil.kistner@gmail.com>",
"Thomas Jansen <thojansen@gmail.com>",
"Scott González <scott.gonzalez@gmail.com>"
"Scott González <scott.gonzalez@gmail.com>",
"Chris Lewis <cflewis@google.com>"
]
}
13 changes: 10 additions & 3 deletions test/.jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@
"bindings": true,
"builtInRulesCount": true,
"cli": true,
"codeContents": true,
"commands": true,
"concat": true,
"controller": true,
"copy": true,
"cp": true,
"createTemporaryDeployCode": true,
"Daemon": true,
"DEPLOY_FILE": true,
"DEPLOY_DIR": true,
"DEPLOY_FILE_JS": true,
"DEPLOY_DIR_JS": true,
"DEPLOY_DIR_RS": true,
"deleteTemporaryDeployCode": true,
"deploy": true,
"deployFile": true,
Expand All @@ -46,15 +47,19 @@
"exports": true,
"extract": true,
"fs": true,
"fstream": true,
"fsTemp": true,
"glob": true,
"http": true,
"Ignore": true,
"inquirer": true,
"init": true,
"initJavaScript": true,
"initPython": true,
"initRust": true,
"IS_TEST_ENV": true,
"jsCodeContents": true,
"jsCodeReference": true,
"lan": true,
"LAN": true,
"log": true,
Expand Down Expand Up @@ -83,10 +88,12 @@
"Tessel": true,
"TesselSeeker": true,
"TesselSimulator": true,
"toml": true,
"Transform": true,
"uglify": true,
"updates": true,
"usb": true,
"url": true,
"USB": true,
"util": true,
"zlib": true
Expand Down
Loading

0 comments on commit d90f375

Please sign in to comment.