Merge pull request #1966 from balena-io/reduce-bluebird

Remove some bluebird usage
This commit is contained in:
bulldozer-balena[bot] 2020-07-31 11:58:03 +00:00 committed by GitHub
commit 9da7f03b2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 149 additions and 150 deletions

View File

@ -59,13 +59,13 @@ export default class LocalConfigureCmd extends Command {
public async run() { public async run() {
const { args: params } = this.parse<FlagsDef, ArgsDef>(LocalConfigureCmd); const { args: params } = this.parse<FlagsDef, ArgsDef>(LocalConfigureCmd);
const Bluebird = await import('bluebird'); const { promisify } = await import('util');
const path = await import('path'); const path = await import('path');
const umount = await import('umount'); const umount = await import('umount');
const umountAsync = Bluebird.promisify(umount.umount); const umountAsync = promisify(umount.umount);
const isMountedAsync = Bluebird.promisify(umount.isMounted); const isMountedAsync = promisify(umount.isMounted);
const reconfix = await import('reconfix'); const reconfix = await import('reconfix');
const denymount = Bluebird.promisify(await import('denymount')); const denymount = promisify(await import('denymount'));
const Logger = await import('../../utils/logger'); const Logger = await import('../../utils/logger');
const logger = Logger.getLogger(); const logger = Logger.getLogger();

View File

@ -42,10 +42,9 @@ const applicationExpandOptions = {
}; };
let allDeviceTypes; let allDeviceTypes;
const getDeviceTypes = function () { const getDeviceTypes = async function () {
const Bluebird = require('bluebird');
if (allDeviceTypes !== undefined) { if (allDeviceTypes !== undefined) {
return Bluebird.resolve(allDeviceTypes); return allDeviceTypes;
} }
const balena = getBalenaSdk(); const balena = getBalenaSdk();
return balena.models.config return balena.models.config
@ -154,12 +153,11 @@ const selectApplicationCommit = function (releases) {
}); });
}; };
const offerToDisableAutomaticUpdates = function ( const offerToDisableAutomaticUpdates = async function (
application, application,
commit, commit,
pinDevice, pinDevice,
) { ) {
const Bluebird = require('bluebird');
const balena = getBalenaSdk(); const balena = getBalenaSdk();
if ( if (
@ -167,7 +165,7 @@ const offerToDisableAutomaticUpdates = function (
!application.should_track_latest_release || !application.should_track_latest_release ||
pinDevice pinDevice
) { ) {
return Bluebird.resolve(); return;
} }
const message = `\ const message = `\

View File

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import * as Bluebird from 'bluebird';
import * as _ from 'lodash'; import * as _ from 'lodash';
import * as url from 'url'; import * as url from 'url';
import { getBalenaSdk } from '../utils/lazy'; import { getBalenaSdk } from '../utils/lazy';
@ -26,7 +25,7 @@ import { getBalenaSdk } from '../utils/lazy';
* *
* @param {String} callbackUrl - callback url * @param {String} callbackUrl - callback url
* @fulfil {String} - dashboard login url * @fulfil {String} - dashboard login url
* @returns {Bluebird} * @returns {Promise}
* *
* @example * @example
* utils.getDashboardLoginURL('http://127.0.0.1:3000').then (url) -> * utils.getDashboardLoginURL('http://127.0.0.1:3000').then (url) ->
@ -58,15 +57,15 @@ export const getDashboardLoginURL = (callbackUrl: string) => {
* *
* @param {String} token - session token or api key * @param {String} token - session token or api key
* @fulfil {Boolean} - whether the login was successful or not * @fulfil {Boolean} - whether the login was successful or not
* @returns {Bluebird} * @returns {Promise}
* *
* utils.loginIfTokenValid('...').then (loggedIn) -> * utils.loginIfTokenValid('...').then (loggedIn) ->
* if loggedIn * if loggedIn
* console.log('Token is valid!') * console.log('Token is valid!')
*/ */
export const loginIfTokenValid = (token: string) => { export const loginIfTokenValid = async (token: string) => {
if (_.isEmpty(token?.trim())) { if (_.isEmpty(token?.trim())) {
return Bluebird.resolve(false); return false;
} }
const balena = getBalenaSdk(); const balena = getBalenaSdk();

View File

@ -15,7 +15,6 @@
* limitations under the License. * limitations under the License.
*/ */
import { BalenaSDK } from 'balena-sdk'; import { BalenaSDK } from 'balena-sdk';
import * as Bluebird from 'bluebird';
import type * as Dockerode from 'dockerode'; import type * as Dockerode from 'dockerode';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
@ -249,7 +248,7 @@ export async function tarDirectory(
preFinalizeCallback, preFinalizeCallback,
}: TarDirectoryOptions, }: TarDirectoryOptions,
): Promise<import('stream').Readable> { ): Promise<import('stream').Readable> {
(await import('assert')).strict.strictEqual(nogitignore, true); (await import('assert')).strict.equal(nogitignore, true);
const { filterFilesWithDockerignore } = await import('./ignore'); const { filterFilesWithDockerignore } = await import('./ignore');
const { toPosixPath } = (await import('resin-multibuild')).PathUtils; const { toPosixPath } = (await import('resin-multibuild')).PathUtils;
@ -558,30 +557,34 @@ async function performResolution(
}, },
preprocessHook, preprocessHook,
); );
// Do one task at a time (Bluebird.each instead of Bluebird.all) (async () => {
// in order to reduce peak memory usage. Resolves to buildTasks. try {
Bluebird.each(buildTasks, (buildTask) => { // Do one task at a time in order to reduce peak memory usage. Resolves to buildTasks.
// buildStream is falsy for "external" tasks (image pull) for (const buildTask of buildTasks) {
if (!buildTask.buildStream) { // buildStream is falsy for "external" tasks (image pull)
return buildTask; if (!buildTask.buildStream) {
} continue;
// Consume each task.buildStream in order to trigger the }
// resolution events that define fields like: // Consume each task.buildStream in order to trigger the
// task.dockerfile, task.dockerfilePath, // resolution events that define fields like:
// task.projectType, task.resolved // task.dockerfile, task.dockerfilePath,
// This mimics what is currently done in `resin-builder`. // task.projectType, task.resolved
return cloneTarStream(buildTask.buildStream).then( // This mimics what is currently done in `resin-builder`.
(clonedStream: tar.Pack) => { const clonedStream: tar.Pack = await cloneTarStream(
buildTask.buildStream,
);
buildTask.buildStream = clonedStream; buildTask.buildStream = clonedStream;
if (!buildTask.external && !buildTask.resolved) { if (!buildTask.external && !buildTask.resolved) {
throw new ExpectedError( throw new ExpectedError(
`Project type for service "${buildTask.serviceName}" could not be determined. Missing a Dockerfile?`, `Project type for service "${buildTask.serviceName}" could not be determined. Missing a Dockerfile?`,
); );
} }
return buildTask; }
}, resolve(buildTasks);
); } catch (e) {
}).then(resolve, reject); reject(e);
}
})();
}); });
} }

View File

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import type * as BalenaSdk from 'balena-sdk'; import type * as BalenaSdk from 'balena-sdk';
import * as semver from 'balena-semver'; import * as semver from 'balena-semver';
import Bluebird = require('bluebird');
import { getBalenaSdk } from './lazy'; import { getBalenaSdk } from './lazy';
export interface ImgConfig { export interface ImgConfig {
@ -52,7 +51,7 @@ export interface ImgConfig {
}; };
} }
export function generateBaseConfig( export async function generateBaseConfig(
application: BalenaSdk.Application, application: BalenaSdk.Application,
options: { options: {
version: string; version: string;
@ -62,41 +61,44 @@ export function generateBaseConfig(
sshKeys?: string[]; sshKeys?: string[];
}; };
}, },
): Bluebird<ImgConfig> { ): Promise<ImgConfig> {
options = { options = {
...options, ...options,
appUpdatePollInterval: options.appUpdatePollInterval || 10, appUpdatePollInterval: options.appUpdatePollInterval || 10,
}; };
const promise = getBalenaSdk().models.os.getConfig( const config = (await getBalenaSdk().models.os.getConfig(
application.app_name, application.app_name,
options, options,
) as Bluebird<ImgConfig & { apiKey?: string }>; )) as ImgConfig & { apiKey?: string };
return promise.tap((config) => { // os.getConfig always returns a config for an app
// os.getConfig always returns a config for an app delete config.apiKey;
delete config.apiKey;
// merge sshKeys to config, when they have been specified // merge sshKeys to config, when they have been specified
if (options.os && options.os.sshKeys) { if (options.os && options.os.sshKeys) {
// Create config.os object if it does not exist // Create config.os object if it does not exist
config.os = config.os ? config.os : {}; config.os = config.os ? config.os : {};
config.os.sshKeys = config.os.sshKeys config.os.sshKeys = config.os.sshKeys
? [...config.os.sshKeys, ...options.os.sshKeys] ? [...config.os.sshKeys, ...options.os.sshKeys]
: options.os.sshKeys; : options.os.sshKeys;
} }
});
return config;
} }
export function generateApplicationConfig( export async function generateApplicationConfig(
application: BalenaSdk.Application, application: BalenaSdk.Application,
options: { version: string; deviceType?: string }, options: { version: string; deviceType?: string },
) { ) {
return generateBaseConfig(application, options).tap((config) => { const config = await generateBaseConfig(application, options);
if (semver.satisfies(options.version, '<2.7.8')) {
return addApplicationKey(config, application.id); if (semver.satisfies(options.version, '<2.7.8')) {
} await addApplicationKey(config, application.id);
return addProvisioningKey(config, application.id); } else {
}); await addProvisioningKey(config, application.id);
}
return config;
} }
export function generateDeviceConfig( export function generateDeviceConfig(
@ -108,20 +110,20 @@ export function generateDeviceConfig(
) { ) {
return getBalenaSdk() return getBalenaSdk()
.models.application.get(device.belongs_to__application.__id) .models.application.get(device.belongs_to__application.__id)
.then((application) => { .then(async (application) => {
const baseConfigOpts = { const baseConfigOpts = {
...options, ...options,
deviceType: device.device_type, deviceType: device.device_type,
}; };
return generateBaseConfig(application, baseConfigOpts).tap((config) => { const config = await generateBaseConfig(application, baseConfigOpts);
if (
deviceApiKey == null && if (deviceApiKey == null && semver.satisfies(options.version, '<2.0.3')) {
semver.satisfies(options.version, '<2.0.3') await addApplicationKey(config, application.id);
) { } else {
return addApplicationKey(config, application.id); await addDeviceKey(config, device.uuid, deviceApiKey || true);
} }
return addDeviceKey(config, device.uuid, deviceApiKey || true);
}); return config;
}) })
.then((config) => { .then((config) => {
// Associate a device, to prevent the supervisor // Associate a device, to prevent the supervisor
@ -150,18 +152,16 @@ function addProvisioningKey(config: any, applicationNameOrId: string | number) {
}); });
} }
function addDeviceKey( async function addDeviceKey(
config: any, config: any,
uuid: string, uuid: string,
customDeviceApiKey: string | true, customDeviceApiKey: string | true,
) { ) {
return Bluebird.try(() => { if (customDeviceApiKey === true) {
if (customDeviceApiKey === true) { config.deviceApiKey = await getBalenaSdk().models.device.generateDeviceKey(
return getBalenaSdk().models.device.generateDeviceKey(uuid); uuid,
} else { );
return customDeviceApiKey; } else {
} config.deviceApiKey = customDeviceApiKey;
}).tap((deviceApiKey) => { }
config.deviceApiKey = deviceApiKey;
});
} }

View File

@ -16,7 +16,6 @@
*/ */
import * as semver from 'balena-semver'; import * as semver from 'balena-semver';
import * as Bluebird from 'bluebird';
import * as Docker from 'dockerode'; import * as Docker from 'dockerode';
import * as _ from 'lodash'; import * as _ from 'lodash';
import { Composition } from 'resin-compose-parse'; import { Composition } from 'resin-compose-parse';
@ -258,7 +257,7 @@ export async function deployToDevice(opts: DeviceDeployOptions): Promise<void> {
deployOpts: opts, deployOpts: opts,
}); });
const promises: Array<Bluebird<void> | Promise<void>> = [livepush.init()]; const promises: Array<Promise<void>> = [livepush.init()];
// Only show logs if we're not detaching // Only show logs if we're not detaching
if (!opts.detached) { if (!opts.detached) {
const logStream = await api.getLogStream(); const logStream = await api.getLogStream();
@ -298,7 +297,7 @@ function connectToDocker(host: string, port: number): Docker {
return new Docker({ return new Docker({
host, host,
port, port,
Promise: Bluebird as any, Promise: require('bluebird'),
}); });
} }

View File

@ -106,76 +106,75 @@ Implements the same feature as the "docker build --cache-from" option.`,
]); ]);
} }
const generateConnectOpts = function (opts) { const generateConnectOpts = async function (opts) {
const { promises: fs } = require('fs'); const { promises: fs } = await import('fs');
const Bluebird = require('bluebird');
return Bluebird.try(function () { const connectOpts = {};
const connectOpts = {};
// Start with docker-modem defaults which take several env vars into account, // Start with docker-modem defaults which take several env vars into account,
// including DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH, SSH_AUTH_SOCK // including DOCKER_HOST, DOCKER_TLS_VERIFY, DOCKER_CERT_PATH, SSH_AUTH_SOCK
// https://github.com/apocas/docker-modem/blob/v2.1.3/lib/modem.js#L15-L65 // https://github.com/apocas/docker-modem/blob/v2.1.3/lib/modem.js#L15-L65
const Modem = require('docker-modem'); const Modem = await import('docker-modem');
const defaultOpts = new Modem(); const defaultOpts = new Modem();
const optsOfInterest = [ const optsOfInterest = [
'ca', 'ca',
'cert', 'cert',
'key', 'key',
'host', 'host',
'port', 'port',
'socketPath', 'socketPath',
'protocol', 'protocol',
'username', 'username',
'sshAuthAgent', 'sshAuthAgent',
'timeout', 'timeout',
]; ];
for (const opt of optsOfInterest) { for (const opt of optsOfInterest) {
connectOpts[opt] = defaultOpts[opt]; connectOpts[opt] = defaultOpts[opt];
} }
// Now override the default options with any explicit command line options // Now override the default options with any explicit command line options
if (opts.docker != null && opts.dockerHost == null) { if (opts.docker != null && opts.dockerHost == null) {
// good, local docker socket // good, local docker socket
connectOpts.socketPath = opts.docker; connectOpts.socketPath = opts.docker;
delete connectOpts.host; delete connectOpts.host;
delete connectOpts.port; delete connectOpts.port;
} else if (opts.dockerHost != null && opts.docker == null) { } else if (opts.dockerHost != null && opts.docker == null) {
// Good a host is provided, and local socket isn't // Good a host is provided, and local socket isn't
connectOpts.host = opts.dockerHost; connectOpts.host = opts.dockerHost;
connectOpts.port = opts.dockerPort || 2376; connectOpts.port = opts.dockerPort || 2376;
delete connectOpts.socketPath; delete connectOpts.socketPath;
} else if (opts.docker != null && opts.dockerHost != null) { } else if (opts.docker != null && opts.dockerHost != null) {
// Both provided, no obvious way to continue // Both provided, no obvious way to continue
throw new ExpectedError(
"Both a local docker socket and docker host have been provided. Don't know how to continue.",
);
}
// Now need to check if the user wants to connect over TLS
// to the host
// If any are set...
if (opts.ca != null || opts.cert != null || opts.key != null) {
// but not all
if (!(opts.ca != null && opts.cert != null && opts.key != null)) {
throw new ExpectedError( throw new ExpectedError(
"Both a local docker socket and docker host have been provided. Don't know how to continue.", 'You must provide a CA, certificate and key in order to use TLS',
); );
} }
// Now need to check if the user wants to connect over TLS const [ca, cert, key] = await Promise.all([
// to the host fs.readFile(opts.ca, 'utf-8'),
fs.readFile(opts.cert, 'utf-8'),
fs.readFile(opts.key, 'utf-8'),
]);
return _.merge(connectOpts, {
ca,
cert,
key,
});
}
// If any are set... return connectOpts;
if (opts.ca != null || opts.cert != null || opts.key != null) {
// but not all
if (!(opts.ca != null && opts.cert != null && opts.key != null)) {
throw new ExpectedError(
'You must provide a CA, certificate and key in order to use TLS',
);
}
const certBodies = {
ca: fs.readFile(opts.ca, 'utf-8'),
cert: fs.readFile(opts.cert, 'utf-8'),
key: fs.readFile(opts.key, 'utf-8'),
};
return Bluebird.props(certBodies).then((toMerge) =>
_.merge(connectOpts, toMerge),
);
}
return connectOpts;
});
}; };
const parseBuildArgs = function (args) { const parseBuildArgs = function (args) {
@ -231,10 +230,11 @@ export function generateBuildOpts(options) {
* }} options * }} options
* @returns {Promise<import('docker-toolbelt')>} * @returns {Promise<import('docker-toolbelt')>}
*/ */
export function getDocker(options) { export async function getDocker(options) {
return generateConnectOpts(options) const connectOpts = await generateConnectOpts(options);
.then(createClient) const client = createClient(connectOpts);
.tap(ensureDockerSeemsAccessible); await ensureDockerSeemsAccessible(client);
return client;
} }
const getDockerToolbelt = _.once(function () { const getDockerToolbelt = _.once(function () {

View File

@ -20,7 +20,7 @@ declare module 'denymount' {
target: string, target: string,
handler: (cb: typeof callback) => void, handler: (cb: typeof callback) => void,
opts?: { autoMountOnSuccess?: boolean; executablePath?: string }, opts?: { autoMountOnSuccess?: boolean; executablePath?: string },
callback: (err?: any) => void, callback: (err?: Error) => void,
) => void; ) => void;
export = denymount; export = denymount;
} }

View File

@ -22,6 +22,6 @@ declare module 'umount' {
) => void; ) => void;
export const isMounted: ( export const isMounted: (
device: string, device: string,
callback: (err?: Error, isMounted?: boolean) => void, callback: (err: Error | null, isMounted?: boolean) => void,
) => void; ) => void;
} }