mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-22 15:02:22 +00:00
119fa78927
Change-Type: patch
280 lines
10 KiB
JavaScript
280 lines
10 KiB
JavaScript
// Generated by CoffeeScript 1.12.7
|
|
|
|
/*
|
|
Copyright 2016-2017 Resin.io
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
var LATEST, dockerUtils, getApplicationsWithSuccessfulBuilds, offerToDisableAutomaticUpdates, selectApplication, selectApplicationCommit,
|
|
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
|
|
|
dockerUtils = require('../utils/docker');
|
|
|
|
LATEST = 'latest';
|
|
|
|
getApplicationsWithSuccessfulBuilds = function(deviceType) {
|
|
var preload, resin;
|
|
preload = require('resin-preload');
|
|
resin = require('resin-sdk-preconfigured');
|
|
return resin.pine.get({
|
|
resource: 'my_application',
|
|
options: {
|
|
filter: {
|
|
device_type: deviceType,
|
|
build: {
|
|
$any: {
|
|
$alias: 'b',
|
|
$expr: {
|
|
b: {
|
|
status: 'success'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
expand: preload.applicationExpandOptions,
|
|
select: ['id', 'app_name', 'device_type', 'commit'],
|
|
orderby: 'app_name asc'
|
|
}
|
|
});
|
|
};
|
|
|
|
selectApplication = function(deviceType) {
|
|
var applicationInfoSpinner, expectedError, form, visuals;
|
|
visuals = require('resin-cli-visuals');
|
|
form = require('resin-cli-form');
|
|
expectedError = require('../utils/patterns').expectedError;
|
|
applicationInfoSpinner = new visuals.Spinner('Downloading list of applications and builds.');
|
|
applicationInfoSpinner.start();
|
|
return getApplicationsWithSuccessfulBuilds(deviceType).then(function(applications) {
|
|
applicationInfoSpinner.stop();
|
|
if (applications.length === 0) {
|
|
expectedError("You have no apps with successful builds for a '" + deviceType + "' device type.");
|
|
}
|
|
return form.ask({
|
|
message: 'Select an application',
|
|
type: 'list',
|
|
choices: applications.map(function(app) {
|
|
return {
|
|
name: app.app_name,
|
|
value: app
|
|
};
|
|
})
|
|
});
|
|
});
|
|
};
|
|
|
|
selectApplicationCommit = function(builds) {
|
|
var DEFAULT_CHOICE, choices, expectedError, form;
|
|
form = require('resin-cli-form');
|
|
expectedError = require('../utils/patterns').expectedError;
|
|
if (builds.length === 0) {
|
|
expectedError('This application has no successful builds.');
|
|
}
|
|
DEFAULT_CHOICE = {
|
|
'name': LATEST,
|
|
'value': LATEST
|
|
};
|
|
choices = [DEFAULT_CHOICE].concat(builds.map(function(build) {
|
|
return {
|
|
name: build.push_timestamp + " - " + build.commit_hash,
|
|
value: build.commit_hash
|
|
};
|
|
}));
|
|
return form.ask({
|
|
message: 'Select a build',
|
|
type: 'list',
|
|
"default": LATEST,
|
|
choices: choices
|
|
});
|
|
};
|
|
|
|
offerToDisableAutomaticUpdates = function(application, commit) {
|
|
var Promise, form, message, resin;
|
|
Promise = require('bluebird');
|
|
resin = require('resin-sdk-preconfigured');
|
|
form = require('resin-cli-form');
|
|
if (commit === LATEST || !application.should_track_latest_release) {
|
|
return Promise.resolve();
|
|
}
|
|
message = '\nThis application is set to automatically update all devices to the latest available version.\nThis might be unexpected behaviour: with this enabled, the preloaded device will still\ndownload and install the latest build once it is online.\n\nDo you want to disable automatic updates for this application?';
|
|
return form.ask({
|
|
message: message,
|
|
type: 'confirm'
|
|
}).then(function(update) {
|
|
if (!update) {
|
|
return;
|
|
}
|
|
return resin.pine.patch({
|
|
resource: 'application',
|
|
id: application.id,
|
|
body: {
|
|
should_track_latest_release: false
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
module.exports = {
|
|
signature: 'preload <image>',
|
|
description: '(beta) preload an app on a disk image (or Edison zip archive)',
|
|
help: 'Warning: "resin preload" requires Docker to be correctly installed in\nyour shell environment. For more information (including Windows support)\nplease check the README here: https://github.com/resin-io/resin-cli .\n\nUse this command to preload an application to a local disk image (or\nEdison zip archive) with a built commit from Resin.io.\nThis can be used with cloud builds, or images deployed with resin deploy.\n\nExamples:\n $ resin preload resin.img --app 1234 --commit e1f2592fc6ee949e68756d4f4a48e49bff8d72a0 --splash-image some-image.png\n $ resin preload resin.img',
|
|
permission: 'user',
|
|
primary: true,
|
|
options: dockerUtils.appendConnectionOptions([
|
|
{
|
|
signature: 'app',
|
|
parameter: 'appId',
|
|
description: 'id of the application to preload',
|
|
alias: 'a'
|
|
}, {
|
|
signature: 'commit',
|
|
parameter: 'hash',
|
|
description: 'a specific application commit to preload (ignored if no appId is given)',
|
|
alias: 'c'
|
|
}, {
|
|
signature: 'splash-image',
|
|
parameter: 'splashImage.png',
|
|
description: 'path to a png image to replace the splash screen',
|
|
alias: 's'
|
|
}, {
|
|
signature: 'dont-detect-flasher-type-images',
|
|
boolean: true,
|
|
description: 'Disables the flasher type images detection: treats all images as non flasher types'
|
|
}, {
|
|
signature: 'dont-check-device-type',
|
|
boolean: true,
|
|
description: 'Disables check for matching device types in image and application'
|
|
}
|
|
]),
|
|
action: function(params, options, done) {
|
|
var Promise, _, errors, expectedError, form, nodeCleanup, preload, progressBars, progressHandler, resin, spinnerHandler, spinners, streamToPromise, visuals;
|
|
_ = require('lodash');
|
|
Promise = require('bluebird');
|
|
resin = require('resin-sdk-preconfigured');
|
|
streamToPromise = require('stream-to-promise');
|
|
form = require('resin-cli-form');
|
|
preload = require('resin-preload');
|
|
errors = require('resin-errors');
|
|
visuals = require('resin-cli-visuals');
|
|
nodeCleanup = require('node-cleanup');
|
|
expectedError = require('../utils/patterns').expectedError;
|
|
progressBars = {};
|
|
progressHandler = function(event) {
|
|
var progressBar;
|
|
progressBar = progressBars[event.name];
|
|
if (!progressBar) {
|
|
progressBar = progressBars[event.name] = new visuals.Progress(event.name);
|
|
}
|
|
return progressBar.update({
|
|
percentage: event.percentage
|
|
});
|
|
};
|
|
spinners = {};
|
|
spinnerHandler = function(event) {
|
|
var spinner;
|
|
spinner = spinners[event.name];
|
|
if (!spinner) {
|
|
spinner = spinners[event.name] = new visuals.Spinner(event.name);
|
|
}
|
|
if (event.action === 'start') {
|
|
return spinner.start();
|
|
} else {
|
|
console.log();
|
|
return spinner.stop();
|
|
}
|
|
};
|
|
options.image = params.image;
|
|
options.appId = options.app;
|
|
delete options.app;
|
|
options.dontDetectFlasherTypeImages = options['dont-detect-flasher-type-images'];
|
|
delete options['dont-detect-flasher-type-images'];
|
|
options.splashImage = options['splash-image'];
|
|
delete options['splash-image'];
|
|
if (options['dont-check-device-type'] && !options.appId) {
|
|
expectedError('You need to specify an app id if you disable the device type check.');
|
|
}
|
|
return dockerUtils.getDocker(options).then(function(docker) {
|
|
var gotSignal, preloader;
|
|
preloader = new preload.Preloader(resin, docker, options.appId, options.commit, options.image, options.splashImage, options.proxy, options.dontDetectFlasherTypeImages);
|
|
gotSignal = false;
|
|
nodeCleanup(function(exitCode, signal) {
|
|
if (signal) {
|
|
gotSignal = true;
|
|
nodeCleanup.uninstall();
|
|
preloader.cleanup().then(function() {
|
|
return process.kill(process.pid, signal);
|
|
});
|
|
return false;
|
|
}
|
|
});
|
|
if (process.env.DEBUG) {
|
|
preloader.stderr.pipe(process.stderr);
|
|
}
|
|
preloader.on('progress', progressHandler);
|
|
preloader.on('spinner', spinnerHandler);
|
|
return new Promise(function(resolve, reject) {
|
|
preloader.on('error', reject);
|
|
return preloader.build().then(function() {
|
|
return preloader.prepare();
|
|
}).then(function() {
|
|
return preloader.getDeviceTypeAndPreloadedBuilds();
|
|
}).then(function(info) {
|
|
return Promise["try"](function() {
|
|
if (options.appId) {
|
|
return preloader.fetchApplication()["catch"](errors.ResinApplicationNotFound, expectedError);
|
|
}
|
|
return selectApplication(info.device_type);
|
|
}).then(function(application) {
|
|
preloader.setApplication(application);
|
|
if (info.device_type !== application.device_type) {
|
|
expectedError("Image device type (" + application.device_type + ") and application device type (" + slug + ") do not match");
|
|
}
|
|
return Promise["try"](function() {
|
|
if (options.commit) {
|
|
if (!_.find(application.build, {
|
|
commit_hash: options.commit
|
|
})) {
|
|
expectedError('There is no build matching this commit');
|
|
}
|
|
return options.commit;
|
|
}
|
|
return selectApplicationCommit(application.build);
|
|
}).then(function(commit) {
|
|
if (commit === LATEST) {
|
|
preloader.commit = application.commit;
|
|
} else {
|
|
preloader.commit = commit;
|
|
}
|
|
return offerToDisableAutomaticUpdates(application, commit);
|
|
});
|
|
}).then(function() {
|
|
var builds, ref;
|
|
builds = info.preloaded_builds.map(function(build) {
|
|
return build.slice(-preload.BUILD_HASH_LENGTH);
|
|
});
|
|
if (ref = preloader.commit, indexOf.call(builds, ref) >= 0) {
|
|
throw new preload.errors.ResinError('This build is already preloaded in this image.');
|
|
}
|
|
return preloader.preload()["catch"](preload.errors.ResinError, expectedError);
|
|
});
|
|
}).then(resolve)["catch"](reject);
|
|
}).then(done)["finally"](function() {
|
|
if (!gotSignal) {
|
|
return preloader.cleanup();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
};
|