mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-04-07 11:26:41 +00:00
config inject/read/write: Fix umount errors with OS image files
Resolves: #1003 Change-type: patch
This commit is contained in:
parent
06f7683837
commit
0f9d78ab50
@ -2330,7 +2330,7 @@ device type (Check available types with `balena devices supported`)
|
||||
|
||||
#### -d, --drive DRIVE
|
||||
|
||||
device filesystem or OS image location
|
||||
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
|
||||
|
||||
## config read
|
||||
|
||||
@ -2350,7 +2350,7 @@ device type (Check available types with `balena devices supported`)
|
||||
|
||||
#### -d, --drive DRIVE
|
||||
|
||||
device filesystem or OS image location
|
||||
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
|
||||
|
||||
## config reconfigure
|
||||
|
||||
@ -2370,7 +2370,7 @@ device type (Check available types with `balena devices supported`)
|
||||
|
||||
#### -d, --drive DRIVE
|
||||
|
||||
device filesystem or OS image location
|
||||
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
|
||||
|
||||
#### -v, --advanced
|
||||
|
||||
@ -2405,7 +2405,7 @@ device type (Check available types with `balena devices supported`)
|
||||
|
||||
#### -d, --drive DRIVE
|
||||
|
||||
device filesystem or OS image location
|
||||
path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)
|
||||
|
||||
# Preload
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2020 Balena Ltd.
|
||||
* Copyright 2016-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -54,16 +54,8 @@ export default class ConfigInjectCmd extends Command {
|
||||
public static usage = 'config inject <file>';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
type: flags.string({
|
||||
description:
|
||||
'device type (Check available types with `balena devices supported`)',
|
||||
char: 't',
|
||||
required: true,
|
||||
}),
|
||||
drive: flags.string({
|
||||
description: 'device filesystem or OS image location',
|
||||
char: 'd',
|
||||
}),
|
||||
type: cf.deviceType,
|
||||
drive: cf.driveOrImg,
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
@ -76,12 +68,11 @@ export default class ConfigInjectCmd extends Command {
|
||||
ConfigInjectCmd,
|
||||
);
|
||||
|
||||
const { promisify } = await import('util');
|
||||
const umountAsync = promisify((await import('umount')).umount);
|
||||
const { safeUmount } = await import('../../utils/helpers');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device/OS drive'));
|
||||
await umountAsync(drive);
|
||||
await safeUmount(drive);
|
||||
|
||||
const fs = await import('fs');
|
||||
const configJSON = JSON.parse(
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2020 Balena Ltd.
|
||||
* Copyright 2016-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -42,16 +42,8 @@ export default class ConfigReadCmd extends Command {
|
||||
public static usage = 'config read';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
type: flags.string({
|
||||
description:
|
||||
'device type (Check available types with `balena devices supported`)',
|
||||
char: 't',
|
||||
required: true,
|
||||
}),
|
||||
drive: flags.string({
|
||||
description: 'device filesystem or OS image location',
|
||||
char: 'd',
|
||||
}),
|
||||
type: cf.deviceType,
|
||||
drive: cf.driveOrImg,
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
@ -62,12 +54,11 @@ export default class ConfigReadCmd extends Command {
|
||||
public async run() {
|
||||
const { flags: options } = this.parse<FlagsDef, {}>(ConfigReadCmd);
|
||||
|
||||
const { promisify } = await import('util');
|
||||
const umountAsync = promisify((await import('umount')).umount);
|
||||
const { safeUmount } = await import('../../utils/helpers');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device drive'));
|
||||
await umountAsync(drive);
|
||||
await safeUmount(drive);
|
||||
|
||||
const config = await import('balena-config-json');
|
||||
const configJSON = await config.read(drive, options.type);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2020 Balena Ltd.
|
||||
* Copyright 2016-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -42,16 +42,8 @@ export default class ConfigReconfigureCmd extends Command {
|
||||
public static usage = 'config reconfigure';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
type: flags.string({
|
||||
description:
|
||||
'device type (Check available types with `balena devices supported`)',
|
||||
char: 't',
|
||||
required: true,
|
||||
}),
|
||||
drive: flags.string({
|
||||
description: 'device filesystem or OS image location',
|
||||
char: 'd',
|
||||
}),
|
||||
type: cf.deviceType,
|
||||
drive: cf.driveOrImg,
|
||||
advanced: flags.boolean({
|
||||
description: 'show advanced commands',
|
||||
char: 'v',
|
||||
@ -66,16 +58,15 @@ export default class ConfigReconfigureCmd extends Command {
|
||||
public async run() {
|
||||
const { flags: options } = this.parse<FlagsDef, {}>(ConfigReconfigureCmd);
|
||||
|
||||
const { promisify } = await import('util');
|
||||
const umountAsync = promisify((await import('umount')).umount);
|
||||
const { safeUmount } = await import('../../utils/helpers');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device drive'));
|
||||
await umountAsync(drive);
|
||||
await safeUmount(drive);
|
||||
|
||||
const config = await import('balena-config-json');
|
||||
const { uuid } = await config.read(drive, options.type);
|
||||
await umountAsync(drive);
|
||||
await safeUmount(drive);
|
||||
|
||||
const configureCommand = ['os', 'configure', drive, '--device', uuid];
|
||||
if (options.advanced) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2020 Balena Ltd.
|
||||
* Copyright 2016-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -61,16 +61,8 @@ export default class ConfigWriteCmd extends Command {
|
||||
public static usage = 'config write <key> <value>';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
type: flags.string({
|
||||
description:
|
||||
'device type (Check available types with `balena devices supported`)',
|
||||
char: 't',
|
||||
required: true,
|
||||
}),
|
||||
drive: flags.string({
|
||||
description: 'device filesystem or OS image location',
|
||||
char: 'd',
|
||||
}),
|
||||
type: cf.deviceType,
|
||||
drive: cf.driveOrImg,
|
||||
help: cf.help,
|
||||
};
|
||||
|
||||
@ -83,12 +75,11 @@ export default class ConfigWriteCmd extends Command {
|
||||
ConfigWriteCmd,
|
||||
);
|
||||
|
||||
const { promisify } = await import('util');
|
||||
const umountAsync = promisify((await import('umount')).umount);
|
||||
const { safeUmount } = await import('../../utils/helpers');
|
||||
|
||||
const drive =
|
||||
options.drive || (await getVisuals().drive('Select the device drive'));
|
||||
await umountAsync(drive);
|
||||
await safeUmount(drive);
|
||||
|
||||
const config = await import('balena-config-json');
|
||||
const configJSON = await config.read(drive, options.type);
|
||||
@ -97,7 +88,7 @@ export default class ConfigWriteCmd extends Command {
|
||||
const _ = await import('lodash');
|
||||
_.set(configJSON, params.key, params.value);
|
||||
|
||||
await umountAsync(drive);
|
||||
await safeUmount(drive);
|
||||
|
||||
await config.write(drive, options.type, configJSON);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2020 Balena Ltd.
|
||||
* Copyright 2016-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -61,20 +61,16 @@ export default class LocalConfigureCmd extends Command {
|
||||
const { args: params } = this.parse<FlagsDef, ArgsDef>(LocalConfigureCmd);
|
||||
|
||||
const path = await import('path');
|
||||
const umount = await import('umount');
|
||||
const umountAsync = promisify(umount.umount);
|
||||
const isMountedAsync = promisify(umount.isMounted);
|
||||
const reconfix = await import('reconfix');
|
||||
const denymount = promisify(await import('denymount'));
|
||||
const { safeUmount } = await import('../../utils/helpers');
|
||||
const Logger = await import('../../utils/logger');
|
||||
|
||||
const logger = Logger.getLogger();
|
||||
|
||||
const configurationSchema = await this.prepareConnectionFile(params.target);
|
||||
|
||||
if (await isMountedAsync(params.target)) {
|
||||
await umountAsync(params.target);
|
||||
}
|
||||
await safeUmount(params.target);
|
||||
|
||||
const dmOpts: any = {};
|
||||
if (process.pkg) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2016-2020 Balena Ltd.
|
||||
* Copyright 2016-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -61,12 +61,7 @@ export default class OsInitializeCmd extends Command {
|
||||
public static usage = 'os initialize <image>';
|
||||
|
||||
public static flags: flags.Input<FlagsDef> = {
|
||||
type: flags.string({
|
||||
description:
|
||||
'device type (Check available types with `balena devices supported`)',
|
||||
char: 't',
|
||||
required: true,
|
||||
}),
|
||||
type: cf.deviceType,
|
||||
drive: cf.drive,
|
||||
yes: cf.yes,
|
||||
help: cf.help,
|
||||
@ -79,9 +74,9 @@ export default class OsInitializeCmd extends Command {
|
||||
OsInitializeCmd,
|
||||
);
|
||||
|
||||
const { promisify } = await import('util');
|
||||
const umountAsync = promisify((await import('umount')).umount);
|
||||
const { getManifest, sudo } = await import('../../utils/helpers');
|
||||
const { getManifest, safeUmount, sudo } = await import(
|
||||
'../../utils/helpers'
|
||||
);
|
||||
|
||||
console.info(`Initializing device ${INIT_WARNING_MESSAGE}`);
|
||||
|
||||
@ -101,7 +96,7 @@ export default class OsInitializeCmd extends Command {
|
||||
`Going to erase ${answers.drive}.`,
|
||||
true,
|
||||
);
|
||||
await umountAsync(answers.drive);
|
||||
await safeUmount(answers.drive);
|
||||
}
|
||||
|
||||
await sudo([
|
||||
@ -113,22 +108,7 @@ export default class OsInitializeCmd extends Command {
|
||||
]);
|
||||
|
||||
if (answers.drive != null) {
|
||||
// TODO: balena local makes use of ejectAsync, see below
|
||||
// DO we need this / should we do that here?
|
||||
|
||||
// getDrive = (drive) ->
|
||||
// driveListAsync().then (drives) ->
|
||||
// selectedDrive = _.find(drives, device: drive)
|
||||
|
||||
// if not selectedDrive?
|
||||
// throw new Error("Drive not found: #{drive}")
|
||||
|
||||
// return selectedDrive
|
||||
// if (os.platform() is 'win32') and selectedDrive.mountpoint?
|
||||
// ejectAsync = Promise.promisify(require('removedrive').eject)
|
||||
// return ejectAsync(selectedDrive.mountpoint)
|
||||
|
||||
await umountAsync(answers.drive);
|
||||
await safeUmount(answers.drive);
|
||||
console.info(`You can safely remove ${answers.drive} now`);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2019 Balena Ltd.
|
||||
* Copyright 2019-2021 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -82,6 +82,19 @@ export const drive = flags.string({
|
||||
`,
|
||||
});
|
||||
|
||||
export const driveOrImg = flags.string({
|
||||
char: 'd',
|
||||
description:
|
||||
'path to OS image file (e.g. balena.img) or block device (e.g. /dev/disk2)',
|
||||
});
|
||||
|
||||
export const deviceType = flags.string({
|
||||
description:
|
||||
'device type (Check available types with `balena devices supported`)',
|
||||
char: 't',
|
||||
required: true,
|
||||
});
|
||||
|
||||
export const json: IBooleanFlag<boolean> = flags.boolean({
|
||||
char: 'j',
|
||||
description: 'produce JSON output instead of tabular output',
|
||||
|
@ -579,3 +579,16 @@ export async function awaitInterruptibleTask<
|
||||
process.removeListener('SIGINT', sigintHandler);
|
||||
}
|
||||
}
|
||||
|
||||
/** Check if `drive` is mounted, and if so umount it. No-op on Windows. */
|
||||
export async function safeUmount(drive: string) {
|
||||
if (!drive) {
|
||||
return;
|
||||
}
|
||||
const { isMounted, umount } = await import('umount');
|
||||
const isMountedAsync = promisify(isMounted);
|
||||
if (await isMountedAsync(drive)) {
|
||||
const umountAsync = promisify(umount);
|
||||
await umountAsync(drive);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user