mirror of
https://github.com/balena-io/balena-cli.git
synced 2024-12-20 14:13:07 +00:00
223432406d
Connects-To: #646 Change-Type: minor
246 lines
9.2 KiB
JavaScript
246 lines
9.2 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',
|
|
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 with a\nbuilt 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, imageInfoSpinner, preload, resin, 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');
|
|
expectedError = require('../utils/patterns').expectedError;
|
|
imageInfoSpinner = new visuals.Spinner('Reading image device type and preloaded builds.');
|
|
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'];
|
|
return dockerUtils.getDocker(options).then(function(docker) {
|
|
var buildOutputStream;
|
|
buildOutputStream = preload.build(docker);
|
|
if (process.env.DEBUG) {
|
|
buildOutputStream.pipe(process.stdout);
|
|
}
|
|
return streamToPromise(buildOutputStream).then(resin.settings.getAll).then(function(settings) {
|
|
options.proxy = settings.proxy;
|
|
options.apiHost = settings.apiUrl;
|
|
imageInfoSpinner.start();
|
|
return preload.getDeviceTypeSlugAndPreloadedBuilds(docker, options)["catch"](preload.errors.ResinError, expectedError);
|
|
}).then(function(arg) {
|
|
var builds, slug;
|
|
slug = arg.slug, builds = arg.builds;
|
|
imageInfoSpinner.stop();
|
|
return Promise["try"](function() {
|
|
if (options['dont-check-device-type'] && !options.appId) {
|
|
expectedError('You need to specify an app id if you disable the device type check.');
|
|
}
|
|
if (options.appId) {
|
|
return preload.getApplication(resin, options.appId)["catch"](errors.ResinApplicationNotFound, expectedError);
|
|
}
|
|
return selectApplication(slug);
|
|
}).then(function(application) {
|
|
options.application = application;
|
|
if (slug !== 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) {
|
|
options.commit = application.commit;
|
|
} else {
|
|
options.commit = commit;
|
|
}
|
|
return offerToDisableAutomaticUpdates(application, commit);
|
|
});
|
|
}).then(function() {
|
|
var ref;
|
|
builds = builds.map(function(build) {
|
|
return build.slice(-preload.BUILD_HASH_LENGTH);
|
|
});
|
|
if (ref = options.commit, indexOf.call(builds, ref) >= 0) {
|
|
console.log('This build is already preloaded in this image.');
|
|
process.exit(0);
|
|
}
|
|
return preload.run(resin, docker, options)["catch"](preload.errors.ResinError, expectedError);
|
|
});
|
|
});
|
|
}).then(function(info) {
|
|
info.stdout.pipe(process.stdout);
|
|
info.stderr.pipe(process.stderr);
|
|
return info.statusCodePromise;
|
|
}).then(function(statusCode) {
|
|
if (statusCode !== 0) {
|
|
return process.exit(statusCode);
|
|
}
|
|
}).then(done);
|
|
}
|
|
};
|