mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-01-18 02:39:49 +00:00
Update resin-preload to 4.0.2 to support preloading Edison images
Change-Type: patch
This commit is contained in:
parent
dad655c9ec
commit
119fa78927
@ -127,8 +127,8 @@ offerToDisableAutomaticUpdates = function(application, commit) {
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
signature: 'preload <image>',
|
signature: 'preload <image>',
|
||||||
description: '(beta) preload an app on a disk 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 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',
|
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',
|
permission: 'user',
|
||||||
primary: true,
|
primary: true,
|
||||||
options: dockerUtils.appendConnectionOptions([
|
options: dockerUtils.appendConnectionOptions([
|
||||||
@ -158,7 +158,7 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
action: function(params, options, done) {
|
action: function(params, options, done) {
|
||||||
var Promise, _, errors, expectedError, form, imageInfoSpinner, preload, resin, streamToPromise, visuals;
|
var Promise, _, errors, expectedError, form, nodeCleanup, preload, progressBars, progressHandler, resin, spinnerHandler, spinners, streamToPromise, visuals;
|
||||||
_ = require('lodash');
|
_ = require('lodash');
|
||||||
Promise = require('bluebird');
|
Promise = require('bluebird');
|
||||||
resin = require('resin-sdk-preconfigured');
|
resin = require('resin-sdk-preconfigured');
|
||||||
@ -167,8 +167,33 @@ module.exports = {
|
|||||||
preload = require('resin-preload');
|
preload = require('resin-preload');
|
||||||
errors = require('resin-errors');
|
errors = require('resin-errors');
|
||||||
visuals = require('resin-cli-visuals');
|
visuals = require('resin-cli-visuals');
|
||||||
|
nodeCleanup = require('node-cleanup');
|
||||||
expectedError = require('../utils/patterns').expectedError;
|
expectedError = require('../utils/patterns').expectedError;
|
||||||
imageInfoSpinner = new visuals.Spinner('Reading image device type and preloaded builds.');
|
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.image = params.image;
|
||||||
options.appId = options.app;
|
options.appId = options.app;
|
||||||
delete options.app;
|
delete options.app;
|
||||||
@ -176,72 +201,79 @@ module.exports = {
|
|||||||
delete options['dont-detect-flasher-type-images'];
|
delete options['dont-detect-flasher-type-images'];
|
||||||
options.splashImage = options['splash-image'];
|
options.splashImage = options['splash-image'];
|
||||||
delete 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) {
|
return dockerUtils.getDocker(options).then(function(docker) {
|
||||||
var buildOutputStream;
|
var gotSignal, preloader;
|
||||||
buildOutputStream = preload.build(docker);
|
preloader = new preload.Preloader(resin, docker, options.appId, options.commit, options.image, options.splashImage, options.proxy, options.dontDetectFlasherTypeImages);
|
||||||
if (process.env.DEBUG) {
|
gotSignal = false;
|
||||||
buildOutputStream.pipe(process.stdout);
|
nodeCleanup(function(exitCode, signal) {
|
||||||
}
|
if (signal) {
|
||||||
return streamToPromise(buildOutputStream).then(resin.settings.getAll).then(function(settings) {
|
gotSignal = true;
|
||||||
options.proxy = settings.proxy;
|
nodeCleanup.uninstall();
|
||||||
options.apiHost = settings.apiUrl;
|
preloader.cleanup().then(function() {
|
||||||
imageInfoSpinner.start();
|
return process.kill(process.pid, signal);
|
||||||
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() {
|
return false;
|
||||||
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) {
|
if (process.env.DEBUG) {
|
||||||
info.stdout.pipe(process.stdout);
|
preloader.stderr.pipe(process.stderr);
|
||||||
info.stderr.pipe(process.stderr);
|
|
||||||
return info.statusCodePromise;
|
|
||||||
}).then(function(statusCode) {
|
|
||||||
if (statusCode !== 0) {
|
|
||||||
return process.exit(statusCode);
|
|
||||||
}
|
}
|
||||||
}).then(done);
|
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();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -102,14 +102,14 @@ offerToDisableAutomaticUpdates = (application, commit) ->
|
|||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
signature: 'preload <image>'
|
signature: 'preload <image>'
|
||||||
description: '(beta) preload an app on a disk image'
|
description: '(beta) preload an app on a disk image (or Edison zip archive)'
|
||||||
help: '''
|
help: '''
|
||||||
Warning: "resin preload" requires Docker to be correctly installed in
|
Warning: "resin preload" requires Docker to be correctly installed in
|
||||||
your shell environment. For more information (including Windows support)
|
your shell environment. For more information (including Windows support)
|
||||||
please check the README here: https://github.com/resin-io/resin-cli .
|
please check the README here: https://github.com/resin-io/resin-cli .
|
||||||
|
|
||||||
Use this command to preload an application to a local disk image with a
|
Use this command to preload an application to a local disk image (or
|
||||||
built commit from Resin.io.
|
Edison zip archive) with a built commit from Resin.io.
|
||||||
This can be used with cloud builds, or images deployed with resin deploy.
|
This can be used with cloud builds, or images deployed with resin deploy.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@ -157,9 +157,28 @@ module.exports =
|
|||||||
preload = require('resin-preload')
|
preload = require('resin-preload')
|
||||||
errors = require('resin-errors')
|
errors = require('resin-errors')
|
||||||
visuals = require('resin-cli-visuals')
|
visuals = require('resin-cli-visuals')
|
||||||
|
nodeCleanup = require('node-cleanup')
|
||||||
{ expectedError } = require('../utils/patterns')
|
{ expectedError } = require('../utils/patterns')
|
||||||
|
|
||||||
imageInfoSpinner = new visuals.Spinner('Reading image device type and preloaded builds.')
|
progressBars = {}
|
||||||
|
|
||||||
|
progressHandler = (event) ->
|
||||||
|
progressBar = progressBars[event.name]
|
||||||
|
if not progressBar
|
||||||
|
progressBar = progressBars[event.name] = new visuals.Progress(event.name)
|
||||||
|
progressBar.update(percentage: event.percentage)
|
||||||
|
|
||||||
|
spinners = {}
|
||||||
|
|
||||||
|
spinnerHandler = (event) ->
|
||||||
|
spinner = spinners[event.name]
|
||||||
|
if not spinner
|
||||||
|
spinner = spinners[event.name] = new visuals.Spinner(event.name)
|
||||||
|
if event.action == 'start'
|
||||||
|
spinner.start()
|
||||||
|
else
|
||||||
|
console.log()
|
||||||
|
spinner.stop()
|
||||||
|
|
||||||
options.image = params.image
|
options.image = params.image
|
||||||
options.appId = options.app
|
options.appId = options.app
|
||||||
@ -171,79 +190,92 @@ module.exports =
|
|||||||
options.splashImage = options['splash-image']
|
options.splashImage = options['splash-image']
|
||||||
delete options['splash-image']
|
delete options['splash-image']
|
||||||
|
|
||||||
|
if options['dont-check-device-type'] and not options.appId
|
||||||
|
expectedError('You need to specify an app id if you disable the device type check.')
|
||||||
|
|
||||||
# Get a configured dockerode instance
|
# Get a configured dockerode instance
|
||||||
dockerUtils.getDocker(options)
|
dockerUtils.getDocker(options)
|
||||||
.then (docker) ->
|
.then (docker) ->
|
||||||
|
|
||||||
# Build the preloader image
|
preloader = new preload.Preloader(
|
||||||
buildOutputStream = preload.build(docker)
|
resin,
|
||||||
|
docker,
|
||||||
|
options.appId,
|
||||||
|
options.commit,
|
||||||
|
options.image,
|
||||||
|
options.splashImage,
|
||||||
|
options.proxy,
|
||||||
|
options.dontDetectFlasherTypeImages
|
||||||
|
)
|
||||||
|
|
||||||
|
gotSignal = false
|
||||||
|
|
||||||
|
nodeCleanup (exitCode, signal) ->
|
||||||
|
if signal
|
||||||
|
gotSignal = true
|
||||||
|
nodeCleanup.uninstall() # don't call cleanup handler again
|
||||||
|
preloader.cleanup()
|
||||||
|
.then ->
|
||||||
|
# calling process.exit() won't inform parent process of signal
|
||||||
|
process.kill(process.pid, signal)
|
||||||
|
return false
|
||||||
|
|
||||||
if process.env.DEBUG
|
if process.env.DEBUG
|
||||||
buildOutputStream.pipe(process.stdout)
|
preloader.stderr.pipe(process.stderr)
|
||||||
|
|
||||||
streamToPromise(buildOutputStream)
|
preloader.on('progress', progressHandler)
|
||||||
|
preloader.on('spinner', spinnerHandler)
|
||||||
|
|
||||||
# Get resin sdk settings so we can pass them to the preloader
|
return new Promise (resolve, reject) ->
|
||||||
.then(resin.settings.getAll)
|
preloader.on('error', reject)
|
||||||
.then (settings) ->
|
|
||||||
options.proxy = settings.proxy
|
|
||||||
options.apiHost = settings.apiUrl
|
|
||||||
|
|
||||||
# Use the preloader docker image to extract the deviceType of the image
|
preloader.build()
|
||||||
imageInfoSpinner.start()
|
|
||||||
preload.getDeviceTypeSlugAndPreloadedBuilds(docker, options)
|
|
||||||
.catch(preload.errors.ResinError, expectedError)
|
|
||||||
.then ({ slug, builds }) ->
|
|
||||||
imageInfoSpinner.stop()
|
|
||||||
# Use the appId given as --app or show an interactive app selection menu
|
|
||||||
Promise.try ->
|
|
||||||
if options['dont-check-device-type'] and not 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)
|
|
||||||
selectApplication(slug)
|
|
||||||
.then (application) ->
|
|
||||||
options.application = application
|
|
||||||
|
|
||||||
# Check that the app device type and the image device type match
|
|
||||||
if slug != application.device_type
|
|
||||||
expectedError(
|
|
||||||
"Image device type (#{application.device_type}) and application device type (#{slug}) do not match"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Use the commit given as --commit or show an interactive commit selection menu
|
|
||||||
Promise.try ->
|
|
||||||
if options.commit
|
|
||||||
if not _.find(application.build, commit_hash: options.commit)
|
|
||||||
expectedError('There is no build matching this commit')
|
|
||||||
return options.commit
|
|
||||||
selectApplicationCommit(application.build)
|
|
||||||
.then (commit) ->
|
|
||||||
|
|
||||||
# No commit specified => use the latest commit
|
|
||||||
if commit == LATEST
|
|
||||||
options.commit = application.commit
|
|
||||||
else
|
|
||||||
options.commit = commit
|
|
||||||
|
|
||||||
# Propose to disable automatic app updates if the commit is not the latest
|
|
||||||
offerToDisableAutomaticUpdates(application, commit)
|
|
||||||
.then ->
|
.then ->
|
||||||
|
preloader.prepare()
|
||||||
|
.then ->
|
||||||
|
preloader.getDeviceTypeAndPreloadedBuilds()
|
||||||
|
.then (info) ->
|
||||||
|
Promise.try ->
|
||||||
|
if options.appId
|
||||||
|
return preloader.fetchApplication()
|
||||||
|
.catch(errors.ResinApplicationNotFound, expectedError)
|
||||||
|
selectApplication(info.device_type)
|
||||||
|
.then (application) ->
|
||||||
|
preloader.setApplication(application)
|
||||||
|
# Check that the app device type and the image device type match
|
||||||
|
if info.device_type != application.device_type
|
||||||
|
expectedError(
|
||||||
|
"Image device type (#{application.device_type}) and application device type (#{slug}) do not match"
|
||||||
|
)
|
||||||
|
|
||||||
builds = builds.map (build) ->
|
# Use the commit given as --commit or show an interactive commit selection menu
|
||||||
build.slice(-preload.BUILD_HASH_LENGTH)
|
Promise.try ->
|
||||||
if options.commit in builds
|
if options.commit
|
||||||
console.log('This build is already preloaded in this image.')
|
if not _.find(application.build, commit_hash: options.commit)
|
||||||
process.exit(0)
|
expectedError('There is no build matching this commit')
|
||||||
# All options are ready: preload the image.
|
return options.commit
|
||||||
preload.run(resin, docker, options)
|
selectApplicationCommit(application.build)
|
||||||
.catch(preload.errors.ResinError, expectedError)
|
.then (commit) ->
|
||||||
.then (info) ->
|
|
||||||
info.stdout.pipe(process.stdout)
|
# No commit specified => use the latest commit
|
||||||
info.stderr.pipe(process.stderr)
|
if commit == LATEST
|
||||||
info.statusCodePromise
|
preloader.commit = application.commit
|
||||||
.then (statusCode) ->
|
else
|
||||||
if statusCode != 0
|
preloader.commit = commit
|
||||||
process.exit(statusCode)
|
|
||||||
.then(done)
|
# Propose to disable automatic app updates if the commit is not the latest
|
||||||
|
offerToDisableAutomaticUpdates(application, commit)
|
||||||
|
.then ->
|
||||||
|
builds = info.preloaded_builds.map (build) ->
|
||||||
|
build.slice(-preload.BUILD_HASH_LENGTH)
|
||||||
|
if preloader.commit in builds
|
||||||
|
throw new preload.errors.ResinError('This build is already preloaded in this image.')
|
||||||
|
# All options are ready: preload the image.
|
||||||
|
preloader.preload()
|
||||||
|
.catch(preload.errors.ResinError, expectedError)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject)
|
||||||
|
.then(done)
|
||||||
|
.finally ->
|
||||||
|
if not gotSignal
|
||||||
|
preloader.cleanup()
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
"mixpanel": "^0.4.0",
|
"mixpanel": "^0.4.0",
|
||||||
"moment": "^2.12.0",
|
"moment": "^2.12.0",
|
||||||
"mz": "^2.6.0",
|
"mz": "^2.6.0",
|
||||||
|
"node-cleanup": "^2.1.2",
|
||||||
"nplugm": "^3.0.0",
|
"nplugm": "^3.0.0",
|
||||||
"president": "^2.0.1",
|
"president": "^2.0.1",
|
||||||
"prettyjson": "^1.1.3",
|
"prettyjson": "^1.1.3",
|
||||||
@ -85,7 +86,7 @@
|
|||||||
"resin-doodles": "0.0.1",
|
"resin-doodles": "0.0.1",
|
||||||
"resin-image-fs": "^2.3.0",
|
"resin-image-fs": "^2.3.0",
|
||||||
"resin-image-manager": "^4.1.1",
|
"resin-image-manager": "^4.1.1",
|
||||||
"resin-preload": "^3.1.4",
|
"resin-preload": "^4.0.2",
|
||||||
"resin-sdk-preconfigured": "^6.9.0",
|
"resin-sdk-preconfigured": "^6.9.0",
|
||||||
"resin-settings-client": "^3.6.1",
|
"resin-settings-client": "^3.6.1",
|
||||||
"resin-stream-logger": "^0.0.4",
|
"resin-stream-logger": "^0.0.4",
|
||||||
@ -103,4 +104,4 @@
|
|||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"removedrive": "^1.0.0"
|
"removedrive": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user