chore(xo-server,xo-server-load-balancer): phase out mapToArray (#5662)

Use native `Array#map` or `Object.values` where possible and import directly from `lodash`.

Reasons:
- less dependencies
- more idiomatic
- better example for new code
This commit is contained in:
Julien Fontanet 2021-03-11 15:17:28 +01:00 committed by GitHub
parent 27abee0850
commit aff874c68a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 75 additions and 92 deletions

View File

@ -1,5 +1,5 @@
import { createSchedule } from '@xen-orchestra/cron'
import { intersection, map as mapToArray, uniq } from 'lodash'
import { intersection, uniq } from 'lodash'
import DensityPlan from './density-plan'
import PerformancePlan from './performance-plan'
@ -140,7 +140,7 @@ class LoadBalancerPlugin {
_executePlans() {
debug('Execute plans!')
return Promise.all(mapToArray(this._plans, plan => plan.execute()))
return Promise.all(this._plans.map(plan => plan.execute()))
}
}

View File

@ -1,4 +1,4 @@
import { filter, find, map as mapToArray } from 'lodash'
import { filter, find } from 'lodash'
import Plan from './plan'
import { debug } from './utils'
@ -33,13 +33,10 @@ export default class PerformancePlan extends Plan {
// Try to power on a hosts set.
try {
await Promise.all(
mapToArray(
filter(this._getHosts({ powerState: 'Halted' }), host => host.powerOnMode !== ''),
host => {
const { id } = host
return this.xo.getXapi(id).powerOnHost(id)
}
)
filter(this._getHosts({ powerState: 'Halted' }), host => host.powerOnMode !== '').map(host => {
const { id } = host
return this.xo.getXapi(id).powerOnHost(id)
})
)
} catch (error) {
console.error(error)

View File

@ -212,7 +212,7 @@ export default class Plan {
const hostsStats = {}
await Promise.all(
mapToArray(hosts, host =>
hosts.map(host =>
this.xo.getXapiHostStats(host, granularity).then(hostStats => {
hostsStats[host.id] = {
nPoints: hostStats.stats.cpus[0].length,
@ -230,7 +230,7 @@ export default class Plan {
const vmsStats = {}
await Promise.all(
mapToArray(vms, vm =>
vms.map(vm =>
this.xo.getXapiVmStats(vm, granularity).then(vmStats => {
vmsStats[vm.id] = {
nPoints: vmStats.stats.cpus[0].length,

View File

@ -1,5 +1,4 @@
import xapiObjectToXo from '../xapi-object-to-xo'
import { mapToArray } from '../utils'
export function getBondModes() {
return ['balance-slb', 'active-backup', 'lacp']
@ -37,7 +36,7 @@ export async function createBonded({ pool, name, description, pifs, mtu = 1500,
return this.getXapi(pool).createBondedNetwork({
name,
description,
pifIds: mapToArray(pifs, pif => this.getObject(pif, 'PIF')._xapiId),
pifIds: pifs.map(pif => this.getObject(pif, 'PIF')._xapiId),
mtu: +mtu,
bondMode,
})

View File

@ -1,6 +1,6 @@
import { forbiddenOperation, invalidParameters } from 'xo-common/api-errors'
import { isEmpty } from 'lodash'
import { getUserPublicProperties, mapToArray } from '../utils'
import { getUserPublicProperties } from '../utils'
// ===================================================================
@ -49,7 +49,7 @@ export async function getAll() {
const users = await this.getAllUsers()
// Filters out private properties.
return mapToArray(users, getUserPublicProperties)
return users.map(getUserPublicProperties)
}
getAll.description = 'returns all the existing users'

View File

@ -1,6 +1,6 @@
import Collection from '../collection/redis'
import Model from '../model'
import { forEach, mapToArray, multiKeyHash } from '../utils'
import { forEach, multiKeyHash } from '../utils'
// ===================================================================
@ -54,11 +54,11 @@ export class Acls extends Collection {
})
if (toUpdate.length) {
// Removes all existing entries.
await this.remove(mapToArray(toUpdate, 'id'))
await this.remove(toUpdate.map(_ => _.id))
// Compute the new ids (new hashes).
await Promise.all(
mapToArray(toUpdate, acl =>
toUpdate.map(acl =>
multiKeyHash(acl.subject, acl.object, acl.action).then(id => {
acl.id = id
})

View File

@ -223,7 +223,6 @@ export { default as forEach } from 'lodash/forEach'
export { default as isEmpty } from 'lodash/isEmpty'
export { default as isInteger } from 'lodash/isInteger'
export { default as isObject } from 'lodash/isObject'
export { default as mapToArray } from 'lodash/map'
// -------------------------------------------------------------------

View File

@ -1,7 +1,7 @@
import * as sensitiveValues from './sensitive-values'
import ensureArray from './_ensureArray'
import { extractIpFromVmNetworks } from './_extractIpFromVmNetworks'
import { extractProperty, forEach, isEmpty, mapFilter, mapToArray, parseXml } from './utils'
import { extractProperty, forEach, isEmpty, mapFilter, parseXml } from './utils'
import { getVmDomainType, isHostRunning, isVmRunning, parseDateTime } from './xapi'
import { useUpdateSystem } from './xapi/utils'
@ -44,7 +44,7 @@ function link(obj, prop, idField = '$id') {
}
if (Array.isArray(dynamicValue)) {
return mapToArray(dynamicValue, idField)
return dynamicValue.map(_ => _[idField])
}
return dynamicValue[idField]

View File

@ -5,6 +5,7 @@ import concurrency from 'limit-concurrency-decorator'
import createLogger from '@xen-orchestra/log'
import deferrable from 'golike-defer'
import fatfs from 'fatfs'
import mapToArray from 'lodash/map'
import mixin from '@xen-orchestra/mixin'
import ms from 'ms'
import synchronized from 'decorator-synchronized'
@ -22,18 +23,7 @@ import { satisfies as versionSatisfies } from 'semver'
import createSizeStream from '../size-stream'
import ensureArray from '../_ensureArray'
import fatfsBuffer, { init as fatfsBufferInit } from '../fatfs-buffer'
import {
camelToSnakeCase,
forEach,
map,
mapToArray,
pAll,
parseSize,
pDelay,
pFinally,
promisifyAll,
pSettle,
} from '../utils'
import { camelToSnakeCase, forEach, map, pAll, parseSize, pDelay, pFinally, promisifyAll, pSettle } from '../utils'
import mixins from './mixins'
import OTHER_CONFIG_TEMPLATE from './other-config-template'
@ -75,7 +65,7 @@ export const IPV6_CONFIG_MODES = ['None', 'DHCP', 'Static', 'Autoconf']
// ===================================================================
@mixin(mapToArray(mixins))
@mixin(Object.values(mixins))
export default class Xapi extends XapiBase {
constructor({
guessVhdSizeOnImport,
@ -261,7 +251,8 @@ export default class Xapi extends XapiBase {
const vms = host.$resident_VMs
log.debug(`Emergency shutdown: ${host.name_label}`)
await pSettle(
mapToArray(vms, vm => {
// eslint-disable-next-line array-callback-return
vms.map(vm => {
if (!vm.is_control_domain) {
return this.callAsync('VM.suspend', vm.$ref)
}
@ -1089,7 +1080,7 @@ export default class Xapi extends XapiBase {
const defaultNetworkRef = find(host.$PIFs, pif => pif.management).$network.$ref
// Add snapshots' VIFs which VM has no VIFs on these devices
const vmVifs = vm.$VIFs
const vifDevices = new Set(mapToArray(vmVifs, 'device'))
const vifDevices = new Set(vmVifs.map(_ => _.device))
const vifs = flatMap(vm.$snapshots, '$VIFs')
.filter(vif => !vifDevices.has(vif.device))
.concat(vmVifs)
@ -1182,14 +1173,16 @@ export default class Xapi extends XapiBase {
// No shared SR available: find an available local SR on each host
return Promise.all(
mapToArray(
hosts,
hosts.map(
deferrable(async ($defer, host) => {
// pipe stream synchronously to several PassThroughs to be able to pipe them asynchronously later
const pt = stream.pipe(new PassThrough())
pt.length = stream.length
const sr = find(mapToArray(host.$PBDs, '$SR'), isSrAvailable)
const sr = find(
host.$PBDs.map(_ => _.$SR),
isSrAvailable
)
if (!sr) {
throw new Error('no SR available to store installation file')
@ -1774,7 +1767,7 @@ export default class Xapi extends XapiBase {
// TODO: remove when no longer used.
async destroyVbdsFromVm(vmId) {
await Promise.all(
mapToArray(this.getObject(vmId).$VBDs, async vbd => {
this.getObject(vmId).$VBDs.map(async vbd => {
await this.disconnectVbd(vbd.$ref)::ignoreErrors()
return this.call('VBD.destroy', vbd.$ref)
})
@ -1973,13 +1966,12 @@ export default class Xapi extends XapiBase {
wasAttached[pif.host] = pif.currently_attached
})
const vlans = uniq(mapToArray(pifs, pif => pif.VLAN_master_of))
await Promise.all(mapToArray(vlans, vlan => Ref.isNotEmpty(vlan) && this.callAsync('VLAN.destroy', vlan)))
const vlans = uniq(pifs.map(pif => pif.VLAN_master_of))
await Promise.all(vlans.map(vlan => Ref.isNotEmpty(vlan) && this.callAsync('VLAN.destroy', vlan)))
const newPifs = await this.call('pool.create_VLAN_from_PIF', physPif.$ref, pif.network, asInteger(vlan))
await Promise.all(
mapToArray(
newPifs,
newPifs.map(
pifRef => !wasAttached[this.getObject(pifRef).host] && this.callAsync('PIF.unplug', pifRef)::ignoreErrors()
)
)
@ -2009,15 +2001,15 @@ export default class Xapi extends XapiBase {
const network = this.getObject(networkId)
const pifs = network.$PIFs
const vlans = uniq(mapToArray(pifs, pif => pif.VLAN_master_of))
await Promise.all(mapToArray(vlans, vlan => Ref.isNotEmpty(vlan) && this.callAsync('VLAN.destroy', vlan)))
const vlans = uniq(pifs.map(pif => pif.VLAN_master_of))
await Promise.all(vlans.map(vlan => Ref.isNotEmpty(vlan) && this.callAsync('VLAN.destroy', vlan)))
const bonds = uniq(flatten(mapToArray(pifs, pif => pif.bond_master_of)))
await Promise.all(mapToArray(bonds, bond => this.call('Bond.destroy', bond)))
const bonds = uniq(flatten(pifs.map(pif => pif.bond_master_of)))
await Promise.all(bonds.map(bond => this.call('Bond.destroy', bond)))
const tunnels = filter(this.objects.all, { $type: 'tunnel' })
await Promise.all(
map(pifs, async pif => {
pifs.map(async pif => {
const tunnel = find(tunnels, { access_PIF: pif.$ref })
if (tunnel != null) {
await this.callAsync('tunnel.destroy', tunnel.$ref)

View File

@ -7,7 +7,7 @@ import { timeout } from 'promise-toolbox'
import ensureArray from '../../_ensureArray'
import { debounceWithKey } from '../../_pDebounceWithKey'
import { forEach, mapFilter, mapToArray, parseXml } from '../../utils'
import { forEach, mapFilter, parseXml } from '../../utils'
import { extractOpaqueRef, parseDateTime, useUpdateSystem } from '../utils'
@ -76,8 +76,8 @@ export default {
url: patch['patch-url'],
id: patch.uuid,
uuid: patch.uuid,
conflicts: mapToArray(ensureArray(patch.conflictingpatches), patch => patch.conflictingpatch.uuid),
requirements: mapToArray(ensureArray(patch.requiredpatches), patch => patch.requiredpatch.uuid),
conflicts: ensureArray(patch.conflictingpatches).map(patch => patch.conflictingpatch.uuid),
requirements: ensureArray(patch.requiredpatches).map(patch => patch.requiredpatch.uuid),
paid: patch['update-stream'] === 'premium',
upgrade: /^(XS|CH)\d{2,}$/.test(patch['name-label']),
// TODO: what does it mean, should we handle it?

View File

@ -2,13 +2,11 @@ import createLogger from '@xen-orchestra/log'
import defer from 'golike-defer'
import { filter, forEach, groupBy } from 'lodash'
import { mapToArray } from '../../utils'
const log = createLogger('xo:storage')
export default {
_connectAllSrPbds(sr) {
return Promise.all(mapToArray(sr.$PBDs, pbd => this._plugPbd(pbd)))
return Promise.all(sr.$PBDs.map(pbd => this._plugPbd(pbd)))
},
async connectAllSrPbds(id) {
@ -16,7 +14,7 @@ export default {
},
_disconnectAllSrPbds(sr) {
return Promise.all(mapToArray(sr.$PBDs, pbd => this._unplugPbd(pbd)))
return Promise.all(sr.$PBDs.map(pbd => this._unplugPbd(pbd)))
},
async disconnectAllSrPbds(id) {

View File

@ -1,9 +1,9 @@
import deferrable from 'golike-defer'
import { find, gte, includes, isEmpty, lte, mapValues, noop } from 'lodash'
import { find, gte, includes, isEmpty, lte, map as mapToArray, mapValues, noop } from 'lodash'
import { cancelable, ignoreErrors, pCatch } from 'promise-toolbox'
import { Ref } from 'xen-api'
import { forEach, mapToArray, parseSize } from '../../utils'
import { forEach, parseSize } from '../../utils'
import { extractOpaqueRef, isVmHvm, isVmRunning, makeEditObject } from '../utils'
@ -195,7 +195,7 @@ export default {
}
// Destroys the VIFs cloned from the template.
await Promise.all(mapToArray(vm.$VIFs, vif => this._deleteVif(vif)))
await Promise.all(vm.$VIFs.map(vif => this._deleteVif(vif)))
// Creates the VIFs specified by the user.
if (vifs) {

View File

@ -6,7 +6,7 @@ import pickBy from 'lodash/pickBy'
import { utcParse } from 'd3-time-format'
import { satisfies as versionSatisfies } from 'semver'
import { camelToSnakeCase, forEach, isInteger, map, mapFilter, mapToArray, noop } from '../utils'
import { camelToSnakeCase, forEach, isInteger, map, mapFilter, noop } from '../utils'
// ===================================================================
@ -168,7 +168,7 @@ export const makeEditObject = specs => {
throw new Error('must be an array, a function or a string')
}
set = mapToArray(set, normalizeSet)
set = set.map(normalizeSet)
const { length } = set
if (!length) {
@ -180,7 +180,7 @@ export const makeEditObject = specs => {
}
return function (value, object) {
return Promise.all(mapToArray(set, set => set.call(this, value, object)))
return Promise.all(set.map(set => set.call(this, value, object)))
}
}
@ -296,7 +296,7 @@ export const makeEditObject = specs => {
})
if (cbs.length) {
return () => Promise.all(mapToArray(cbs, cb => cb())).then(cb)
return () => Promise.all(cbs.map(cb => cb())).then(cb)
}
}
@ -309,7 +309,7 @@ export const makeEditObject = specs => {
await checkLimits(limits, object)
}
return Promise.all(mapToArray(cbs, cb => cb())).then(noop)
return Promise.all(cbs.map(cb => cb())).then(noop)
}
}

View File

@ -10,7 +10,7 @@ import { decorateWith } from '@vates/decorate-with'
import { satisfies as versionSatisfies } from 'semver'
import { utcFormat } from 'd3-time-format'
import { basename, dirname } from 'path'
import { escapeRegExp, filter, find, includes, once, range, sortBy } from 'lodash'
import { escapeRegExp, filter, find, includes, map as mapToArray, once, range, sortBy } from 'lodash'
import { chainVhd, createSyntheticStream as createVhdReadStream, mergeVhd } from 'vhd-lib'
import createSizeStream from '../size-stream'
@ -21,7 +21,6 @@ import {
forEach,
getFirstPropertyName,
mapFilter,
mapToArray,
pFinally,
pFromCallback,
pSettle,
@ -286,7 +285,7 @@ export default class {
const deltaBackups = filter(files, isDeltaBackup)
backups.push(
...mapToArray(deltaBackups, deltaBackup => {
...deltaBackups.map(deltaBackup => {
return `${deltaDir}/${getDeltaBackupNameWithoutExt(deltaBackup)}`
})
)
@ -602,7 +601,7 @@ export default class {
const fullVdisRequired = []
await Promise.all(
mapToArray(vm.$VBDs, async vbd => {
vm.$VBDs.map(async vbd => {
if (!vbd.VDI || vbd.type !== 'Disk') {
return
}
@ -686,7 +685,7 @@ export default class {
// Here we have a completed backup. We can merge old vdis.
await Promise.all(
mapToArray(vdiBackups, vdiBackup => {
vdiBackups.map(vdiBackup => {
const backupName = vdiBackup.value().path
const backupDirectory = backupName.slice(0, backupName.lastIndexOf('/'))
const backupDir = `${dir}/${backupDirectory}`
@ -996,7 +995,7 @@ export default class {
const entriesMap = {}
await Promise.all(
mapToArray(entries, async name => {
entries.map(async name => {
const stats = await pFromCallback(cb => stat(`${path}/${name}`, cb))::ignoreErrors()
if (stats) {
entriesMap[stats.isDirectory() ? `${name}/` : name] = {}
@ -1015,7 +1014,7 @@ export default class {
partition.unmount()
}
}
return mapToArray(paths, path => {
return paths.map(path => {
++i
return createReadStream(resolveSubpath(partition.path, path)).once('end', onEnd)
})

View File

@ -7,6 +7,7 @@ import highland from 'highland'
import includes from 'lodash/includes'
import isObject from 'lodash/isObject'
import keys from 'lodash/keys'
import mapToArray from 'lodash/map'
import mapValues from 'lodash/mapValues'
import pick from 'lodash/pick'
import remove from 'lodash/remove'
@ -14,7 +15,7 @@ import synchronized from 'decorator-synchronized'
import { noSuchObject } from 'xo-common/api-errors'
import { fromCallback } from 'promise-toolbox'
import { forEach, generateUnsecureToken, isEmpty, lightSet, mapToArray, streamToArray, throwFn } from '../utils'
import { forEach, generateUnsecureToken, isEmpty, lightSet, streamToArray, throwFn } from '../utils'
// ===================================================================
@ -44,7 +45,7 @@ export default class IpPools {
xo.addConfigManager(
'ipPools',
() => this.getAllIpPools(),
ipPools => Promise.all(mapToArray(ipPools, ipPool => this._save(ipPool)))
ipPools => Promise.all(ipPools.map(ipPool => this._save(ipPool)))
)
})
}
@ -67,7 +68,7 @@ export default class IpPools {
if (await store.has(id)) {
await Promise.all(
mapToArray(await this._xo.getAllResourceSets(), async set => {
(await this._xo.getAllResourceSets()).map(async set => {
await this._xo.removeLimitFromResourceSet(`ipPool:${id}`, set.id)
return this._xo.removeIpPoolFromResourceSet(id, set.id)
})
@ -93,7 +94,7 @@ export default class IpPools {
const user = await this._xo.getUser(userId)
if (user.permission !== 'admin') {
const resourceSets = await this._xo.getAllResourceSets(userId)
const ipPools = lightSet(flatten(mapToArray(resourceSets, 'ipPools')))
const ipPools = lightSet(flatten(resourceSets.map(_ => _.ipPools)))
filter = ({ id }) => ipPools.has(id)
}
}

View File

@ -8,7 +8,6 @@ import emitAsync from '@xen-orchestra/emit-async'
import { CancelToken, ignoreErrors } from 'promise-toolbox'
import { defer } from 'golike-defer'
import { map as mapToArray } from 'lodash'
import { noSuchObject } from 'xo-common/api-errors'
import Collection from '../../collection/redis'
@ -156,7 +155,7 @@ export default class Jobs {
xo.addConfigManager(
'jobs',
() => jobsDb.get(),
jobs => Promise.all(mapToArray(jobs, job => jobsDb.save(job))),
jobs => Promise.all(jobs.map(job => jobsDb.save(job))),
['users']
)
})
@ -395,7 +394,7 @@ export default class Jobs {
}
async runJobSequence(idSequence: Array<string>, schedule?: Schedule, data?: any) {
const jobs = await Promise.all(mapToArray(idSequence, id => this.getJob(id)))
const jobs = await Promise.all(idSequence.map(id => this.getJob(id)))
for (const job of jobs) {
await this._runJob(job, schedule, data)

View File

@ -1,10 +1,10 @@
import Ajv from 'ajv'
import createLogger from '@xen-orchestra/log'
import mapToArray from 'lodash/map'
import { invalidParameters, noSuchObject } from 'xo-common/api-errors'
import * as sensitiveValues from '../sensitive-values'
import { PluginsMetadata } from '../models/plugin-metadata'
import { mapToArray } from '../utils'
// ===================================================================
@ -26,7 +26,7 @@ export default class {
xo.addConfigManager(
'plugins',
() => this._pluginsMetadata.get(),
plugins => Promise.all(mapToArray(plugins, plugin => this._pluginsMetadata.save(plugin)))
plugins => Promise.all(plugins.map(plugin => this._pluginsMetadata.save(plugin)))
)
})
}

View File

@ -7,7 +7,6 @@ import { noSuchObject } from 'xo-common/api-errors'
import * as sensitiveValues from '../sensitive-values'
import patch from '../patch'
import { mapToArray } from '../utils'
import { Remotes } from '../models/remote'
// ===================================================================
@ -34,7 +33,7 @@ export default class {
xo.addConfigManager(
'remotes',
() => this._remotes.get(),
remotes => Promise.all(mapToArray(remotes, remote => this._remotes.update(remote)))
remotes => Promise.all(remotes.map(remote => this._remotes.update(remote)))
)
const remotes = await this._remotes.get()

View File

@ -70,7 +70,7 @@ export default class {
xo.addConfigManager(
'resourceSets',
() => this.getAllResourceSets(),
resourceSets => Promise.all(mapToArray(resourceSets, resourceSet => this._save(resourceSet))),
resourceSets => Promise.all(resourceSets.map(resourceSet => this._save(resourceSet))),
['groups', 'users']
)

View File

@ -7,7 +7,7 @@ import { invalidCredentials, noSuchObject } from 'xo-common/api-errors'
import * as XenStore from '../_XenStore'
import { Groups } from '../models/group'
import { Users } from '../models/user'
import { forEach, isEmpty, lightSet, mapToArray } from '../utils'
import { forEach, isEmpty, lightSet } from '../utils'
// ===================================================================
@ -39,7 +39,7 @@ export default class {
xo.addConfigManager(
'groups',
() => groupsDb.get(),
groups => Promise.all(mapToArray(groups, group => groupsDb.save(group))),
groups => Promise.all(groups.map(group => groupsDb.save(group))),
['users']
)
xo.addConfigManager(
@ -47,11 +47,11 @@ export default class {
() => usersDb.get(),
users =>
Promise.all(
mapToArray(users, async user => {
users.map(async user => {
const userId = user.id
const conflictUsers = await usersDb.get({ email: user.email })
if (!isEmpty(conflictUsers)) {
await Promise.all(mapToArray(conflictUsers, ({ id }) => id !== userId && this.deleteUser(id)))
await Promise.all(conflictUsers.map(({ id }) => id !== userId && this.deleteUser(id)))
}
return usersDb.save(user)
})
@ -425,8 +425,8 @@ export default class {
const saveUser = ::this._users.save
await Promise.all([
Promise.all(mapToArray(newUsers, saveUser)),
Promise.all(mapToArray(oldUsers, saveUser)),
Promise.all(newUsers.map(saveUser)),
Promise.all(oldUsers.map(saveUser)),
this._groups.save(group),
])
}

View File

@ -6,7 +6,7 @@ import { createClient as createRedisClient } from 'redis'
import { createDebounceResource } from '@vates/disposable/debounceResource'
import { EventEmitter } from 'events'
import { noSuchObject } from 'xo-common/api-errors'
import { forEach, includes, isEmpty, iteratee, map as mapToArray, stubTrue } from 'lodash'
import { forEach, includes, isEmpty, iteratee, stubTrue } from 'lodash'
import { parseDuration } from '@vates/parse-duration'
import mixins from './xo-mixins'
@ -17,7 +17,7 @@ import { generateToken, noop } from './utils'
const log = createLogger('xo:xo')
@mixin(mapToArray(mixins))
@mixin(Object.values(mixins))
export default class Xo extends EventEmitter {
constructor(config) {
super()