Skip to content

Commit

Permalink
Check if remote hosts are reachable before making requests. Fixes gh-…
Browse files Browse the repository at this point in the history
…1051

Fails with error that indicates the issue
  • Loading branch information
rwaldron committed Oct 27, 2016
1 parent ecb81fc commit 130b1bd
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 176 deletions.
47 changes: 25 additions & 22 deletions lib/crash-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ var log = require('./log');
var Menu = require('./menu');
var packageJson = require('../package.json');
var Preferences = require('./preferences');
var remote = require('./remote');

// the value of the crash reporter preference
// the value has to be one of 'on' or 'off'
Expand All @@ -18,7 +19,7 @@ var CRASH_REPORTER_PROMPT = 'crash.reporter.prompt';
var CRASH_PROMPT_MESSAGE = `\nSubmit Crash Report to help Tessel Developers improve the CLI ?
If yes(y), subsequent crashes will be submitted automatically.`;

var CRASH_REPORTER_BASE_URL = 'http://crash-reporter.tessel.io';
var CRASH_REPORTER_BASE_URL = `http://${remote.CRASH_REPORTER_HOSTNAME}`;

// override for testing
if (process.env.DEV_MODE === 'true') {
Expand Down Expand Up @@ -149,30 +150,32 @@ CrashReporter.post = function(labels, crash, argv) {
var url = SUBMIT_CRASH_URL;

return new Promise((resolve, reject) => {
request.post({
url,
form: {
argv,
crash,
labels,
f
}
}, (error, httpResponse, body) => {
try {
if (error) {
reject(error);
} else {
var json = JSON.parse(body);
if (json.error) {
reject(json.error);
remote.ifReachable(remote.CRASH_REPORTER_HOSTNAME).then(() => {
request.post({
url,
form: {
argv,
crash,
labels,
f
}
}, (error, httpResponse, body) => {
try {
if (error) {
reject(error);
} else {
resolve(json.crash_report.fingerprint);
var json = JSON.parse(body);
if (json.error) {
reject(json.error);
} else {
resolve(json.crash_report.fingerprint);
}
}
} catch (exception) {
reject(exception);
}
} catch (exception) {
reject(exception);
}
});
});
}).catch(reject);
});
};

Expand Down
50 changes: 25 additions & 25 deletions lib/install/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,17 @@ var tar = require('tar-fs');

// Internal
var log = require('../log');
var remote = require('../remote');

var SDK_PATHS = {
const SDK_PATHS = {
sdk: path.join(osenv.home(), '.tessel/sdk'),
rustlib: path.join(osenv.home(), '.tessel/rust'),
};

var SDK_URLS = {
macos: 'https://builds.tessel.io/t2/sdk/t2-sdk-macos-x86_64.tar.bz2',
linux: 'https://builds.tessel.io/t2/sdk/t2-sdk-linux-x86_64.tar.bz2',
const SDK_URLS = {
macos: `https://${remote.BUILDS_HOSTNAME}/t2/sdk/t2-sdk-macos-x86_64.tar.bz2`,
linux: `https://${remote.BUILDS_HOSTNAME}/t2/sdk/t2-sdk-linux-x86_64.tar.bz2`,
};

var RUST_LIB_TGZ_URL = 'https://builds.tessel.io/t2/sdk/t2-rustlib-VERSION.tar.gz';

// Get the platform identifier. This actually conforms to the list of OSes
// Rust supports, not the value of process.platform, so we need to convert it.
// See: https://doc.rust-lang.org/std/env/consts/constant.OS.html
Expand Down Expand Up @@ -186,31 +184,33 @@ module.exports.installTools = () => {
var url = SDK_URLS[getPlatform()];
var checksumVerify = null;

return downloadString(`${url}.sha256`)
.then((checksum) => {
checksumVerify = checksum;
return exports.checkTools(checksumVerify);
})
.then((check) => {
if (check.exists && check.isVerified) {
log.info(`Latest ${pkgname} already installed.`);
return;
} else if (!check.exists) {
log.info(`Installing ${pkgname}...`);
} else {
log.info(`Updating ${pkgname}...`);
}
return remote.ifReachable(remote.BUILDS_HOSTNAME).then(() => {
return downloadString(`${url}.sha256`)
.then((checksum) => {
checksumVerify = checksum;
return exports.checkTools(checksumVerify);
})
.then((check) => {
if (check.exists && check.isVerified) {
log.info(`Latest ${pkgname} already installed.`);
return;
} else if (!check.exists) {
log.info(`Installing ${pkgname}...`);
} else {
log.info(`Updating ${pkgname}...`);
}

fs.mkdirpSync(path.join(osenv.home(), '.tessel/sdk'));
return extractTools(checksumVerify, path.basename(url), download(url));
});
fs.mkdirpSync(path.join(osenv.home(), '.tessel/sdk'));
return extractTools(checksumVerify, path.basename(url), download(url));
});
});
};

module.exports.installRustlib = () => {
return exports.rustVersion()
.then((rustv) => {
var pkgname = `MIPS libstd v${rustv}`;
var url = RUST_LIB_TGZ_URL.replace('VERSION', rustv);
var url = `https://${remote.BUILDS_HOSTNAME}/t2/sdk/t2-rustlib-${rustv}.tar.gz`;
var checksumVerify;

return downloadString(url + '.sha256')
Expand Down
24 changes: 24 additions & 0 deletions lib/remote.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
var dns = require('dns');

const remote = {
CRASH_REPORTER_HOSTNAME: 'crash-reporter.tessel.io',
BUILDS_HOSTNAME: 'builds.tessel.io',
PACKAGES_HOSTNAME: 'packages.tessel.io',
RUSTCC_HOSTNAME: 'rustcc.tessel.io',

ifReachable(url) {
return new Promise((resolve, reject) => {
dns.lookup(url, error => {
if (error) {
reject(new Error('This operation requires an internet connection'));
} else {
resolve();
}
});
});
},
};



module.exports = remote;
29 changes: 16 additions & 13 deletions lib/tessel/deployment/javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ var lists = require('./lists/javascript');
var log = require('../../log');
// Necessary to ensure that the next line has had the LOCAL_AUTH_PATH descriptor added.
var provision = require('../provision'); // jshint ignore:line
var remote = require('../../remote');
var Tessel = require('../tessel');

var binaryModulesUsed = new Map();
var isWindows = process.platform.startsWith('win');

const BINARY_SERVER_ROOT = 'http://packages.tessel.io/npm/';
const BINARY_SERVER_ROOT = `http://${remote.PACKAGES_HOSTNAME}/npm/`;
const BINARY_CACHE_PATH = path.join(Tessel.LOCAL_AUTH_PATH, 'binaries');

var exportables = {
Expand Down Expand Up @@ -295,18 +296,20 @@ exportables.resolveBinaryModules = function(opts) {
}
});

request({
url: url,
gzip: true,
})
.pipe(gunzip)
.pipe(extract)
.on('error', reject)
.on('end', () => {
// Once complete, the locally cached binary can
// be found in ~/.tessel/binaries
resolve();
});
remote.ifReachable(remote.PACKAGES_HOSTNAME).then(() => {
request({
url: url,
gzip: true,
})
.pipe(gunzip)
.pipe(extract)
.on('error', reject)
.on('end', () => {
// Once complete, the locally cached binary can
// be found in ~/.tessel/binaries
resolve();
});
}).catch(reject);
});
}
});
Expand Down
138 changes: 71 additions & 67 deletions lib/tessel/deployment/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var Reader = fstream.Reader;
var commands = require('../commands');
var lists = require('./lists/rust');
var log = require('../../log');
var remote = require('../../remote');
var rust = require('../../install/rust');
var Tessel = require('../tessel');

Expand Down Expand Up @@ -101,7 +102,7 @@ exportables.preRun = function(tessel, opts) { // jshint ignore:line

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

// Save our incoming compiled buffer to this array
var buffers = [];
Expand All @@ -110,7 +111,7 @@ exportables.remoteRustCompilation = (opts) => {
if (!opts.rustcc.startsWith('http')) {
// Without an HTTP protocol definition, url.parse will fail;
// assume http:// was implied
opts.rustcc = 'http://' + opts.rustcc;
opts.rustcc = `http://${opts.rustcc}`;
}
var destination = url.parse(opts.rustcc);

Expand All @@ -125,74 +126,77 @@ exportables.remoteRustCompilation = (opts) => {
}
};

// Set up the request
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 buffer collection
buffers.push(chunk);
remote.ifReachable(destination.hostname).then(() => {
// Set up the request
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 buffer collection
buffers.push(chunk);
})
// Reject on failure
.on('error', function(postReqError) {
return reject(postReqError);
})
// When the post completes, resolve with the executable
.on('end', function() {
// Parse the incoming data as JSON
var result;
try {
result = JSON.parse(Buffer.concat(buffers));
} catch (e) {
return reject(tags.stripIndent `
Please file an issue on https://github.com/tessel/t2-cli with the following:
You received an invalid JSON response from the cross-compilation server.
${Buffer.concat(buffers).toString()}`);
}

// 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));
}

// Print out any stderr output
else if (result.stderr !== null && result.stderr !== '') {
log.info(result.stderr);
}

// Print out any stdout output
/* istanbul ignore else */
if (result.stdout !== null) {
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'));
}
});
});

// Create an outgoing tar packer for our project
var outgoingPacker = tar.Pack({
noProprietary: true
})
// Reject on failure
.on('error', function(postReqError) {
return reject(postReqError);
.on('error', reject);

// Send the project directory through the tar packer and into the post request
Reader({
path: opts.target,
type: 'Directory'
})
// When the post completes, resolve with the executable
.on('end', function() {
// Parse the incoming data as JSON
var result;
try {
result = JSON.parse(Buffer.concat(buffers));
} catch (e) {
return reject(tags.stripIndent `
Please file an issue on https://github.com/tessel/t2-cli with the following:
You received an invalid JSON response from the cross-compilation server.
${Buffer.concat(buffers).toString()}`);
}

// 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));
}

// Print out any stderr output
else if (result.stderr !== null && result.stderr !== '') {
log.info(result.stderr);
}

// Print out any stdout output
/* istanbul ignore else */
if (result.stdout !== null) {
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'));
}
});
});

// Create an outgoing tar packer for our project
var outgoingPacker = tar.Pack({
noProprietary: true
})
.on('error', reject);
.on('error', reject)
.pipe(outgoingPacker)
.pipe(req);

// Send the project directory through the tar packer and into the post request
Reader({
path: opts.target,
type: 'Directory'
})
.on('error', reject)
.pipe(outgoingPacker)
.pipe(req);
}).catch(reject);
});
};

Expand Down

0 comments on commit 130b1bd

Please sign in to comment.